Frank-Rainer Grahl 8 months ago
parent
commit
876f5b09e1
52 changed files with 5610 additions and 80846 deletions
  1. 0 0
      frg/work-js/mozilla-release/patches/1401146-58a1.patch
  2. 52 0
      frg/work-js/mozilla-release/patches/1441098-1-62a1.patch
  3. 188 0
      frg/work-js/mozilla-release/patches/1441098-2-62a1.patch
  4. 293 0
      frg/work-js/mozilla-release/patches/1441098-3-62a1.patch
  5. 37 0
      frg/work-js/mozilla-release/patches/1441098-4-62a1.patch
  6. 0 0
      frg/work-js/mozilla-release/patches/1460381-3-62a1.patch
  7. 83 0
      frg/work-js/mozilla-release/patches/1464758-62a1.patch
  8. 170 0
      frg/work-js/mozilla-release/patches/1466363-62a1.patch
  9. 45 0
      frg/work-js/mozilla-release/patches/1466487-62a1.patch
  10. 95 0
      frg/work-js/mozilla-release/patches/1466893-1-62a1.patch
  11. 110 0
      frg/work-js/mozilla-release/patches/1466893-2-62a1.patch
  12. 100 0
      frg/work-js/mozilla-release/patches/1468792-62a1.patch
  13. 183 0
      frg/work-js/mozilla-release/patches/1471134-1-63a1.patch
  14. 177 0
      frg/work-js/mozilla-release/patches/1471134-2-63a1.patch
  15. 221 0
      frg/work-js/mozilla-release/patches/1471134-3-63a1.patch
  16. 276 0
      frg/work-js/mozilla-release/patches/1471134-4-63a1.patch
  17. 190 0
      frg/work-js/mozilla-release/patches/1471134-5-63a1.patch
  18. 610 0
      frg/work-js/mozilla-release/patches/1478503-63a1.patch
  19. 121 0
      frg/work-js/mozilla-release/patches/1480963-63a1.patch
  20. 47 0
      frg/work-js/mozilla-release/patches/1481032-63a1.patch
  21. 0 0
      frg/work-js/mozilla-release/patches/1485698-63a1.patch
  22. 132 0
      frg/work-js/mozilla-release/patches/1486173-1-63a1.patch
  23. 110 0
      frg/work-js/mozilla-release/patches/1486173-2-63a1.patch
  24. 69 0
      frg/work-js/mozilla-release/patches/1486173-3-63a1.patch
  25. 612 0
      frg/work-js/mozilla-release/patches/1488698-2-PARTIAL-biginttype-64a1.patch
  26. 279 0
      frg/work-js/mozilla-release/patches/1490387-1-64a1.patch
  27. 84 0
      frg/work-js/mozilla-release/patches/1490387-2-64a1.patch
  28. 904 0
      frg/work-js/mozilla-release/patches/1490387-3-64a1.patch
  29. 392 0
      frg/work-js/mozilla-release/patches/1492669-65a1.patch
  30. 0 360
      frg/work-js/mozilla-release/patches/L-1429656-59a1.patch
  31. 0 143
      frg/work-js/mozilla-release/patches/L-1430299-59a1.patch
  32. 0 1086
      frg/work-js/mozilla-release/patches/L-1535226-68a1.patch
  33. 0 2679
      frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-2-buildit-25318-rebase.patch
  34. 0 17285
      frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-2-buildit-25318.patch
  35. 0 63
      frg/work-js/mozilla-release/patches/bbb.patch
  36. 0 3043
      frg/work-js/mozilla-release/patches/mozilla-central-push_421127.patch
  37. 0 60
      frg/work-js/mozilla-release/patches/mozilla-central-push_422049.patch
  38. 0 55
      frg/work-js/mozilla-release/patches/mozilla-central-push_422050.patch
  39. 0 38
      frg/work-js/mozilla-release/patches/mozilla-central-push_422053.patch
  40. 0 149
      frg/work-js/mozilla-release/patches/mozilla-central-push_422054.patch
  41. 0 38
      frg/work-js/mozilla-release/patches/mozilla-central-push_422055.patch
  42. 0 84
      frg/work-js/mozilla-release/patches/mozilla-central-push_423356.patch
  43. 0 84
      frg/work-js/mozilla-release/patches/mozilla-central-push_423358.patch
  44. 0 1293
      frg/work-js/mozilla-release/patches/mozilla-central_419570.patch
  45. 0 673
      frg/work-js/mozilla-release/patches/mozilla-central_419571.patch
  46. 0 169
      frg/work-js/mozilla-release/patches/mozilla-central_419572.patch
  47. 0 116
      frg/work-js/mozilla-release/patches/mozilla-central_419573.patch
  48. 0 37586
      frg/work-js/mozilla-release/patches/mozilla-central_476624.patch
  49. 0 13112
      frg/work-js/mozilla-release/patches/mozilla-central_480696.patch
  50. 0 2355
      frg/work-js/mozilla-release/patches/mozilla-central_489301.patch
  51. 0 323
      frg/work-js/mozilla-release/patches/rebase-25318.patch
  52. 30 52
      frg/work-js/mozilla-release/patches/series

+ 0 - 0
frg/work-js/mozilla-release/patches/L-mozilla-release58_435910.patch → frg/work-js/mozilla-release/patches/1401146-58a1.patch


+ 52 - 0
frg/work-js/mozilla-release/patches/1441098-1-62a1.patch

@@ -0,0 +1,52 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1529511000 -10800
+#      Wed Jun 20 19:10:00 2018 +0300
+# Node ID f87f53656ed51696c9b00b794f8718313f7e2721
+# Parent  f84b2e8eaa8ed58d2e5e9777eac4eb37786d34b1
+bug 1441098 - Part 1: Add BigInt support in BufferGrayRootsTracer. r=sfink
+
+This class is used for tracing DOM objects.
+
+diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp
+--- a/js/src/gc/RootMarking.cpp
++++ b/js/src/gc/RootMarking.cpp
+@@ -460,16 +460,19 @@ class BufferGrayRootsTracer final : publ
+ {
+     // Set to false if we OOM while buffering gray roots.
+     bool bufferingGrayRootsFailed;
+ 
+     void onObjectEdge(JSObject** objp) override { bufferRoot(*objp); }
+     void onStringEdge(JSString** stringp) override { bufferRoot(*stringp); }
+     void onScriptEdge(JSScript** scriptp) override { bufferRoot(*scriptp); }
+     void onSymbolEdge(JS::Symbol** symbolp) override { bufferRoot(*symbolp); }
++#ifdef ENABLE_BIGINT
++    void onBigIntEdge(JS::BigInt** bip) override { bufferRoot(*bip); }
++#endif
+ 
+     void onChild(const JS::GCCellPtr& thing) override {
+         MOZ_CRASH("Unexpected gray root kind");
+     }
+ 
+     template <typename T> inline void bufferRoot(T* thing);
+ 
+   public:
+@@ -520,17 +523,17 @@ js::gc::GCRuntime::bufferGrayRoots()
+ 
+ template <typename T>
+ inline void
+ BufferGrayRootsTracer::bufferRoot(T* thing)
+ {
+     MOZ_ASSERT(JS::CurrentThreadIsHeapBusy());
+     MOZ_ASSERT(thing);
+     // Check if |thing| is corrupt by calling a method that touches the heap.
+-    MOZ_ASSERT(thing->getTraceKind() <= JS::TraceKind::Null);
++    MOZ_ASSERT(thing->getTraceKind() != JS::TraceKind(0xff));
+ 
+     TenuredCell* tenured = &thing->asTenured();
+ 
+     // This is run from a helper thread while the mutator is paused so we have
+     // to use *FromAnyThread methods here.
+     Zone* zone = tenured->zoneFromAnyThread();
+     if (zone->isCollectingFromAnyThread()) {
+         // See the comment on SetMaybeAliveFlag to see why we only do this for

+ 188 - 0
frg/work-js/mozilla-release/patches/1441098-2-62a1.patch

@@ -0,0 +1,188 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1529511000 -10800
+#      Wed Jun 20 19:10:00 2018 +0300
+# Node ID 940e6648c1f24868b5017f8fd4ed5b9a105bb848
+# Parent  f87f53656ed51696c9b00b794f8718313f7e2721
+bug 1441098 - Part 2: Define BigInt serialization methods. r=sfink
+
+writeBytes serializes a BigInt value as a little-endian byte sequence,
+ignoring its sign. createFromBytes can be used to deserialize the output
+of writeBytes.
+
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -97,16 +97,39 @@ BigInt::createFromBoolean(JSContext* cx,
+ {
+     BigInt* x = Allocate<BigInt>(cx);
+     if (!x)
+         return nullptr;
+     mpz_init_set_ui(x->num_, b);
+     return x;
+ }
+ 
++BigInt*
++BigInt::createFromBytes(JSContext* cx, int sign, void* bytes, size_t nbytes)
++{
++    BigInt* x = Allocate<BigInt>(cx);
++    if (!x)
++        return nullptr;
++    // Initialize num_ to zero before calling mpz_import.
++    mpz_init(x->num_);
++
++    if (nbytes == 0)
++        return x;
++
++    mpz_import(x->num_, nbytes,
++               -1, // order: least significant word first
++               1, // size: one byte per "word"
++               0, // endianness: native
++               0, // nail bits: none; use full words
++               bytes);
++    if (sign < 0)
++        mpz_neg(x->num_, x->num_);
++    return x;
++}
++
+ // BigInt proposal section 5.1.1
+ static bool
+ IsInteger(double d)
+ {
+     // Step 1 is an assertion checked by the caller.
+     // Step 2.
+     if (!mozilla::IsFinite(d))
+         return false;
+@@ -289,16 +312,41 @@ js::StringToBigInt(JSContext* cx, Handle
+         }
+     }
+ 
+     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+                               JSMSG_BIGINT_INVALID_SYNTAX);
+     return nullptr;
+ }
+ 
++size_t
++BigInt::byteLength(BigInt* x)
++{
++    if (mpz_sgn(x->num_) == 0)
++        return 0;
++    return JS_HOWMANY(mpz_sizeinbase(x->num_, 2), 8);
++}
++
++void
++BigInt::writeBytes(BigInt* x, RangedPtr<uint8_t> buffer)
++{
++#ifdef DEBUG
++    // Check that the buffer being filled is large enough to hold the
++    // integer we're writing. The result of the RangedPtr addition is
++    // restricted to the buffer's range.
++    size_t reprSize = byteLength(x);
++    MOZ_ASSERT(buffer + reprSize, "out of bounds access to buffer");
++#endif
++
++    size_t count;
++    // cf. mpz_import parameters in createFromBytes, above.
++    mpz_export(buffer.get(), &count, -1, 1, 0, 0, x->num_);
++    MOZ_ASSERT(count == reprSize);
++}
++
+ void
+ BigInt::finalize(js::FreeOp* fop)
+ {
+     mpz_clear(num_);
+ }
+ 
+ JSAtom*
+ js::BigIntToAtom(JSContext* cx, BigInt* bi)
+@@ -310,16 +358,22 @@ js::BigIntToAtom(JSContext* cx, BigInt* 
+ }
+ 
+ bool
+ BigInt::toBoolean()
+ {
+     return mpz_sgn(num_) != 0;
+ }
+ 
++int8_t
++BigInt::sign()
++{
++    return mpz_sgn(num_);
++}
++
+ js::HashNumber
+ BigInt::hash()
+ {
+     const mp_limb_t* limbs = mpz_limbs_read(num_);
+     size_t limbCount = mpz_size(num_);
+     uint32_t hash = mozilla::HashBytes(limbs, limbCount * sizeof(mp_limb_t));
+     hash = mozilla::AddToHash(hash, mpz_sgn(num_));
+     return hash;
+diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
+--- a/js/src/vm/BigIntType.h
++++ b/js/src/vm/BigIntType.h
+@@ -3,16 +3,17 @@
+  * This Source Code Form is subject to the terms of the Mozilla Public
+  * License, v. 2.0. If a copy of the MPL was not distributed with this
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ 
+ #ifndef vm_BigIntType_h
+ #define vm_BigIntType_h
+ 
+ #include "mozilla/Range.h"
++#include "mozilla/RangedPtr.h"
+ 
+ #include <gmp.h>
+ 
+ #include "gc/Barrier.h"
+ #include "gc/GC.h"
+ #include "gc/Heap.h"
+ #include "js/AllocPolicy.h"
+ #include "js/GCHashTable.h"
+@@ -48,34 +49,46 @@ class BigInt final : public js::gc::Tenu
+   public:
+     // Allocate and initialize a BigInt value
+     static BigInt* create(JSContext* cx);
+ 
+     static BigInt* createFromDouble(JSContext* cx, double d);
+ 
+     static BigInt* createFromBoolean(JSContext* cx, bool b);
+ 
++    // Read a BigInt value from a little-endian byte array.
++    static BigInt* createFromBytes(JSContext* cx, int sign, void* bytes, size_t nbytes);
++
+     static const JS::TraceKind TraceKind = JS::TraceKind::BigInt;
+ 
+     void traceChildren(JSTracer* trc);
+ 
+     void finalize(js::FreeOp* fop);
+ 
+     js::HashNumber hash();
+ 
+     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+ 
+     bool toBoolean();
++    int8_t sign();
+ 
+     static void init();
+ 
+     static BigInt* copy(JSContext* cx, Handle<BigInt*> x);
+ 
+     static double numberValue(BigInt* x);
+     static JSLinearString* toString(JSContext* cx, BigInt* x, uint8_t radix);
++
++    // Return the length in bytes of the representation used by
++    // writeBytes.
++    static size_t byteLength(BigInt* x);
++
++    // Write a little-endian representation of a BigInt's absolute value
++    // to a byte array.
++    static void writeBytes(BigInt* x, mozilla::RangedPtr<uint8_t> buffer);
+ };
+ 
+ static_assert(sizeof(BigInt) >= js::gc::MinCellSize,
+               "sizeof(BigInt) must be greater than the minimum allocation size");
+ 
+ } // namespace JS
+ 
+ namespace js {

+ 293 - 0
frg/work-js/mozilla-release/patches/1441098-3-62a1.patch

@@ -0,0 +1,293 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1529511000 -10800
+#      Wed Jun 20 19:10:00 2018 +0300
+# Node ID 84ae27690d6b756b64d9bb951db4a035e7e56102
+# Parent  20dd5210f80d51c89f3de5af05e69a4f3fef4b25
+bug 1441098 - Part 3: Add structured clone support for BigInt. r=sfink
+
+New data types are defined for primitive BigInt values and BigInt
+objects. BigInts are serialized starting with 32 bits of sign and length
+information, followed by a little-endian byte sequence representing an
+unsigned integer.
+
+diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp
+--- a/js/src/vm/StructuredClone.cpp
++++ b/js/src/vm/StructuredClone.cpp
+@@ -27,29 +27,33 @@
+  */
+ 
+ #include "js/StructuredClone.h"
+ 
+ #include "mozilla/Casting.h"
+ #include "mozilla/CheckedInt.h"
+ #include "mozilla/EndianUtils.h"
+ #include "mozilla/FloatingPoint.h"
++#include "mozilla/RangedPtr.h"
+ 
+ #include <algorithm>
+ #include <utility>
+ 
+ #include "jsapi.h"
+ #include "jsdate.h"
+ 
+ #include "builtin/DataViewObject.h"
+ #include "builtin/MapObject.h"
+ #include "js/Date.h"
+ #include "js/GCHashTable.h"
+ #include "js/RegExpFlags.h"
+ #include "js/Wrapper.h"
++#ifdef ENABLE_BIGINT
++#include "vm/BigIntType.h"
++#endif
+ #include "vm/JSContext.h"
+ #include "vm/RegExpObject.h"
+ #include "vm/SavedFrame.h"
+ #include "vm/SharedArrayObject.h"
+ #include "vm/TypedArrayObject.h"
+ #include "vm/WrapperObject.h"
+ #include "wasm/WasmJS.h"
+ 
+@@ -57,16 +61,17 @@
+ #include "vm/JSObject-inl.h"
+ 
+ using namespace js;
+ 
+ using mozilla::AssertedCast;
+ using mozilla::BitwiseCast;
+ using mozilla::NativeEndian;
+ using mozilla::NumbersAreIdentical;
++using mozilla::RangedPtr;
+ using JS::CanonicalizeNaN;
+ using JS::RegExpFlag;
+ using JS::RegExpFlags;
+ 
+ // When you make updates here, make sure you consider whether you need to bump the
+ // value of JS_STRUCTURED_CLONE_VERSION in js/public/StructuredClone.h.  You will
+ // likely need to increment the version if anything at all changes in the serialization
+ // format.
+@@ -107,16 +112,19 @@ enum StructuredDataType : uint32_t {
+     SCTAG_JSPRINCIPALS,
+     SCTAG_NULL_JSPRINCIPALS,
+     SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_SYSTEM,
+     SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_NOT_SYSTEM,
+ 
+     SCTAG_SHARED_ARRAY_BUFFER_OBJECT,
+     SCTAG_SHARED_WASM_MEMORY_OBJECT,
+ 
++    SCTAG_BIGINT,
++    SCTAG_BIGINT_OBJECT,
++
+     SCTAG_TYPED_ARRAY_V1_MIN = 0xFFFF0100,
+     SCTAG_TYPED_ARRAY_V1_INT8 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Int8,
+     SCTAG_TYPED_ARRAY_V1_UINT8 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Uint8,
+     SCTAG_TYPED_ARRAY_V1_INT16 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Int16,
+     SCTAG_TYPED_ARRAY_V1_UINT16 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Uint16,
+     SCTAG_TYPED_ARRAY_V1_INT32 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Int32,
+     SCTAG_TYPED_ARRAY_V1_UINT32 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Uint32,
+     SCTAG_TYPED_ARRAY_V1_FLOAT32 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Float32,
+@@ -413,16 +421,20 @@ struct JSStructuredCloneReader {
+ 
+     bool readHeader();
+     bool readTransferMap();
+ 
+     template <typename CharT>
+     JSString* readStringImpl(uint32_t nchars);
+     JSString* readString(uint32_t data);
+ 
++#ifdef ENABLE_BIGINT
++    BigInt* readBigInt(uint32_t data);
++#endif
++
+     bool checkDouble(double d);
+     MOZ_MUST_USE bool readTypedArray(uint32_t arrayType, uint32_t nelems, MutableHandleValue vp,
+                                      bool v1Read = false);
+     MOZ_MUST_USE bool readDataView(uint32_t byteLength, MutableHandleValue vp);
+     MOZ_MUST_USE bool readArrayBuffer(uint32_t nbytes, MutableHandleValue vp);
+     MOZ_MUST_USE bool readSharedArrayBuffer(MutableHandleValue vp);
+     MOZ_MUST_USE bool readSharedWasmMemory(uint32_t nbytes, MutableHandleValue vp);
+     MOZ_MUST_USE bool readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, MutableHandleValue vp);
+@@ -515,16 +527,20 @@ struct JSStructuredCloneWriter {
+     bool writeSharedWasmMemory(HandleObject obj);
+     bool startObject(HandleObject obj, bool* backref);
+     bool startWrite(HandleValue v);
+     bool traverseObject(HandleObject obj);
+     bool traverseMap(HandleObject obj);
+     bool traverseSet(HandleObject obj);
+     bool traverseSavedFrame(HandleObject obj);
+ 
++#ifdef ENABLE_BIGINT
++    bool writeBigInt(uint32_t tag, BigInt* bi);
++#endif
++
+     bool reportDataCloneError(uint32_t errorId);
+ 
+     bool parseTransferable();
+     bool transferOwnership();
+ 
+     inline void checkStack();
+ 
+     SCOutput out;
+@@ -1160,16 +1176,38 @@ JSStructuredCloneWriter::writeString(uin
+         return false;
+ 
+     JS::AutoCheckCannotGC nogc;
+     return linear->hasLatin1Chars()
+            ? out.writeChars(linear->latin1Chars(nogc), length)
+            : out.writeChars(linear->twoByteChars(nogc), length);
+ }
+ 
++#ifdef ENABLE_BIGINT
++bool
++JSStructuredCloneWriter::writeBigInt(uint32_t tag, BigInt* bi)
++{
++    bool signBit = bi->sign() < 1;
++    size_t length = BigInt::byteLength(bi);
++    // The length must fit in 31 bits to leave room for a sign bit.
++    if (length > size_t(INT32_MAX))
++        return false;
++    uint32_t lengthAndSign = length | (static_cast<uint32_t>(signBit) << 31);
++
++    js::UniquePtr<uint8_t> buf(static_cast<uint8_t*>(js_malloc(length)));
++    if (!buf)
++        return false;
++
++    BigInt::writeBytes(bi, RangedPtr<uint8_t>(buf.get(), length));
++    if (!out.writePair(tag, lengthAndSign))
++        return false;
++    return out.writeBytes(buf.get(), length);
++}
++#endif
++
+ inline void
+ JSStructuredCloneWriter::checkStack()
+ {
+ #ifdef DEBUG
+     // To avoid making serialization O(n^2), limit stack-checking at 10.
+     const size_t MAX = 10;
+ 
+     size_t limit = Min(counts.length(), MAX);
+@@ -1534,17 +1572,23 @@ JSStructuredCloneWriter::startWrite(Hand
+     } else if (v.isDouble()) {
+         return out.writeDouble(v.toDouble());
+     } else if (v.isBoolean()) {
+         return out.writePair(SCTAG_BOOLEAN, v.toBoolean());
+     } else if (v.isNull()) {
+         return out.writePair(SCTAG_NULL, 0);
+     } else if (v.isUndefined()) {
+         return out.writePair(SCTAG_UNDEFINED, 0);
+-    } else if (v.isObject()) {
++    }
++#ifdef ENABLE_BIGINT
++    else if (v.isBigInt()) {
++        return writeBigInt(SCTAG_BIGINT, v.toBigInt());
++    }
++#endif
++    else if (v.isObject()) {
+         RootedObject obj(context(), &v.toObject());
+ 
+         bool backref;
+         if (!startObject(obj, &backref))
+             return false;
+         if (backref)
+             return true;
+ 
+@@ -1591,17 +1635,26 @@ JSStructuredCloneWriter::startWrite(Hand
+             RootedValue unboxed(context());
+             if (!Unbox(context(), obj, &unboxed))
+                 return false;
+             return writeString(SCTAG_STRING_OBJECT, unboxed.toString());
+         } else if (cls == ESClass::Map) {
+             return traverseMap(obj);
+         } else if (cls == ESClass::Set) {
+             return traverseSet(obj);
+-        } else if (SavedFrame::isSavedFrameOrWrapperAndNotProto(*obj)) {
++        }
++#ifdef ENABLE_BIGINT
++        else if (cls == ESClass::BigInt) {
++            RootedValue unboxed(context());
++            if (!Unbox(context(), obj, &unboxed))
++                return false;
++            return writeBigInt(SCTAG_BIGINT_OBJECT, unboxed.toBigInt());
++        }
++#endif
++        else if (SavedFrame::isSavedFrameOrWrapperAndNotProto(*obj)) {
+             return traverseSavedFrame(obj);
+         }
+ 
+         if (out.buf.callbacks_ && out.buf.callbacks_->write)
+             return out.buf.callbacks_->write(context(), this, obj, out.buf.closure_);
+         // else fall through
+     }
+ 
+@@ -1904,16 +1957,35 @@ JSStructuredCloneReader::readStringImpl(
+ JSString*
+ JSStructuredCloneReader::readString(uint32_t data)
+ {
+     uint32_t nchars = data & JS_BITMASK(31);
+     bool latin1 = data & (1 << 31);
+     return latin1 ? readStringImpl<Latin1Char>(nchars) : readStringImpl<char16_t>(nchars);
+ }
+ 
++#ifdef ENABLE_BIGINT
++BigInt*
++JSStructuredCloneReader::readBigInt(uint32_t data)
++{
++    size_t nbytes = data & JS_BITMASK(31);
++    bool isNegative = data & (1 << 31);
++
++    if (nbytes == 0)
++        return BigInt::create(context());
++
++    UniquePtr<uint8_t> buf(static_cast<uint8_t*>(js_malloc(nbytes)));
++    if (!buf)
++        return nullptr;
++    if (!in.readBytes(buf.get(), nbytes))
++        return nullptr;
++    return BigInt::createFromBytes(context(), isNegative ? -1 : 1, buf.get(), nbytes);
++}
++#endif
++
+ static uint32_t
+ TagToV1ArrayType(uint32_t tag)
+ {
+     MOZ_ASSERT(tag >= SCTAG_TYPED_ARRAY_V1_MIN && tag <= SCTAG_TYPED_ARRAY_V1_MAX);
+     return tag - SCTAG_TYPED_ARRAY_V1_MIN;
+ }
+ 
+ bool
+@@ -2224,16 +2296,34 @@ JSStructuredCloneReader::startRead(Mutab
+         if (!in.readDouble(&d) || !checkDouble(d))
+             return false;
+         vp.setDouble(d);
+         if (!PrimitiveToObject(context(), vp))
+             return false;
+         break;
+       }
+ 
++      case SCTAG_BIGINT:
++      case SCTAG_BIGINT_OBJECT: {
++#ifdef ENABLE_BIGINT
++        RootedBigInt bi(context(), readBigInt(data));
++        if (!bi)
++            return false;
++        vp.setBigInt(bi);
++        if (tag == SCTAG_BIGINT_OBJECT && !PrimitiveToObject(context(), vp))
++            return false;
++        break;
++#else
++        JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
++                                  JSMSG_SC_BAD_SERIALIZED_DATA,
++                                  "BigInt unsupported");
++        return false;
++#endif
++      }
++
+       case SCTAG_DATE_OBJECT: {
+         double d;
+         if (!in.readDouble(&d) || !checkDouble(d))
+             return false;
+         JS::ClippedTime t = JS::TimeClip(d);
+         if (!NumbersAreIdentical(d, t.toDouble())) {
+             JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
+                                       JSMSG_SC_BAD_SERIALIZED_DATA,

+ 37 - 0
frg/work-js/mozilla-release/patches/1441098-4-62a1.patch

@@ -0,0 +1,37 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1529511060 -10800
+#      Wed Jun 20 19:11:00 2018 +0300
+# Node ID a41bcbc841f9baf2eaf67f4c166331e618d21b66
+# Parent  84ae27690d6b756b64d9bb951db4a035e7e56102
+bug 1441098 - Part 4: Enable BigInt wrapping from DOM bindings. r=bz
+
+diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h
+--- a/dom/bindings/BindingUtils.h
++++ b/dom/bindings/BindingUtils.h
+@@ -971,16 +971,25 @@ MaybeWrapValue(JSContext* cx, JS::Mutabl
+ {
+   if (rval.isGCThing()) {
+     if (rval.isString()) {
+       return MaybeWrapStringValue(cx, rval);
+     }
+     if (rval.isObject()) {
+       return MaybeWrapObjectValue(cx, rval);
+     }
++#ifdef ENABLE_BIGINT
++    // This could be optimized by checking the zone first, similar to
++    // the way strings are handled. At present, this is used primarily
++    // for structured cloning, so avoiding the overhead of JS_WrapValue
++    // calls is less important than for other types.
++    if (rval.isBigInt()) {
++      return JS_WrapValue(cx, rval);
++    }
++#endif
+     MOZ_ASSERT(rval.isSymbol());
+     JS_MarkCrossZoneId(cx, SYMBOL_TO_JSID(rval.toSymbol()));
+   }
+   return true;
+ }
+ 
+ namespace binding_detail {
+ enum GetOrCreateReflectorWrapBehavior {

+ 0 - 0
frg/work-js/mozilla-release/patches/1460381-62a1.patch → frg/work-js/mozilla-release/patches/1460381-3-62a1.patch


+ 83 - 0
frg/work-js/mozilla-release/patches/1464758-62a1.patch

@@ -0,0 +1,83 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1527576600 -10800
+# Node ID fcf6bdd122add51175a57fdf4953aec895f18bfb
+# Parent  c14e3d00d74076f7908f4c1259ccd7e869e60a31
+bug 1464758 - BigInt shouldn't get the legacy fallback behaviour in Object.prototype.toString. r=anba
+
+Change BigInt's class name to "Object" so that the correct tag is used
+when the @@toStringTag property is not a string. Remove special cases
+for BigInt in GetBuiltinTagFast and GetBuiltinTagSlow.
+
+diff --git a/js/src/builtin/BigInt.cpp b/js/src/builtin/BigInt.cpp
+--- a/js/src/builtin/BigInt.cpp
++++ b/js/src/builtin/BigInt.cpp
+@@ -184,18 +184,19 @@ const ClassSpec BigIntObject::classSpec_
+     GenericCreateConstructor<BigIntConstructor, 1, gc::AllocKind::FUNCTION>,
+     CreateBigIntPrototype,
+     nullptr,
+     nullptr,
+     BigIntObject::methods,
+     BigIntObject::properties
+ };
+ 
++// The class is named "Object" as a workaround for bug 1277801.
+ const Class BigIntObject::class_ = {
+-    "BigInt",
++    "Object",
+     JSCLASS_HAS_CACHED_PROTO(JSProto_BigInt) |
+     JSCLASS_HAS_RESERVED_SLOTS(RESERVED_SLOTS),
+     JS_NULL_CLASS_OPS,
+     &BigIntObject::classSpec_
+ };
+ 
+ const JSPropertySpec BigIntObject::properties[] = {
+     // BigInt proposal section 5.3.5
+diff --git a/js/src/builtin/Object.cpp b/js/src/builtin/Object.cpp
+--- a/js/src/builtin/Object.cpp
++++ b/js/src/builtin/Object.cpp
+@@ -469,21 +469,16 @@ GetBuiltinTagSlow(JSContext* cx, HandleO
+         builtinTag.set(cx->names().objectNumber);
+         return true;
+       case ESClass::Date:
+         builtinTag.set(cx->names().objectDate);
+         return true;
+       case ESClass::RegExp:
+         builtinTag.set(cx->names().objectRegExp);
+         return true;
+-#ifdef ENABLE_BIGINT
+-      case ESClass::BigInt:
+-        builtinTag.set(cx->names().objectBigInt);
+-        return true;
+-#endif
+       default:
+         if (obj->isCallable()) {
+             // Non-standard: Prevent <object> from showing up as Function.
+             RootedObject unwrapped(cx, CheckedUnwrap(obj));
+             if (!unwrapped || !unwrapped->getClass()->isDOMClass()) {
+                 builtinTag.set(cx->names().objectFunction);
+                 return true;
+             }
+@@ -533,21 +528,16 @@ GetBuiltinTagFast(JSObject* obj, const C
+     if (obj->is<ErrorObject>())
+         return cx->names().objectError;
+ 
+     if (obj->isCallable() && !obj->getClass()->isDOMClass()) {
+         // Non-standard: Prevent <object> from showing up as Function.
+         return cx->names().objectFunction;
+     }
+ 
+-#ifdef ENABLE_BIGINT
+-    if (obj->is<BigIntObject>())
+-        return cx->names().objectBigInt;
+-#endif
+-
+     return nullptr;
+ }
+ 
+ // ES6 19.1.3.6
+ bool
+ js::obj_toString(JSContext* cx, unsigned argc, Value* vp)
+ {
+     CallArgs args = CallArgsFromVp(argc, vp);
+

+ 170 - 0
frg/work-js/mozilla-release/patches/1466363-62a1.patch

@@ -0,0 +1,170 @@
+# HG changeset patch
+# User Jan de Mooij <jdemooij@mozilla.com>
+# Date 1529658983 -7200
+# Node ID a1765b4cd8fa4af9f1442b587bbe7bfb9865ac6a
+# Parent  781b79f408e41423868e5a5934e5d8f6cadceb87
+Bug 1466363 - Don't optimize INITELEM on non-extensible objects as we might have to throw a TypeError. r=anba
+
+diff --git a/js/src/jit-test/tests/basic/non-extensible-elements6.js b/js/src/jit-test/tests/basic/non-extensible-elements6.js
+--- a/js/src/jit-test/tests/basic/non-extensible-elements6.js
++++ b/js/src/jit-test/tests/basic/non-extensible-elements6.js
+@@ -33,17 +33,18 @@ function testNonExtensible() {
+                                                        {value:4,
+                                                         enumerable: true,
+                                                         configurable: true,
+                                                         writable: true}),
+                            TypeError);
+ 
+     assertEq(a.toString(), "4,9,3,,-2");
+ }
+-testNonExtensible();
++for (var i = 0; i < 15; i++)
++    testNonExtensible();
+ 
+ function testSealed() {
+     var a = [1, 2, 3, , 5];
+     Object.seal(a);
+ 
+     // Can change the value.
+     Object.defineProperty(a, 1, {value:7, enumerable: true, configurable: false, writable: true});
+     assertEq(JSON.stringify(Object.getOwnPropertyDescriptor(a, 1)),
+@@ -82,17 +83,18 @@ function testSealed() {
+                                                        {value:4,
+                                                         enumerable: true,
+                                                         configurable: true,
+                                                         writable: true}),
+                            TypeError);
+ 
+     assertEq(a.toString(), "4,7,3,,5");
+ }
+-testSealed();
++for (var i = 0; i < 15; i++)
++    testSealed();
+ 
+ function testFrozen() {
+     var a = [1, 2, 3, , 5];
+     Object.freeze(a);
+ 
+     // Can redefine with same value/attributes.
+     Object.defineProperty(a, 0, {value:1, enumerable: true, configurable: false, writable: false});
+ 
+@@ -133,9 +135,10 @@ function testFrozen() {
+                                                        {value:4,
+                                                         enumerable: true,
+                                                         configurable: true,
+                                                         writable: true}),
+                            TypeError);
+ 
+     assertEq(a.toString(), "1,2,3,,5");
+ }
+-testFrozen();
++for (var i = 0; i < 15; i++)
++    testFrozen();
+diff --git a/js/src/jit-test/tests/basic/non-extensible-elements8.js b/js/src/jit-test/tests/basic/non-extensible-elements8.js
+new file mode 100644
+--- /dev/null
++++ b/js/src/jit-test/tests/basic/non-extensible-elements8.js
+@@ -0,0 +1,43 @@
++function testSealNonExtensibleArray() {
++    var obj = Object.preventExtensions([0]);
++    var desc = {value: 0, writable: true, enumerable: true, configurable: true};
++
++    var errorAt = -1;
++    var N = 100;
++
++    for (var i = 0; i <= N; ++i) {
++        if (i === N) {
++            Object.seal(obj);
++        }
++        try {
++            Object.defineProperty(obj, 0, desc);
++        } catch {
++            errorAt = i;
++        }
++    }
++    assertEq(errorAt, N);
++}
++for (var i = 0; i < 15; i++)
++    testSealNonExtensibleArray();
++
++function testSealNonExtensibleObject() {
++    var obj = Object.preventExtensions({0:1});
++    var desc = {value: 0, writable: true, enumerable: true, configurable: true};
++
++    var errorAt = -1;
++    var N = 100;
++
++    for (var i = 0; i <= N; ++i) {
++        if (i === N) {
++            Object.seal(obj);
++        }
++        try {
++            Object.defineProperty(obj, 0, desc);
++        } catch {
++            errorAt = i;
++        }
++    }
++    assertEq(errorAt, N);
++}
++for (var i = 0; i < 15; i++)
++    testSealNonExtensibleObject();
+diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp
+--- a/js/src/jit/CacheIR.cpp
++++ b/js/src/jit/CacheIR.cpp
+@@ -3532,16 +3532,23 @@ SetPropIRGenerator::tryAttachSetDenseEle
+ {
+     if (!obj->isNative())
+         return false;
+ 
+     NativeObject* nobj = &obj->as<NativeObject>();
+     if (!nobj->containsDenseElement(index) || nobj->getElementsHeader()->isFrozen())
+         return false;
+ 
++    // Don't optimize INITELEM (DefineProperty) on non-extensible objects: when
++    // the elements are sealed, we have to throw an exception. Note that we have
++    // to check !isExtensible instead of denseElementsAreSealed because sealing
++    // a (non-extensible) object does not necessarily trigger a Shape change.
++    if (IsPropertyInitOp(JSOp(*pc_)) && !nobj->isExtensible())
++        return false;
++
+     if (typeCheckInfo_.needsTypeBarrier())
+         writer.guardGroupForTypeBarrier(objId, nobj->group());
+     TestMatchingNativeReceiver(writer, nobj, objId);
+ 
+     writer.storeDenseElement(objId, indexId, rhsId);
+     writer.returnFromIC();
+ 
+     // Type inference uses JSID_VOID for the element types.
+diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
+--- a/js/src/jit/IonBuilder.cpp
++++ b/js/src/jit/IonBuilder.cpp
+@@ -9161,21 +9161,27 @@ IonBuilder::initOrSetElemDense(Temporary
+ 
+     // Writes which are on holes in the object do not have to bail out if they
+     // cannot hit another indexed property on the object or its prototypes.
+     bool hasExtraIndexedProperty;
+     MOZ_TRY_VAR(hasExtraIndexedProperty, ElementAccessHasExtraIndexedProperty(this, obj));
+ 
+     bool mayBeNonExtensible = ElementAccessMightBeNonExtensible(constraints(), obj);
+ 
+-    if (mayBeNonExtensible && hasExtraIndexedProperty) {
++    if (mayBeNonExtensible) {
+         // FallibleStoreElement does not know how to deal with extra indexed
+         // properties on the prototype. This case should be rare so we fall back
+         // to an IC.
+-        return Ok();
++        if (hasExtraIndexedProperty)
++            return Ok();
++
++        // Don't optimize INITELEM (DefineProperty) on potentially non-extensible
++        // objects: when the array is sealed, we have to throw an exception.
++        if (IsPropertyInitOp(JSOp(*pc)))
++            return Ok();
+     }
+ 
+     *emitted = true;
+ 
+     // Ensure id is an integer.
+     MInstruction* idInt32 = MToNumberInt32::New(alloc(), id);
+     current->add(idInt32);
+     id = idInt32;

+ 45 - 0
frg/work-js/mozilla-release/patches/1466487-62a1.patch

@@ -0,0 +1,45 @@
+# HG changeset patch
+# User Jon Coppeard <jcoppeard@mozilla.com>
+# Date 1528278899 -3600
+# Node ID 450557c0669f09c69dbdc2837e9ca5c24125f789
+# Parent  f72ccbb154263d442b58e10a8dc69da9cd004a4d
+Bug 1466487 - Throw if module metadata hook is not set in the shell r=anba
+
+diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
+--- a/js/src/builtin/ModuleObject.cpp
++++ b/js/src/builtin/ModuleObject.cpp
+@@ -1650,16 +1650,20 @@ js::GetOrCreateModuleMetaObject(JSContex
+     if (JSObject* obj = module->metaObject())
+         return obj;
+ 
+     RootedObject metaObject(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr));
+     if (!metaObject)
+         return nullptr;
+ 
+     JS::ModuleMetadataHook func = cx->runtime()->moduleMetadataHook;
+-    MOZ_ASSERT(func);
++    if (!func) {
++        JS_ReportErrorASCII(cx, "Module metadata hook not set");
++        return nullptr;
++    }
++
+     if (!func(cx, module, metaObject))
+         return nullptr;
+ 
+     module->setMetaObject(metaObject);
+ 
+     return metaObject;
+ }
+diff --git a/js/src/jit-test/tests/modules/bug-1466487.js b/js/src/jit-test/tests/modules/bug-1466487.js
+new file mode 100644
+--- /dev/null
++++ b/js/src/jit-test/tests/modules/bug-1466487.js
+@@ -0,0 +1,7 @@
++if (helperThreadCount() === 0)
++    quit();
++evalInWorker(`
++    let m = parseModule("import.meta;");
++    m.declarationInstantiation();
++    m.evaluation();
++`);
+

+ 95 - 0
frg/work-js/mozilla-release/patches/1466893-1-62a1.patch

@@ -0,0 +1,95 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1528826226 14400
+# Node ID 631e90e9e0747845da585184217fa6f30525c14e
+# Parent  da4e49603752ddf885f7561e8268f7aaecacddc7
+bug 1466893 - Part 1: Implement ToNumeric operation. r=jandem
+
+ToNumeric is a generalized version of ToNumber that converts its
+argument to a numeric primitive value (either a Number or a BigInt).
+
+diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp
+--- a/js/src/jsnum.cpp
++++ b/js/src/jsnum.cpp
+@@ -1602,16 +1602,44 @@ js::ToNumberSlow(JSContext* cx, HandleVa
+         if (v.isBigInt())
+             errnum = JSMSG_BIGINT_TO_NUMBER;
+ #endif
+         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, errnum);
+     }
+     return false;
+ }
+ 
++// BigInt proposal section 3.1.6
++bool
++js::ToNumericSlow(JSContext* cx, MutableHandleValue vp)
++{
++    MOZ_ASSERT(!vp.isNumber());
++#ifdef ENABLE_BIGINT
++    MOZ_ASSERT(!vp.isBigInt());
++#endif
++
++    // Step 1.
++    if (!vp.isPrimitive()) {
++        if (cx->helperThread())
++            return false;
++        if (!ToPrimitive(cx, JSTYPE_NUMBER, vp))
++            return false;
++    }
++
++    // Step 2.
++#ifdef ENABLE_BIGINT
++    if (vp.isBigInt()) {
++        return true;
++    }
++#endif
++
++    // Step 3.
++    return ToNumber(cx, vp);
++}
++
+ /*
+  * Convert a value to an int8_t, according to the WebIDL rules for byte
+  * conversion. Return converted value in *out on success, false on failure.
+  */
+ JS_PUBLIC_API(bool)
+ js::ToInt8Slow(JSContext *cx, const HandleValue v, int8_t *out)
+ {
+     MOZ_ASSERT(!v.isInt32());
+diff --git a/js/src/jsnum.h b/js/src/jsnum.h
+--- a/js/src/jsnum.h
++++ b/js/src/jsnum.h
+@@ -166,16 +166,32 @@ ToNumber(JSContext* cx, JS::MutableHandl
+     extern JS_PUBLIC_API(bool) ToNumberSlow(JSContext* cx, HandleValue v, double* dp);
+     if (!ToNumberSlow(cx, vp, &d))
+         return false;
+ 
+     vp.setNumber(d);
+     return true;
+ }
+ 
++bool
++ToNumericSlow(JSContext* cx, JS::MutableHandleValue vp);
++
++// BigInt proposal section 3.1.6
++MOZ_ALWAYS_INLINE MOZ_MUST_USE bool
++ToNumeric(JSContext* cx, JS::MutableHandleValue vp)
++{
++    if (vp.isNumber())
++        return true;
++#ifdef ENABLE_BIGINT
++    if (vp.isBigInt())
++        return true;
++#endif
++    return ToNumericSlow(cx, vp);
++}
++
+ MOZ_MUST_USE bool
+ num_parseInt(JSContext* cx, unsigned argc, Value* vp);
+ 
+ }  /* namespace js */
+ 
+ /*
+  * Similar to strtod except that it replaces overflows with infinities of the
+  * correct sign, and underflows with zeros of the correct sign.  Guaranteed to
+

+ 110 - 0
frg/work-js/mozilla-release/patches/1466893-2-62a1.patch

@@ -0,0 +1,110 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1528826300 14400
+# Node ID 7cdfba2700eb020b568fe2c34282d4154ba13577
+# Parent  631e90e9e0747845da585184217fa6f30525c14e
+bug 1466893 - Part 2: Convert BigInt arguments to the Number constructor. r=jandem
+
+diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp
+--- a/js/src/jsnum.cpp
++++ b/js/src/jsnum.cpp
+@@ -24,16 +24,19 @@
+ 
+ #include "jstypes.h"
+ 
+ #include "builtin/String.h"
+ #include "double-conversion/double-conversion.h"
+ #include "js/Conversions.h"
+ #include "util/DoubleToString.h"
+ #include "util/StringBuffer.h"
++#ifdef ENABLE_BIGINT
++#include "vm/BigIntType.h"
++#endif
+ #include "vm/GlobalObject.h"
+ #include "vm/JSAtom.h"
+ #include "vm/JSContext.h"
+ #include "vm/JSObject.h"
+ 
+ #include "vm/NativeObject-inl.h"
+ #include "vm/NumberObject-inl.h"
+ #include "vm/StringType-inl.h"
+@@ -482,18 +485,24 @@ const Class NumberObject::class_ = {
+ };
+ 
+ static bool
+ Number(JSContext* cx, unsigned argc, Value* vp)
+ {
+     CallArgs args = CallArgsFromVp(argc, vp);
+ 
+     if (args.length() > 0) {
+-        if (!ToNumber(cx, args[0]))
++        // BigInt proposal section 6.2, steps 2a-c.
++        if (!ToNumeric(cx, args[0]))
+             return false;
++#ifdef ENABLE_BIGINT
++        if (args[0].isBigInt())
++            args[0].setNumber(BigInt::numberValue(args[0].toBigInt()));
++#endif
++        MOZ_ASSERT(args[0].isNumber());
+     }
+ 
+     if (!args.isConstructing()) {
+         if (args.length() > 0)
+             args.rval().set(args[0]);
+         else
+             args.rval().setInt32(0);
+         return true;
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -170,16 +170,28 @@ js::ToBigInt(JSContext* cx, HandleValue 
+         RootedString str(cx, v.toString());
+         return StringToBigInt(cx, str, 0);
+     }
+ 
+     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_BIGINT);
+     return nullptr;
+ }
+ 
++// ES 2019 draft 6.1.6
++double
++BigInt::numberValue(BigInt* x)
++{
++    // mpz_get_d may cause a hardware overflow trap, so use
++    // mpz_get_d_2exp to get the fractional part and exponent
++    // separately.
++    signed long int exp;
++    double d = mpz_get_d_2exp(&exp, x->num_);
++    return ldexp(d, exp);
++}
++
+ JSLinearString*
+ BigInt::toString(JSContext* cx, BigInt* x, uint8_t radix)
+ {
+     MOZ_ASSERT(2 <= radix && radix <= 36);
+     // We need two extra chars for '\0' and potentially '-'.
+     size_t strSize = mpz_sizeinbase(x->num_, 10) + 2;
+     UniqueChars str(static_cast<char*>(js_malloc(strSize)));
+     if (!str) {
+diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
+--- a/js/src/vm/BigIntType.h
++++ b/js/src/vm/BigIntType.h
+@@ -64,16 +64,17 @@ class BigInt final : public js::gc::Tenu
+     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+ 
+     bool toBoolean();
+ 
+     static void init();
+ 
+     static BigInt* copy(JSContext* cx, Handle<BigInt*> x);
+ 
++    static double numberValue(BigInt* x);
+     static JSLinearString* toString(JSContext* cx, BigInt* x, uint8_t radix);
+ };
+ 
+ static_assert(sizeof(BigInt) >= js::gc::MinCellSize,
+               "sizeof(BigInt) must be greater than the minimum allocation size");
+ 
+ } // namespace JS
+ 
+

+ 100 - 0
frg/work-js/mozilla-release/patches/1468792-62a1.patch

@@ -0,0 +1,100 @@
+# HG changeset patch
+# User Jon Coppeard <jcoppeard@mozilla.com>
+# Date 1529482958 -3600
+# Node ID 7aaaed1a9ef133175a7f18054302e890e451f9eb
+# Parent  a4eaa08820524cf318dd4437c02c36d10f8f40c5
+Bug 1468792 - Purge dota caches at the same time as deferred atom cache purge r=sfink
+
+diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp
+--- a/js/src/gc/Zone.cpp
++++ b/js/src/gc/Zone.cpp
+@@ -424,30 +424,44 @@ Zone::ownedByCurrentHelperThread()
+ 
+ void Zone::releaseAtoms()
+ {
+     MOZ_ASSERT(hasKeptAtoms());
+ 
+     keepAtomsCount--;
+ 
+     if (!hasKeptAtoms() && purgeAtomsDeferred) {
+-        atomCache().clearAndShrink();
+         purgeAtomsDeferred = false;
++        purgeAtomCache();
+     }
+ }
+ 
+ void
+ Zone::purgeAtomCacheOrDefer()
+ {
+     if (hasKeptAtoms()) {
+         purgeAtomsDeferred = true;
+         return;
+     }
+ 
++    purgeAtomCache();
++}
++
++void
++Zone::purgeAtomCache()
++{
++    MOZ_ASSERT(!hasKeptAtoms());
++    MOZ_ASSERT(!purgeAtomsDeferred);
++
+     atomCache().clearAndShrink();
++
++    // Also purge the dtoa caches so that subsequent lookups populate atom
++    // cache too.
++    for (RealmsInZoneIter r(this); !r.done(); r.next())
++        r->dtoaCache.purge();
+ }
+ 
+ void
+ Zone::traceAtomCache(JSTracer* trc)
+ {
+     MOZ_ASSERT(hasKeptAtoms());
+     for (auto r = atomCache().all(); !r.empty(); r.popFront()) {
+         JSAtom* atom = r.front().asPtrUnbarriered();
+diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h
+--- a/js/src/gc/Zone.h
++++ b/js/src/gc/Zone.h
+@@ -517,16 +517,17 @@ struct Zone : public JS::shadow::Zone,
+ 
+   public:
+     js::SparseBitmap& markedAtoms() { return markedAtoms_.ref(); }
+ 
+     js::AtomSet& atomCache() { return atomCache_.ref(); }
+ 
+     void traceAtomCache(JSTracer* trc);
+     void purgeAtomCacheOrDefer();
++    void purgeAtomCache();
+ 
+     js::ExternalStringCache& externalStringCache() { return externalStringCache_.ref(); };
+ 
+     js::FunctionToStringCache& functionToStringCache() { return functionToStringCache_.ref(); }
+ 
+     // Track heap usage under this Zone.
+     js::gc::HeapUsage usage;
+ 
+diff --git a/js/src/jit-test/tests/gc/bug-1468792.js b/js/src/jit-test/tests/gc/bug-1468792.js
+new file mode 100644
+--- /dev/null
++++ b/js/src/jit-test/tests/gc/bug-1468792.js
+@@ -0,0 +1,18 @@
++// |jit-test| error: ReferenceError
++
++loadFile(`
++  gczeal(2,9);
++  evaluate(\`
++    reportCompare(expect, actual, summary);
++  \`);
++`);
++function loadFile(lfVarx) {
++    try {
++        evaluate(lfVarx);
++    } catch (lfVare) {}
++}
++eval("(function(){({6953421313:0})})")();
++function f() {
++    x[6953421313] = "a";
++}
++f();

+ 183 - 0
frg/work-js/mozilla-release/patches/1471134-1-63a1.patch

@@ -0,0 +1,183 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1531073520 -10800
+#      Sun Jul 08 21:12:00 2018 +0300
+# Node ID b1ebc15b5eec0e7bafa28dcb3bb2c192d90c1613
+# Parent  e89192032fe21bedf44aa4447f126abf6eba61ae
+bug 1471134 - Part 1: Define methods for basic BigInt arithmetic. r=Waldo
+
+diff --git a/js/src/js.msg b/js/src/js.msg
+--- a/js/src/js.msg
++++ b/js/src/js.msg
+@@ -647,13 +647,14 @@ MSG_DEF(JSMSG_BAD_RESPONSE_VALUE,       
+ MSG_DEF(JSMSG_BAD_RESPONSE_MIME_TYPE,                    0, JSEXN_TYPEERR,  "Response has unsupported MIME type")
+ MSG_DEF(JSMSG_BAD_RESPONSE_CORS_SAME_ORIGIN,             0, JSEXN_TYPEERR,  "Response.type must be 'basic', 'cors' or 'default'")
+ MSG_DEF(JSMSG_BAD_RESPONSE_STATUS,                       0, JSEXN_TYPEERR,  "Response does not have ok status")
+ MSG_DEF(JSMSG_RESPONSE_ALREADY_CONSUMED,                 0, JSEXN_TYPEERR,  "Response already consumed")
+ 
+ // BigInt
+ MSG_DEF(JSMSG_BIGINT_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert BigInt to number")
+ MSG_DEF(JSMSG_NUMBER_TO_BIGINT, 0, JSEXN_RANGEERR, "can't convert non-finite number to BigInt")
++MSG_DEF(JSMSG_BIGINT_TOO_LARGE, 0, JSEXN_RANGEERR, "BigInt is too large to allocate")
+ MSG_DEF(JSMSG_BIGINT_DIVISION_BY_ZERO, 0, JSEXN_RANGEERR, "BigInt division by zero")
+ MSG_DEF(JSMSG_BIGINT_NEGATIVE_EXPONENT, 0, JSEXN_RANGEERR, "BigInt negative exponent")
+ MSG_DEF(JSMSG_BIGINT_INVALID_SYNTAX, 0, JSEXN_SYNTAXERR, "invalid BigInt syntax")
+ MSG_DEF(JSMSG_NOT_BIGINT, 0, JSEXN_TYPEERR, "not a BigInt")
+ MSG_DEF(JSMSG_BIGINT_NOT_SERIALIZABLE, 0, JSEXN_TYPEERR, "BigInt value can't be serialized in JSON")
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -166,16 +166,126 @@ BigInt::copy(JSContext* cx, HandleBigInt
+ {
+     BigInt* bi = Allocate<BigInt>(cx);
+     if (!bi)
+         return nullptr;
+     mpz_init_set(bi->num_, x->num_);
+     return bi;
+ }
+ 
++// BigInt proposal section 1.1.7
++BigInt*
++BigInt::add(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    BigInt* z = create(cx);
++    if (!z)
++        return nullptr;
++    mpz_add(z->num_, x->num_, y->num_);
++    return z;
++}
++
++// BigInt proposal section 1.1.8
++BigInt*
++BigInt::sub(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    BigInt* z = create(cx);
++    if (!z)
++        return nullptr;
++    mpz_sub(z->num_, x->num_, y->num_);
++    return z;
++}
++
++// BigInt proposal section 1.1.4
++BigInt*
++BigInt::mul(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    BigInt* z = create(cx);
++    if (!z)
++        return nullptr;
++    mpz_mul(z->num_, x->num_, y->num_);
++    return z;
++}
++
++// BigInt proposal section 1.1.5
++BigInt*
++BigInt::div(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    // Step 1.
++    if (mpz_size(y->num_) == 0) {
++        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
++                                  JSMSG_BIGINT_DIVISION_BY_ZERO);
++        return nullptr;
++    }
++
++    // Steps 2-3.
++    BigInt* z = create(cx);
++    if (!z)
++        return nullptr;
++    mpz_tdiv_q(z->num_, x->num_, y->num_);
++    return z;
++}
++
++// BigInt proposal section 1.1.6
++BigInt*
++BigInt::mod(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    // Step 1.
++    if (mpz_size(y->num_) == 0) {
++        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
++                                  JSMSG_BIGINT_DIVISION_BY_ZERO);
++        return nullptr;
++    }
++
++    // Steps 2-4.
++    BigInt* z = create(cx);
++    if (!z)
++        return nullptr;
++    mpz_tdiv_r(z->num_, x->num_, y->num_);
++    return z;
++}
++
++// BigInt proposal section 1.1.3
++BigInt*
++BigInt::pow(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    // Step 1.
++    if (mpz_sgn(y->num_) < 0) {
++        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
++                                  JSMSG_BIGINT_NEGATIVE_EXPONENT);
++        return nullptr;
++    }
++
++    // Throw a RangeError if the exponent is too large.
++    if (!mpz_fits_uint_p(y->num_)) {
++        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
++                                  JSMSG_BIGINT_TOO_LARGE);
++        return nullptr;
++    }
++    unsigned long int power = mpz_get_ui(y->num_);
++
++    // Steps 2-3.
++    BigInt* z = create(cx);
++    if (!z)
++        return nullptr;
++
++    mpz_pow_ui(z->num_, x->num_, power);
++    return z;
++}
++
++// BigInt proposal section 1.1.1
++BigInt*
++BigInt::neg(JSContext* cx, HandleBigInt x)
++{
++    BigInt* res = create(cx);
++    if (!res)
++        return nullptr;
++    mpz_neg(res->num_, x->num_);
++    return res;
++}
++
+ // BigInt proposal section 7.3
+ BigInt*
+ js::ToBigInt(JSContext* cx, HandleValue val)
+ {
+     RootedValue v(cx, val);
+ 
+     // Step 1.
+     if (!ToPrimitive(cx, JSTYPE_NUMBER, &v))
+diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
+--- a/js/src/vm/BigIntType.h
++++ b/js/src/vm/BigIntType.h
+@@ -68,16 +68,23 @@ class BigInt final : public js::gc::Tenu
+     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+ 
+     bool toBoolean();
+     int8_t sign();
+ 
+     static void init();
+ 
+     static BigInt* copy(JSContext* cx, Handle<BigInt*> x);
++    static BigInt* add(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* sub(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* mul(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* div(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* mod(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* pow(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* neg(JSContext* cx, Handle<BigInt*> x);
+ 
+     static double numberValue(BigInt* x);
+     static JSLinearString* toString(JSContext* cx, BigInt* x, uint8_t radix);
+ 
+     // Return the length in bytes of the representation used by
+     // writeBytes.
+     static size_t byteLength(BigInt* x);
+ 

+ 177 - 0
frg/work-js/mozilla-release/patches/1471134-2-63a1.patch

@@ -0,0 +1,177 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1531073580 -10800
+#      Sun Jul 08 21:13:00 2018 +0300
+# Node ID 1b449d788c942f8bb049423618be36fd3862e8ae
+# Parent  b1ebc15b5eec0e7bafa28dcb3bb2c192d90c1613
+bug 1471134 - Part 2: Add BigInt arithmetic methods that accept Value arguments. r=jandem
+
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -276,16 +276,133 @@ BigInt::neg(JSContext* cx, HandleBigInt 
+ {
+     BigInt* res = create(cx);
+     if (!res)
+         return nullptr;
+     mpz_neg(res->num_, x->num_);
+     return res;
+ }
+ 
++static bool
++ValidBigIntOperands(JSContext* cx, HandleValue lhs, HandleValue rhs)
++{
++    MOZ_ASSERT(lhs.isBigInt() || rhs.isBigInt());
++
++    if (!lhs.isBigInt() || !rhs.isBigInt()) {
++        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
++                                  JSMSG_BIGINT_TO_NUMBER);
++        return false;
++    }
++
++    return true;
++}
++
++bool
++BigInt::add(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs))
++        return false;
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::add(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt)
++        return false;
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::sub(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs))
++        return false;
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::sub(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt)
++        return false;
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::mul(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs))
++        return false;
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::mul(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt)
++        return false;
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::div(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs))
++        return false;
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::div(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt)
++        return false;
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::mod(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs))
++        return false;
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::mod(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt)
++        return false;
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::pow(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs))
++        return false;
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::pow(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt)
++        return false;
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::neg(JSContext* cx, HandleValue operand, MutableHandleValue res)
++{
++    MOZ_ASSERT(operand.isBigInt());
++
++    RootedBigInt operandBigInt(cx, operand.toBigInt());
++    BigInt* resBigInt = BigInt::neg(cx, operandBigInt);
++    if (!resBigInt)
++        return false;
++    res.setBigInt(resBigInt);
++    return true;
++}
++
+ // BigInt proposal section 7.3
+ BigInt*
+ js::ToBigInt(JSContext* cx, HandleValue val)
+ {
+     RootedValue v(cx, val);
+ 
+     // Step 1.
+     if (!ToPrimitive(cx, JSTYPE_NUMBER, &v))
+diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
+--- a/js/src/vm/BigIntType.h
++++ b/js/src/vm/BigIntType.h
+@@ -76,16 +76,28 @@ class BigInt final : public js::gc::Tenu
+     static BigInt* add(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* sub(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* mul(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* div(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* mod(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* pow(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* neg(JSContext* cx, Handle<BigInt*> x);
+ 
++    // Type-checking versions of arithmetic operations. These methods
++    // must be called with at least one BigInt operand. Binary
++    // operations with throw a TypeError if one of the operands is not a
++    // BigInt value.
++    static bool add(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool sub(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool mul(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool div(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool mod(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool pow(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool neg(JSContext* cx, Handle<Value> operand, MutableHandle<Value> res);
++
+     static double numberValue(BigInt* x);
+     static JSLinearString* toString(JSContext* cx, BigInt* x, uint8_t radix);
+ 
+     // Return the length in bytes of the representation used by
+     // writeBytes.
+     static size_t byteLength(BigInt* x);
+ 
+     // Write a little-endian representation of a BigInt's absolute value

+ 221 - 0
frg/work-js/mozilla-release/patches/1471134-3-63a1.patch

@@ -0,0 +1,221 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1531073580 -10800
+#      Sun Jul 08 21:13:00 2018 +0300
+# Node ID f0328b9f1a4d2f9f565c1f20af9559c07bf3e6fa
+# Parent  b5419a2c66e02d9cd10eb416de67a428eed4bae3
+bug 1471134 - Part 3: Make arithmetic operand arguments mutable. r=jandem
+
+Follow the example of AddOperation, which uses MutableHandleValue for
+arguments that will be passed to ToPrimitive. This allows parameters to
+be converted using ToNumeric instead of ToNumber.
+
+diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
+--- a/js/src/jit/BaselineIC.cpp
++++ b/js/src/jit/BaselineIC.cpp
+@@ -4558,20 +4558,23 @@ DoUnaryArithFallback(JSContext* cx, Base
+     switch (op) {
+       case JSOP_BITNOT: {
+         int32_t result;
+         if (!BitNot(cx, val, &result))
+             return false;
+         res.setInt32(result);
+         break;
+       }
+-      case JSOP_NEG:
+-        if (!NegOperation(cx, val, res))
++      case JSOP_NEG: {
++        // We copy val here because the original value is needed below.
++        RootedValue valCopy(cx, val);
++        if (!NegOperation(cx, &valCopy, res))
+             return false;
+         break;
++      }
+       default:
+         MOZ_CRASH("Unexpected op");
+     }
+ 
+     // Check if debug mode toggling made the stub invalid.
+     if (debug_stub.invalid())
+         return true;
+ 
+diff --git a/js/src/jit/IonIC.cpp b/js/src/jit/IonIC.cpp
+--- a/js/src/jit/IonIC.cpp
++++ b/js/src/jit/IonIC.cpp
+@@ -524,20 +524,23 @@ IonUnaryArithIC::update(JSContext* cx, H
+     switch (op) {
+       case JSOP_BITNOT: {
+         int32_t result;
+         if (!BitNot(cx, val, &result))
+             return false;
+         res.setInt32(result);
+         break;
+       }
+-      case JSOP_NEG:
+-        if (!NegOperation(cx, val, res))
++      case JSOP_NEG: {
++        // We copy val here because the original value is needed below.
++        RootedValue valCopy(cx, val);
++        if (!NegOperation(cx, &valCopy, res))
+             return false;
+         break;
++      }
+       default:
+         MOZ_CRASH("Unexpected op");
+     }
+ 
+     if (ic->state().maybeTransition())
+         ic->discardStubs(cx->zone());
+ 
+     if (ic->state().canAttachStub()) {
+diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
+--- a/js/src/vm/Interpreter-inl.h
++++ b/js/src/vm/Interpreter-inl.h
+@@ -442,17 +442,17 @@ DefVarOperation(JSContext* cx, HandleObj
+         if (!varobj->realm()->addToVarNames(cx, dn))
+             return false;
+     }
+ 
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-NegOperation(JSContext* cx, HandleValue val, MutableHandleValue res)
++NegOperation(JSContext* cx, MutableHandleValue val, MutableHandleValue res)
+ {
+     /*
+      * When the operand is int jsval, INT32_FITS_IN_JSVAL(i) implies
+      * INT32_FITS_IN_JSVAL(-i) unless i is 0 or INT32_MIN when the
+      * results, -0.0 or INT32_MAX + 1, are double values.
+      */
+     int32_t i;
+     if (val.isInt32() && (i = val.toInt32()) != 0 && i != INT32_MIN) {
+diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
+--- a/js/src/vm/Interpreter.cpp
++++ b/js/src/vm/Interpreter.cpp
+@@ -1549,47 +1549,47 @@ AddOperation(JSContext* cx, MutableHandl
+             return false;
+         res.setNumber(l + r);
+     }
+ 
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-SubOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++SubOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+     double d1, d2;
+     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
+         return false;
+     res.setNumber(d1 - d2);
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-MulOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++MulOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+     double d1, d2;
+     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
+         return false;
+     res.setNumber(d1 * d2);
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-DivOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++DivOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+     double d1, d2;
+     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
+         return false;
+     res.setNumber(NumberDiv(d1, d2));
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-ModOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++ModOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+     int32_t l, r;
+     if (lhs.isInt32() && rhs.isInt32() &&
+         (l = lhs.toInt32()) >= 0 && (r = rhs.toInt32()) > 0) {
+         int32_t mod = l % r;
+         res.setInt32(mod);
+         return true;
+     }
+@@ -2606,50 +2606,50 @@ CASE(JSOP_ADD)
+ }
+ END_CASE(JSOP_ADD)
+ 
+ CASE(JSOP_SUB)
+ {
+     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
+     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
+     MutableHandleValue res = REGS.stackHandleAt(-2);
+-    if (!SubOperation(cx, lval, rval, res))
++    if (!SubOperation(cx, &lval, &rval, res))
+         goto error;
+     REGS.sp--;
+ }
+ END_CASE(JSOP_SUB)
+ 
+ CASE(JSOP_MUL)
+ {
+     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
+     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
+     MutableHandleValue res = REGS.stackHandleAt(-2);
+-    if (!MulOperation(cx, lval, rval, res))
++    if (!MulOperation(cx, &lval, &rval, res))
+         goto error;
+     REGS.sp--;
+ }
+ END_CASE(JSOP_MUL)
+ 
+ CASE(JSOP_DIV)
+ {
+     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
+     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
+     MutableHandleValue res = REGS.stackHandleAt(-2);
+-    if (!DivOperation(cx, lval, rval, res))
++    if (!DivOperation(cx, &lval, &rval, res))
+         goto error;
+     REGS.sp--;
+ }
+ END_CASE(JSOP_DIV)
+ 
+ CASE(JSOP_MOD)
+ {
+     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
+     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
+     MutableHandleValue res = REGS.stackHandleAt(-2);
+-    if (!ModOperation(cx, lval, rval, res))
++    if (!ModOperation(cx, &lval, &rval, res))
+         goto error;
+     REGS.sp--;
+ }
+ END_CASE(JSOP_MOD)
+ 
+ CASE(JSOP_POW)
+ {
+     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
+@@ -2678,17 +2678,17 @@ CASE(JSOP_BITNOT)
+     REGS.sp[-1].setInt32(i);
+ }
+ END_CASE(JSOP_BITNOT)
+ 
+ CASE(JSOP_NEG)
+ {
+     ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]);
+     MutableHandleValue res = REGS.stackHandleAt(-1);
+-    if (!NegOperation(cx, val, res))
++    if (!NegOperation(cx, &val, res))
+         goto error;
+ }
+ END_CASE(JSOP_NEG)
+ 
+ CASE(JSOP_POS)
+     if (!ToNumber(cx, REGS.stackHandleAt(-1)))
+         goto error;
+ END_CASE(JSOP_POS)

+ 276 - 0
frg/work-js/mozilla-release/patches/1471134-4-63a1.patch

@@ -0,0 +1,276 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1531073580 -10800
+#      Sun Jul 08 21:13:00 2018 +0300
+# Node ID 22883fe0cf16befe28ce81deb8a012453cf80af7
+# Parent  f0328b9f1a4d2f9f565c1f20af9559c07bf3e6fa
+bug 1471134 - Part 4: Add PowValues/PowOperation for exponentiation. r=jandem
+
+Inline math_pow_handle into math_pow and PowValues, and replace other
+uses with calls to PowValues.
+
+diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
+--- a/js/src/jit/CodeGenerator.cpp
++++ b/js/src/jit/CodeGenerator.cpp
+@@ -7489,19 +7489,18 @@ CodeGenerator::visitPowD(LPowD* ins)
+     masm.setupUnalignedABICall(temp);
+     masm.passABIArg(value, MoveOp::DOUBLE);
+     masm.passABIArg(power, MoveOp::DOUBLE);
+     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ecmaPow), MoveOp::DOUBLE);
+ 
+     MOZ_ASSERT(ToFloatRegister(ins->output()) == ReturnDoubleReg);
+ }
+ 
+-using PowFn = bool (*)(JSContext*, HandleValue, HandleValue, MutableHandleValue);
+-static const VMFunction PowInfo =
+-    FunctionInfo<PowFn>(js::math_pow_handle, "math_pow_handle");
++using PowFn = bool (*)(JSContext*, MutableHandleValue, MutableHandleValue, MutableHandleValue);
++static const VMFunction PowInfo = FunctionInfo<PowFn>(js::PowValues, "PowValues");
+ 
+ void
+ CodeGenerator::visitPowV(LPowV* ins)
+ {
+     pushArg(ToValue(ins, LPowV::PowerInput));
+     pushArg(ToValue(ins, LPowV::ValueInput));
+     callVM(PowInfo, ins);
+ }
+diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp
+--- a/js/src/jit/Recover.cpp
++++ b/js/src/jit/Recover.cpp
+@@ -797,17 +797,17 @@ RPow::RPow(CompactBufferReader& reader)
+ bool
+ RPow::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue base(cx, iter.read());
+     RootedValue power(cx, iter.read());
+     RootedValue result(cx);
+ 
+     MOZ_ASSERT(base.isNumber() && power.isNumber());
+-    if (!js::math_pow_handle(cx, base, power, &result))
++    if (!js::PowValues(cx, &base, &power, &result))
+         return false;
+ 
+     iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+ MPowHalf::writeRecoverData(CompactBufferWriter& writer) const
+@@ -824,17 +824,17 @@ bool
+ RPowHalf::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue base(cx, iter.read());
+     RootedValue power(cx);
+     RootedValue result(cx);
+     power.setNumber(0.5);
+ 
+     MOZ_ASSERT(base.isNumber());
+-    if (!js::math_pow_handle(cx, base, power, &result))
++    if (!js::PowValues(cx, &base, &power, &result))
+         return false;
+ 
+     iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+ MMinMax::writeRecoverData(CompactBufferWriter& writer) const
+diff --git a/js/src/jit/SharedIC.cpp b/js/src/jit/SharedIC.cpp
+--- a/js/src/jit/SharedIC.cpp
++++ b/js/src/jit/SharedIC.cpp
+@@ -714,17 +714,17 @@ DoBinaryArithFallback(JSContext* cx, voi
+         if (!DivValues(cx, &lhsCopy, &rhsCopy, ret))
+             return false;
+         break;
+       case JSOP_MOD:
+         if (!ModValues(cx, &lhsCopy, &rhsCopy, ret))
+             return false;
+         break;
+       case JSOP_POW:
+-        if (!math_pow_handle(cx, lhsCopy, rhsCopy, ret))
++        if (!PowValues(cx, &lhsCopy, &rhsCopy, ret))
+             return false;
+         break;
+       case JSOP_BITOR: {
+         int32_t result;
+         if (!BitOr(cx, lhs, rhs, &result))
+             return false;
+         ret.setInt32(result);
+         break;
+diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp
+--- a/js/src/jsmath.cpp
++++ b/js/src/jsmath.cpp
+@@ -644,37 +644,31 @@ js::ecmaPow(double x, double y)
+             return sqrt(x);
+         if (y == -0.5)
+             return 1.0 / sqrt(x);
+     }
+     return pow(x, y);
+ }
+ 
+ bool
+-js::math_pow_handle(JSContext* cx, HandleValue base, HandleValue power, MutableHandleValue result)
+-{
+-    double x;
+-    if (!ToNumber(cx, base, &x))
+-        return false;
+-
+-    double y;
+-    if (!ToNumber(cx, power, &y))
+-        return false;
+-
+-    double z = ecmaPow(x, y);
+-    result.setNumber(z);
+-    return true;
+-}
+-
+-bool
+ js::math_pow(JSContext* cx, unsigned argc, Value* vp)
+ {
+     CallArgs args = CallArgsFromVp(argc, vp);
+ 
+-    return math_pow_handle(cx, args.get(0), args.get(1), args.rval());
++    double x;
++    if (!ToNumber(cx, args.get(0), &x))
++        return false;
++
++    double y;
++    if (!ToNumber(cx, args.get(1), &y))
++        return false;
++
++    double z = ecmaPow(x, y);
++    args.rval().setNumber(z);
++    return true;
+ }
+ 
+ uint64_t
+ js::GenerateRandomSeed()
+ {
+     uint64_t seed = 0;
+ 
+ #if defined(XP_WIN)
+diff --git a/js/src/jsmath.h b/js/src/jsmath.h
+--- a/js/src/jsmath.h
++++ b/js/src/jsmath.h
+@@ -128,20 +128,16 @@ math_sqrt_impl(MathCache* cache, double 
+ 
+ extern bool
+ math_sqrt_handle(JSContext* cx, js::HandleValue number, js::MutableHandleValue result);
+ 
+ extern bool
+ math_sqrt(JSContext* cx, unsigned argc, js::Value* vp);
+ 
+ extern bool
+-math_pow_handle(JSContext* cx, js::HandleValue base, js::HandleValue power,
+-                js::MutableHandleValue result);
+-
+-extern bool
+ math_pow(JSContext* cx, unsigned argc, js::Value* vp);
+ 
+ extern bool
+ minmax_impl(JSContext* cx, bool max, js::HandleValue a, js::HandleValue b,
+             js::MutableHandleValue res);
+ 
+ extern void
+ math_sincos_uncached(double x, double *sin, double *cos);
+diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
+--- a/js/src/vm/Interpreter.cpp
++++ b/js/src/vm/Interpreter.cpp
+@@ -1667,16 +1667,32 @@ ModOperation(JSContext* cx, MutableHandl
+     if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
+         return false;
+ 
+     res.setNumber(NumberMod(d1, d2));
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
++PowOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
++{
++    double x;
++    if (!ToNumber(cx, lhs, &x))
++        return false;
++
++    double y;
++    if (!ToNumber(cx, rhs, &y))
++        return false;
++
++    double z = ecmaPow(x, y);
++    res.setNumber(z);
++    return true;
++}
++
++static MOZ_ALWAYS_INLINE bool
+ SetObjectElementOperation(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
+                           HandleValue receiver, bool strict,
+                           JSScript* script = nullptr, jsbytecode* pc = nullptr)
+ {
+     // receiver != obj happens only at super[expr], where we expect to find the property
+     // People probably aren't building hashtables with |super| anyway.
+     TypeScript::MonitorAssign(cx, obj, id);
+ 
+@@ -2717,17 +2733,17 @@ CASE(JSOP_MOD)
+ }
+ END_CASE(JSOP_MOD)
+ 
+ CASE(JSOP_POW)
+ {
+     ReservedRooted<Value> lval(&rootValue0, REGS.sp[-2]);
+     ReservedRooted<Value> rval(&rootValue1, REGS.sp[-1]);
+     MutableHandleValue res = REGS.stackHandleAt(-2);
+-    if (!math_pow_handle(cx, lval, rval, res))
++    if (!PowOperation(cx, &lval, &rval, res))
+         goto error;
+     REGS.sp--;
+ }
+ END_CASE(JSOP_POW)
+ 
+ CASE(JSOP_NOT)
+ {
+     bool cond = ToBoolean(REGS.stackHandleAt(-1));
+@@ -4818,16 +4834,22 @@ js::DivValues(JSContext* cx, MutableHand
+ 
+ bool
+ js::ModValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+     return ModOperation(cx, lhs, rhs, res);
+ }
+ 
+ bool
++js::PowValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
++{
++    return PowOperation(cx, lhs, rhs, res);
++}
++
++bool
+ js::UrshValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+     return UrshOperation(cx, lhs, rhs, res);
+ }
+ 
+ bool
+ js::AtomicIsLockFree(JSContext* cx, HandleValue in, int* out)
+ {
+diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h
+--- a/js/src/vm/Interpreter.h
++++ b/js/src/vm/Interpreter.h
+@@ -464,16 +464,19 @@ MulValues(JSContext* cx, MutableHandleVa
+ 
+ bool
+ DivValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
+ 
+ bool
+ ModValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
+ 
+ bool
++PowValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
++
++bool
+ UrshValues(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
+ 
+ bool
+ AtomicIsLockFree(JSContext* cx, HandleValue in, int* out);
+ 
+ template <bool strict>
+ bool
+ DeletePropertyJit(JSContext* ctx, HandleValue val, HandlePropertyName name, bool* bv);

+ 190 - 0
frg/work-js/mozilla-release/patches/1471134-5-63a1.patch

@@ -0,0 +1,190 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1531073640 -10800
+#      Sun Jul 08 21:14:00 2018 +0300
+# Node ID 214a13e783acb9bceeb6cdaa4215f4e8b1ae109f
+# Parent  22883fe0cf16befe28ce81deb8a012453cf80af7
+bug 1471134 - Part 5: Support BigInt operands for basic arithmetic operators. r=jandem
+
+Operands are converted to primitive values using ToNumeric, which can
+result in either BigInt or Number values. If any operand is a BigInt,
+the corresponding BigInt method is called; otherwise, the existing
+behavior for Numbers is used.
+
+diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
+--- a/js/src/vm/Interpreter-inl.h
++++ b/js/src/vm/Interpreter-inl.h
+@@ -452,23 +452,28 @@ NegOperation(JSContext* cx, MutableHandl
+     /*
+      * When the operand is int jsval, INT32_FITS_IN_JSVAL(i) implies
+      * INT32_FITS_IN_JSVAL(-i) unless i is 0 or INT32_MIN when the
+      * results, -0.0 or INT32_MAX + 1, are double values.
+      */
+     int32_t i;
+     if (val.isInt32() && (i = val.toInt32()) != 0 && i != INT32_MIN) {
+         res.setInt32(-i);
+-    } else {
+-        double d;
+-        if (!ToNumber(cx, val, &d))
+-            return false;
+-        res.setNumber(-d);
++        return true;
+     }
+ 
++    if (!ToNumeric(cx, val))
++        return false;
++
++#ifdef ENABLE_BIGINT
++    if (val.isBigInt())
++        return BigInt::neg(cx, val, res);
++#endif
++
++    res.setNumber(-val.toNumber());
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ ToIdOperation(JSContext* cx, HandleValue idval, MutableHandleValue res)
+ {
+     if (idval.isInt32()) {
+         res.set(idval);
+diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
+--- a/js/src/vm/Interpreter.cpp
++++ b/js/src/vm/Interpreter.cpp
+@@ -1607,88 +1607,111 @@ AddOperation(JSContext* cx, MutableHandl
+         JSString* str = ConcatStrings<NoGC>(cx, lstr, rstr);
+         if (!str) {
+             RootedString nlstr(cx, lstr), nrstr(cx, rstr);
+             str = ConcatStrings<CanGC>(cx, nlstr, nrstr);
+             if (!str)
+                 return false;
+         }
+         res.setString(str);
+-    } else {
+-        double l, r;
+-        if (!ToNumber(cx, lhs, &l) || !ToNumber(cx, rhs, &r))
+-            return false;
+-        res.setNumber(l + r);
++        return true;
+     }
+ 
++    if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs))
++        return false;
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt())
++        return BigInt::add(cx, lhs, rhs, res);
++#endif
++
++    res.setNumber(lhs.toNumber() + rhs.toNumber());
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ SubOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+-    double d1, d2;
+-    if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
++    if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs))
+         return false;
+-    res.setNumber(d1 - d2);
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt())
++        return BigInt::sub(cx, lhs, rhs, res);
++#endif
++
++    res.setNumber(lhs.toNumber() - rhs.toNumber());
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ MulOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+-    double d1, d2;
+-    if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
++    if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs))
+         return false;
+-    res.setNumber(d1 * d2);
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt())
++        return BigInt::mul(cx, lhs, rhs, res);
++#endif
++
++    res.setNumber(lhs.toNumber() * rhs.toNumber());
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ DivOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+-    double d1, d2;
+-    if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
++    if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs))
+         return false;
+-    res.setNumber(NumberDiv(d1, d2));
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt())
++        return BigInt::div(cx, lhs, rhs, res);
++#endif
++
++    res.setNumber(NumberDiv(lhs.toNumber(), rhs.toNumber()));
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ ModOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+     int32_t l, r;
+     if (lhs.isInt32() && rhs.isInt32() &&
+         (l = lhs.toInt32()) >= 0 && (r = rhs.toInt32()) > 0) {
+         int32_t mod = l % r;
+         res.setInt32(mod);
+         return true;
+     }
+ 
+-    double d1, d2;
+-    if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2))
++    if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs))
+         return false;
+ 
+-    res.setNumber(NumberMod(d1, d2));
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt())
++        return BigInt::mod(cx, lhs, rhs, res);
++#endif
++
++    res.setNumber(NumberMod(lhs.toNumber(), rhs.toNumber()));
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ PowOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res)
+ {
+-    double x;
+-    if (!ToNumber(cx, lhs, &x))
++    if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs))
+         return false;
+ 
+-    double y;
+-    if (!ToNumber(cx, rhs, &y))
+-        return false;
+-
+-    double z = ecmaPow(x, y);
+-    res.setNumber(z);
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt())
++        return BigInt::pow(cx, lhs, rhs, res);
++#endif
++
++    res.setNumber(ecmaPow(lhs.toNumber(), rhs.toNumber()));
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ SetObjectElementOperation(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
+                           HandleValue receiver, bool strict,
+                           JSScript* script = nullptr, jsbytecode* pc = nullptr)
+ {

+ 610 - 0
frg/work-js/mozilla-release/patches/1478503-63a1.patch

@@ -0,0 +1,610 @@
+# HG changeset patch
+# User Andre Bargull <andre.bargull@gmail.com>
+# Date 1533240184 25200
+# Node ID c543368b25a6bc3380ddb207e290a7dfdfcc8be1
+# Parent  197be2a5ee7f7289ae80302c1f9b6ed0480500c7
+Bug 1478503: Shrink capacity when modifying length on a non-extensible array. r=jandem
+
+diff --git a/js/src/builtin/Array.cpp b/js/src/builtin/Array.cpp
+--- a/js/src/builtin/Array.cpp
++++ b/js/src/builtin/Array.cpp
+@@ -521,17 +521,17 @@ DeleteArrayElement(JSContext* cx, Handle
+     {
+         ArrayObject* aobj = &obj->as<ArrayObject>();
+         if (index <= UINT32_MAX) {
+             uint32_t idx = uint32_t(index);
+             if (idx < aobj->getDenseInitializedLength()) {
+                 if (!aobj->maybeCopyElementsForWrite(cx))
+                     return false;
+                 if (idx+1 == aobj->getDenseInitializedLength()) {
+-                    aobj->setDenseInitializedLength(idx);
++                    aobj->setDenseInitializedLengthMaybeNonExtensible(cx, idx);
+                 } else {
+                     aobj->markDenseElementsNotPacked(cx);
+                     aobj->setDenseElement(idx, MagicValue(JS_ELEMENTS_HOLE));
+                 }
+                 if (!SuppressDeletedElement(cx, obj, idx))
+                     return false;
+             }
+         }
+@@ -785,17 +785,17 @@ js::ArraySetLength(JSContext* cx, Handle
+         if (!arr->isIndexed() && !MaybeInIteration(arr, cx) && !arr->denseElementsAreSealed()) {
+             if (!arr->maybeCopyElementsForWrite(cx))
+                 return false;
+ 
+             uint32_t oldCapacity = arr->getDenseCapacity();
+             uint32_t oldInitializedLength = arr->getDenseInitializedLength();
+             MOZ_ASSERT(oldCapacity >= oldInitializedLength);
+             if (oldInitializedLength > newLen)
+-                arr->setDenseInitializedLength(newLen);
++                arr->setDenseInitializedLengthMaybeNonExtensible(cx, newLen);
+             if (oldCapacity > newLen)
+                 arr->shrinkElements(cx, newLen);
+ 
+             // We've done the work of deleting any dense elements needing
+             // deletion, and there are no sparse elements.  Thus we can skip
+             // straight to defining the length.
+             break;
+         }
+@@ -925,16 +925,19 @@ js::ArraySetLength(JSContext* cx, Handle
+     // so that all element fields remain properly synchronized.
+ 
+     // Trim the initialized length, if needed, to preserve the <= length
+     // invariant.  (Capacity was already reduced during element deletion, if
+     // necessary.)
+     ObjectElements* header = arr->getElementsHeader();
+     header->initializedLength = Min(header->initializedLength, newLen);
+ 
++    if (!arr->isExtensible())
++        arr->shrinkCapacityToInitializedLength(cx);
++
+     if (attrs & JSPROP_READONLY)
+         arr->setNonWritableLength(cx);
+ 
+     if (!succeeded)
+         return result.fail(JSMSG_CANT_TRUNCATE_ARRAY);
+ 
+     return result.succeed();
+ }
+@@ -2395,28 +2398,29 @@ js::ArrayShiftMoveElements(NativeObject*
+ 
+     if (!obj->tryShiftDenseElements(1))
+         obj->moveDenseElementsNoPreBarrier(0, 1, initlen - 1);
+ }
+ 
+ static inline void
+ SetInitializedLength(JSContext* cx, NativeObject* obj, size_t initlen)
+ {
++    MOZ_ASSERT(obj->isExtensible());
++
+     size_t oldInitlen = obj->getDenseInitializedLength();
+     obj->setDenseInitializedLength(initlen);
+     if (initlen < oldInitlen)
+         obj->shrinkElements(cx, initlen);
+ }
+ 
+ static DenseElementResult
+ MoveDenseElements(JSContext* cx, NativeObject* obj, uint32_t dstStart, uint32_t srcStart,
+                   uint32_t length)
+ {
+-    if (!obj->isExtensible())
+-        return DenseElementResult::Incomplete;
++    MOZ_ASSERT(obj->isExtensible());
+ 
+     if (!obj->maybeCopyElementsForWrite(cx))
+         return DenseElementResult::Failure;
+     obj->moveDenseElements(dstStart, srcStart, length);
+ 
+     return DenseElementResult::Success;
+ }
+ 
+@@ -2424,16 +2428,19 @@ static DenseElementResult
+ ArrayShiftDenseKernel(JSContext* cx, HandleObject obj, MutableHandleValue rval)
+ {
+     if (!IsPackedArray(obj) && ObjectMayHaveExtraIndexedProperties(obj))
+         return DenseElementResult::Incomplete;
+ 
+     if (MaybeInIteration(obj, cx))
+         return DenseElementResult::Incomplete;
+ 
++    if (!obj->as<NativeObject>().isExtensible())
++        return DenseElementResult::Incomplete;
++
+     size_t initlen = obj->as<NativeObject>().getDenseInitializedLength();
+     if (initlen == 0)
+         return DenseElementResult::Incomplete;
+ 
+     rval.set(obj->as<NativeObject>().getDenseElement(0));
+     if (rval.isMagic(JS_ELEMENTS_HOLE))
+         rval.setUndefined();
+ 
+diff --git a/js/src/jit-test/tests/basic/non-extensible-elements9.js b/js/src/jit-test/tests/basic/non-extensible-elements9.js
+new file mode 100644
+--- /dev/null
++++ b/js/src/jit-test/tests/basic/non-extensible-elements9.js
+@@ -0,0 +1,187 @@
++function testNonExtensibleStoreFallibleT() {
++    // Create an array with initialized-length = capacity = 2.
++    var x = [8, 0];
++
++    // Make it non-extensible.
++    Object.preventExtensions(x);
++
++    // Now reduce initialized-length by one, so that initialized-length < capacity is true.
++    x.length = 1;
++
++    // There's enough capacity in the elements storage to save the new element,
++    // but we still need to reject the store since the object is non-extensible.
++    x[1] = 4;
++
++    assertEq(x.length, 1);
++    assertEq(x[0], 8);
++}
++
++for (var i = 0; i < 15; ++i)
++    testNonExtensibleStoreFallibleT();
++
++// Repeat testNonExtensibleStoreFallibleT for the MIRType::Value specialization.
++function testNonExtensibleStoreFallibleV(i) {
++    // Create an array with initialized-length = capacity = 2.
++    var x = [8, ""];
++
++    // Make it non-extensible.
++    Object.preventExtensions(x);
++
++    // Now reduce initialized-length by one, so that initialized-length < capacity is true.
++    x.length = 1;
++
++    // There's enough capacity in the elements storage to save the new element,
++    // but we still need to reject the store since the object is non-extensible.
++    x[1] = [true, 1][i & 1];
++
++    assertEq(x.length, 1);
++    assertEq(x[0], 8);
++}
++
++for (var i = 0; i < 15; ++i)
++    testNonExtensibleStoreFallibleV(i);
++
++function testForInIterationNonExtensibleStoreFallibleT() {
++    // Create an array with initialized-length = capacity = 2.
++    var x = [8, 0];
++
++    // Make it non-extensible.
++    Object.preventExtensions(x);
++
++    // Modifying an array's length takes a different path during for-in
++    // iteration of the array.
++    for (var k in x) {
++        // Now reduce initialized-length by one, so that initialized-length < capacity is true.
++        x.length = 1;
++    }
++
++    // There's enough capacity in the elements storage to save the new element,
++    // but we still need to reject the store since the object is non-extensible.
++    x[1] = 4;
++
++    assertEq(x.length, 1);
++    assertEq(x[0], 8);
++}
++
++for (var i = 0; i < 15; ++i)
++    testForInIterationNonExtensibleStoreFallibleT();
++
++// Repeat testForInIterationNonExtensibleStoreFallibleT for the MIRType::Value specialization.
++function testForInIterationNonExtensibleStoreFallibleV(i) {
++    // Create an array with initialized-length = capacity = 2.
++    var x = [8, ""];
++
++    // Make it non-extensible.
++    Object.preventExtensions(x);
++
++    // Modifying an array's length takes a different path during for-in
++    // iteration of the array.
++    for (var k in x) {
++        // Now reduce initialized-length by one, so that initialized-length < capacity is true.
++        x.length = 1;
++        break;
++    }
++
++    // There's enough capacity in the elements storage to save the new element,
++    // but we still need to reject the store since the object is non-extensible.
++    x[1] = [true, 1][i & 1];
++
++    assertEq(x.length, 1);
++    assertEq(x[0], 8);
++}
++
++for (var i = 0; i < 15; ++i)
++    testForInIterationNonExtensibleStoreFallibleV(i);
++
++function testNonExtensibleArrayPop() {
++    // Create an array with initialized-length = capacity = 2.
++    var x = [8, 0];
++
++    // Make it non-extensible.
++    Object.preventExtensions(x);
++
++    // Now reduce initialized-length by one, so that initialized-length < capacity is true.
++    x.pop();
++
++    // There's enough capacity in the elements storage to save the new element,
++    // but we still need to reject the store since the object is non-extensible.
++    x[1] = 4;
++
++    assertEq(x.length, 1);
++    assertEq(x[0], 8);
++}
++
++for (var i = 0; i < 15; ++i)
++    testNonExtensibleArrayPop();
++
++function testNonExtensibleArrayPopNonWritable() {
++    // Create an array with initialized-length = capacity = 2.
++    var x = [8, 0];
++
++    // Make it non-extensible.
++    Object.preventExtensions(x);
++
++    // And make the "length" property non-writable.
++    Object.defineProperty(x, "length", {writable: false});
++
++    // Now reduce initialized-length by one, so that initialized-length < capacity is true.
++    // This doesn't update |x.length|, because the "length" property is non-writable.
++    try {
++        x.pop();
++    } catch {}
++
++    // There's enough capacity in the elements storage to save the new element,
++    // but we still need to reject the store since the object is non-extensible.
++    for (var i = 0; i < 100; ++i)
++        x[1] = 4;
++
++    assertEq(x.length, 2);
++    assertEq(x[0], 8);
++    assertEq(x[1], undefined);
++    assertEq(1 in x, false);
++}
++
++for (var i = 0; i < 15; ++i)
++    testNonExtensibleArrayPopNonWritable();
++
++function testNonExtensibleArrayShift() {
++    // Create an array with initialized-length = capacity = 2.
++    var x = [8, 0];
++
++    // Make it non-extensible.
++    Object.preventExtensions(x);
++
++    // Now reduce initialized-length by one, so that initialized-length < capacity is true.
++    x.shift();
++
++    // There's enough capacity in the elements storage to save the new element,
++    // but we still need to reject the store since the object is non-extensible.
++    x[1] = 4;
++
++    assertEq(x.length, 1);
++    assertEq(x[0], 0);
++}
++
++for (var i = 0; i < 15; ++i)
++    testNonExtensibleArrayShift();
++
++function testNonExtensibleArraySplice() {
++    // Create an array with initialized-length = capacity = 2.
++    var x = [8, 0];
++
++    // Make it non-extensible.
++    Object.preventExtensions(x);
++
++    // Now reduce initialized-length by one, so that initialized-length < capacity is true.
++    x.splice(1, 1);
++
++    // There's enough capacity in the elements storage to save the new element,
++    // but we still need to reject the store since the object is non-extensible.
++    x[1] = 4;
++
++    assertEq(x.length, 1);
++    assertEq(x[0], 8);
++}
++
++for (var i = 0; i < 15; ++i)
++    testNonExtensibleArraySplice();
+diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp
+--- a/js/src/jit/MCallOptimize.cpp
++++ b/js/src/jit/MCallOptimize.cpp
+@@ -690,28 +690,28 @@ IonBuilder::inlineArrayPopShift(CallInfo
+     if (returnType == MIRType::Undefined || returnType == MIRType::Null)
+         return InliningStatus_NotInlined;
+     if (callInfo.thisArg()->type() != MIRType::Object)
+         return InliningStatus_NotInlined;
+ 
+     // Pop and shift are only handled for dense arrays that have never been
+     // used in an iterator: popping elements does not account for suppressing
+     // deleted properties in active iterators.
++    // Don't optimize shift if the array may be non-extensible (this matters
++    // when there are holes). Don't optimize pop if the array may be
++    // non-extensible, so we don't need to adjust the capacity for
++    // non-extensible arrays (non-extensible objects always have a capacity
++    // equal to their initialized length). We check this here because there's
++    // no non-extensible ObjectElements flag so we would need an extra guard
++    // on the BaseShape flags.
+     ObjectGroupFlags unhandledFlags =
+         OBJECT_FLAG_SPARSE_INDEXES |
+         OBJECT_FLAG_LENGTH_OVERFLOW |
+-        OBJECT_FLAG_ITERATED;
+-
+-    // Don't optimize shift if the array may be non-extensible (this matters
+-    // when there are holes). We check this here because there's no
+-    // non-extensible ObjectElements flag so we would need an extra guard on the
+-    // BaseShape flags. For pop this doesn't matter, guarding on the SEALED
+-    // ObjectElements flag in JIT code is sufficient.
+-    if (mode == MArrayPopShift::Shift)
+-        unhandledFlags |= OBJECT_FLAG_NON_EXTENSIBLE_ELEMENTS;
++        OBJECT_FLAG_ITERATED |
++        OBJECT_FLAG_NON_EXTENSIBLE_ELEMENTS;
+ 
+     MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
+     TemporaryTypeSet* thisTypes = obj->resultTypeSet();
+     if (!thisTypes)
+         return InliningStatus_NotInlined;
+     const Class* clasp = thisTypes->getKnownClass(constraints());
+     if (clasp != &ArrayObject::class_)
+         return InliningStatus_NotInlined;
+diff --git a/js/src/vm/NativeObject-inl.h b/js/src/vm/NativeObject-inl.h
+--- a/js/src/vm/NativeObject-inl.h
++++ b/js/src/vm/NativeObject-inl.h
+@@ -192,33 +192,36 @@ NativeObject::initDenseElements(const Va
+ 
+     memcpy(reinterpret_cast<Value*>(elements_), src, count * sizeof(Value));
+     elementsRangeWriteBarrierPost(0, count);
+ }
+ 
+ inline bool
+ NativeObject::tryShiftDenseElements(uint32_t count)
+ {
++    MOZ_ASSERT(isExtensible());
++
+     ObjectElements* header = getElementsHeader();
+     if (header->initializedLength == count ||
+         count > ObjectElements::MaxShiftedElements ||
+         header->isCopyOnWrite() ||
+-        !isExtensible() ||
+         header->hasNonwritableArrayLength())
+     {
+         return false;
+     }
+ 
+     shiftDenseElementsUnchecked(count);
+     return true;
+ }
+ 
+ inline void
+ NativeObject::shiftDenseElementsUnchecked(uint32_t count)
+ {
++    MOZ_ASSERT(isExtensible());
++
+     ObjectElements* header = getElementsHeader();
+     MOZ_ASSERT(count > 0);
+     MOZ_ASSERT(count < header->initializedLength);
+ 
+     if (MOZ_UNLIKELY(header->numShiftedElements() + count > ObjectElements::MaxShiftedElements)) {
+         moveShiftedElements();
+         header = getElementsHeader();
+     }
+@@ -310,16 +313,17 @@ NativeObject::reverseDenseElementsNoPreB
+     elementsRangeWriteBarrierPost(0, length);
+ }
+ 
+ inline void
+ NativeObject::ensureDenseInitializedLengthNoPackedCheck(uint32_t index, uint32_t extra)
+ {
+     MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+     MOZ_ASSERT(!denseElementsAreFrozen());
++    MOZ_ASSERT(isExtensible() || (containsDenseElement(index) && extra == 1));
+ 
+     /*
+      * Ensure that the array's contents have been initialized up to index, and
+      * mark the elements through 'index + extra' as initialized in preparation
+      * for a write.
+      */
+     MOZ_ASSERT(index + extra <= getDenseCapacity());
+     uint32_t& initlen = getElementsHeader()->initializedLength;
+@@ -336,16 +340,18 @@ NativeObject::ensureDenseInitializedLeng
+         }
+         initlen = index + extra;
+     }
+ }
+ 
+ inline void
+ NativeObject::ensureDenseInitializedLength(JSContext* cx, uint32_t index, uint32_t extra)
+ {
++    MOZ_ASSERT(isExtensible());
++
+     if (writeToIndexWouldMarkNotPacked(index))
+         markDenseElementsNotPacked(cx);
+     ensureDenseInitializedLengthNoPackedCheck(index, extra);
+ }
+ 
+ DenseElementResult
+ NativeObject::extendDenseElements(JSContext* cx,
+                                   uint32_t requiredCapacity, uint32_t extra)
+@@ -375,16 +381,17 @@ NativeObject::extendDenseElements(JSCont
+ 
+     return DenseElementResult::Success;
+ }
+ 
+ inline DenseElementResult
+ NativeObject::ensureDenseElements(JSContext* cx, uint32_t index, uint32_t extra)
+ {
+     MOZ_ASSERT(isNative());
++    MOZ_ASSERT(isExtensible() || (containsDenseElement(index) && extra == 1));
+ 
+     if (writeToIndexWouldMarkNotPacked(index))
+         markDenseElementsNotPacked(cx);
+ 
+     if (!maybeCopyElementsForWrite(cx))
+         return DenseElementResult::Failure;
+ 
+     uint32_t currentCapacity = getDenseCapacity();
+diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
+--- a/js/src/vm/NativeObject.cpp
++++ b/js/src/vm/NativeObject.cpp
+@@ -661,16 +661,18 @@ NativeObject::maybeDensifySparseElements
+         return DenseElementResult::Failure;
+ 
+     return DenseElementResult::Success;
+ }
+ 
+ void
+ NativeObject::moveShiftedElements()
+ {
++    MOZ_ASSERT(isExtensible());
++
+     ObjectElements* header = getElementsHeader();
+     uint32_t numShifted = header->numShiftedElements();
+     MOZ_ASSERT(numShifted > 0);
+ 
+     uint32_t initLength = header->initializedLength;
+ 
+     ObjectElements* newHeader = static_cast<ObjectElements*>(getUnshiftedElementsHeader());
+     memmove(newHeader, header, sizeof(ObjectElements));
+@@ -693,43 +695,45 @@ NativeObject::moveShiftedElements()
+     // make sure prepareElementRangeForOverwrite is called on the shifted
+     // elements.
+     setDenseInitializedLength(initLength);
+ }
+ 
+ void
+ NativeObject::maybeMoveShiftedElements()
+ {
++    MOZ_ASSERT(isExtensible());
++
+     ObjectElements* header = getElementsHeader();
+     MOZ_ASSERT(header->numShiftedElements() > 0);
+ 
+     // Move the elements if less than a third of the allocated space is in use.
+     if (header->capacity < header->numAllocatedElements() / 3)
+         moveShiftedElements();
+ }
+ 
+ bool
+ NativeObject::tryUnshiftDenseElements(uint32_t count)
+ {
++    MOZ_ASSERT(isExtensible());
+     MOZ_ASSERT(count > 0);
+ 
+     ObjectElements* header = getElementsHeader();
+     uint32_t numShifted = header->numShiftedElements();
+ 
+     if (count > numShifted) {
+         // We need more elements than are easily available. Try to make space
+         // for more elements than we need (and shift the remaining ones) so
+         // that unshifting more elements later will be fast.
+ 
+         // Don't bother reserving elements if the number of elements is small.
+         // Note that there's no technical reason for using this particular
+         // limit.
+         if (header->initializedLength <= 10 ||
+             header->isCopyOnWrite() ||
+-            !isExtensible() ||
+             header->hasNonwritableArrayLength() ||
+             MOZ_UNLIKELY(count > ObjectElements::MaxShiftedElements))
+         {
+             return false;
+         }
+ 
+         MOZ_ASSERT(header->capacity >= header->initializedLength);
+         uint32_t unusedCapacity = header->capacity - header->initializedLength;
+@@ -967,17 +971,17 @@ NativeObject::growElements(JSContext* cx
+ 
+     return true;
+ }
+ 
+ void
+ NativeObject::shrinkElements(JSContext* cx, uint32_t reqCapacity)
+ {
+     MOZ_ASSERT(canHaveNonEmptyElements());
+-    MOZ_ASSERT(reqCapacity >= getDenseInitializedLength());
++    MOZ_ASSERT(reqCapacity >= getDenseInitializedLengthUnchecked());
+ 
+     if (denseElementsAreCopyOnWrite())
+         MOZ_CRASH();
+ 
+     if (!hasDynamicElements())
+         return;
+ 
+     // If we have shifted elements, consider moving them.
+diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
+--- a/js/src/vm/NativeObject.h
++++ b/js/src/vm/NativeObject.h
+@@ -518,17 +518,30 @@ class NativeObject : public ShapedObject
+     }
+     const Value& getDenseElement(uint32_t idx) const {
+         MOZ_ASSERT(idx < getDenseInitializedLength());
+         return elements_[idx];
+     }
+     bool containsDenseElement(uint32_t idx) {
+         return idx < getDenseInitializedLength() && !elements_[idx].isMagic(JS_ELEMENTS_HOLE);
+     }
++
++  private:
++    uint32_t getDenseInitializedLengthUnchecked() const {
++        return getElementsHeader()->initializedLength;
++    }
++
++  public:
+     uint32_t getDenseInitializedLength() const {
++        // If the following assertion fails, there's somewhere else a missing
++        // call to shrinkCapacityToInitializedLength(). Good luck for the hunt
++        // and finding the offender!
++        MOZ_ASSERT_IF(!isExtensible(),
++                      getElementsHeader()->initializedLength == getElementsHeader()->capacity);
++
+         return getElementsHeader()->initializedLength;
+     }
+     uint32_t getDenseCapacity() const {
+         return getElementsHeader()->capacity;
+     }
+ 
+     bool isSharedMemory() const {
+         return getElementsHeader()->isSharedMemory();
+@@ -1239,24 +1252,37 @@ class NativeObject : public ShapedObject
+         uint32_t len = header->initializedLength;
+         if (header->capacity > len) {
+             shrinkElements(cx, len);
+             header = getElementsHeader();
+             header->capacity = len;
+         }
+     }
+ 
+-    void setDenseInitializedLength(uint32_t length) {
++  private:
++    void setDenseInitializedLengthInternal(uint32_t length) {
+         MOZ_ASSERT(length <= getDenseCapacity());
+         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+         MOZ_ASSERT(!denseElementsAreFrozen());
+         prepareElementRangeForOverwrite(length, getElementsHeader()->initializedLength);
+         getElementsHeader()->initializedLength = length;
+     }
+ 
++  public:
++    void setDenseInitializedLength(uint32_t length) {
++        MOZ_ASSERT(isExtensible());
++        setDenseInitializedLengthInternal(length);
++    }
++
++    void setDenseInitializedLengthMaybeNonExtensible(JSContext* cx, uint32_t length) {
++        setDenseInitializedLengthInternal(length);
++        if (!isExtensible())
++            shrinkCapacityToInitializedLength(cx);
++    }
++
+     inline void ensureDenseInitializedLength(JSContext* cx,
+                                              uint32_t index, uint32_t extra);
+ 
+     void setDenseElement(uint32_t index, const Value& val) {
+         MOZ_ASSERT(index < getDenseInitializedLength());
+         MOZ_ASSERT(!denseElementsAreCopyOnWrite());
+         MOZ_ASSERT(!denseElementsAreFrozen());
+         checkStoredValue(val);

+ 121 - 0
frg/work-js/mozilla-release/patches/1480963-63a1.patch

@@ -0,0 +1,121 @@
+# HG changeset patch
+# User Andre Bargull <andre.bargull@gmail.com>
+# Date 1533569682 25200
+# Node ID aef4c2ae8559318068192b484aa82e1d6851bbd7
+# Parent  7d2518b0be268743ceed632c7949a26f9e601675
+Bug 1480963: Remove initialized-length is equal to capacity check in getDenseInitializedLength. r=jandem
+
+diff --git a/js/src/vm/JSObject-inl.h b/js/src/vm/JSObject-inl.h
+--- a/js/src/vm/JSObject-inl.h
++++ b/js/src/vm/JSObject-inl.h
+@@ -206,16 +206,23 @@ inline bool
+ js::IsExtensible(JSContext* cx, HandleObject obj, bool* extensible)
+ {
+     if (obj->is<ProxyObject>()) {
+         MOZ_ASSERT(!cx->helperThread());
+         return Proxy::isExtensible(cx, obj, extensible);
+     }
+ 
+     *extensible = obj->nonProxyIsExtensible();
++
++    // If the following assertion fails, there's somewhere else a missing
++    // call to shrinkCapacityToInitializedLength() which needs to be found and
++    // fixed.
++    MOZ_ASSERT_IF(obj->isNative() && !*extensible,
++                  obj->as<NativeObject>().getDenseInitializedLength() ==
++                  obj->as<NativeObject>().getDenseCapacity());
+     return true;
+ }
+ 
+ inline bool
+ js::HasProperty(JSContext* cx, HandleObject obj, PropertyName* name, bool* found)
+ {
+     RootedId id(cx, NameToId(name));
+     return HasProperty(cx, obj, id, found);
+diff --git a/js/src/vm/JSObject.cpp b/js/src/vm/JSObject.cpp
+--- a/js/src/vm/JSObject.cpp
++++ b/js/src/vm/JSObject.cpp
+@@ -2760,18 +2760,26 @@ js::SetPrototype(JSContext* cx, HandleOb
+ }
+ 
+ bool
+ js::PreventExtensions(JSContext* cx, HandleObject obj, ObjectOpResult& result)
+ {
+     if (obj->is<ProxyObject>())
+         return js::Proxy::preventExtensions(cx, obj, result);
+ 
+-    if (!obj->nonProxyIsExtensible())
++    if (!obj->nonProxyIsExtensible()) {
++        // If the following assertion fails, there's somewhere else a missing
++        // call to shrinkCapacityToInitializedLength() which needs to be found
++        // and fixed.
++        MOZ_ASSERT_IF(obj->isNative(),
++                      obj->as<NativeObject>().getDenseInitializedLength() ==
++                      obj->as<NativeObject>().getDenseCapacity());
++
+         return result.succeed();
++    }
+ 
+     if (!MaybeConvertUnboxedObjectToNative(cx, obj))
+         return false;
+ 
+     if (obj->isNative()) {
+         // Force lazy properties to be resolved.
+         if (!ResolveLazyProperties(cx, obj.as<NativeObject>()))
+             return false;
+diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
+--- a/js/src/vm/NativeObject.cpp
++++ b/js/src/vm/NativeObject.cpp
+@@ -971,17 +971,17 @@ NativeObject::growElements(JSContext* cx
+ 
+     return true;
+ }
+ 
+ void
+ NativeObject::shrinkElements(JSContext* cx, uint32_t reqCapacity)
+ {
+     MOZ_ASSERT(canHaveNonEmptyElements());
+-    MOZ_ASSERT(reqCapacity >= getDenseInitializedLengthUnchecked());
++    MOZ_ASSERT(reqCapacity >= getDenseInitializedLength());
+ 
+     if (denseElementsAreCopyOnWrite())
+         MOZ_CRASH();
+ 
+     if (!hasDynamicElements())
+         return;
+ 
+     // If we have shifted elements, consider moving them.
+diff --git a/js/src/vm/NativeObject.h b/js/src/vm/NativeObject.h
+--- a/js/src/vm/NativeObject.h
++++ b/js/src/vm/NativeObject.h
+@@ -518,30 +518,17 @@ class NativeObject : public ShapedObject
+     }
+     const Value& getDenseElement(uint32_t idx) const {
+         MOZ_ASSERT(idx < getDenseInitializedLength());
+         return elements_[idx];
+     }
+     bool containsDenseElement(uint32_t idx) {
+         return idx < getDenseInitializedLength() && !elements_[idx].isMagic(JS_ELEMENTS_HOLE);
+     }
+-
+-  private:
+-    uint32_t getDenseInitializedLengthUnchecked() const {
+-        return getElementsHeader()->initializedLength;
+-    }
+-
+-  public:
+     uint32_t getDenseInitializedLength() const {
+-        // If the following assertion fails, there's somewhere else a missing
+-        // call to shrinkCapacityToInitializedLength(). Good luck for the hunt
+-        // and finding the offender!
+-        MOZ_ASSERT_IF(!isExtensible(),
+-                      getElementsHeader()->initializedLength == getElementsHeader()->capacity);
+-
+         return getElementsHeader()->initializedLength;
+     }
+     uint32_t getDenseCapacity() const {
+         return getElementsHeader()->capacity;
+     }
+ 
+     bool isSharedMemory() const {
+         return getElementsHeader()->isSharedMemory();

+ 47 - 0
frg/work-js/mozilla-release/patches/1481032-63a1.patch

@@ -0,0 +1,47 @@
+# HG changeset patch
+# User Andre Bargull <andre.bargull@gmail.com>
+# Date 1533569736 25200
+# Node ID b20289e446893be662123b91104e35646408a578
+# Parent  aef4c2ae8559318068192b484aa82e1d6851bbd7
+Bug 1481032: Non-extensible arrays are already shrunk to capacity. r=jandem
+
+diff --git a/js/src/builtin/Array.cpp b/js/src/builtin/Array.cpp
+--- a/js/src/builtin/Array.cpp
++++ b/js/src/builtin/Array.cpp
+@@ -786,18 +786,22 @@ js::ArraySetLength(JSContext* cx, Handle
+             if (!arr->maybeCopyElementsForWrite(cx))
+                 return false;
+ 
+             uint32_t oldCapacity = arr->getDenseCapacity();
+             uint32_t oldInitializedLength = arr->getDenseInitializedLength();
+             MOZ_ASSERT(oldCapacity >= oldInitializedLength);
+             if (oldInitializedLength > newLen)
+                 arr->setDenseInitializedLengthMaybeNonExtensible(cx, newLen);
+-            if (oldCapacity > newLen)
+-                arr->shrinkElements(cx, newLen);
++            if (oldCapacity > newLen) {
++                if (arr->isExtensible())
++                    arr->shrinkElements(cx, newLen);
++                else
++                    MOZ_ASSERT(arr->getDenseInitializedLength() == arr->getDenseCapacity());
++            }
+ 
+             // We've done the work of deleting any dense elements needing
+             // deletion, and there are no sparse elements.  Thus we can skip
+             // straight to defining the length.
+             break;
+         }
+ 
+         // Step 15.
+diff --git a/js/src/jit-test/tests/auto-regress/bug1481032.js b/js/src/jit-test/tests/auto-regress/bug1481032.js
+new file mode 100644
+--- /dev/null
++++ b/js/src/jit-test/tests/auto-regress/bug1481032.js
+@@ -0,0 +1,6 @@
++x = [];
++x[6] = 0;
++Object.preventExtensions(x);
++
++// Don't assert.
++x.length = 1;
+

+ 0 - 0
frg/work-js/mozilla-release/patches/L-1485698-63a1.patch → frg/work-js/mozilla-release/patches/1485698-63a1.patch


+ 132 - 0
frg/work-js/mozilla-release/patches/1486173-1-63a1.patch

@@ -0,0 +1,132 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1535132580 -10800
+# Node ID 417d94835a0334fb79cfa35b4216739d067783f2
+# Parent  c6552a729ea7cca69c4ec87740cfc7393e52a597
+bug 1486173 - Part 1: Move error reporting out of StringToBigInt. r=jandem
+
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -404,26 +404,32 @@ js::ToBigInt(JSContext* cx, HandleValue 
+ {
+     RootedValue v(cx, val);
+ 
+     // Step 1.
+     if (!ToPrimitive(cx, JSTYPE_NUMBER, &v))
+         return nullptr;
+ 
+     // Step 2.
+-    // String conversions are not yet supported.
+     if (v.isBigInt())
+         return v.toBigInt();
+ 
+     if (v.isBoolean())
+         return BigInt::createFromBoolean(cx, v.toBoolean());
+ 
+     if (v.isString()) {
+         RootedString str(cx, v.toString());
+-        return StringToBigInt(cx, str, 0);
++        BigInt* bi;
++        JS_TRY_VAR_OR_RETURN_NULL(cx, bi, StringToBigInt(cx, str, 0));
++        if (!bi) {
++            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
++                                      JSMSG_BIGINT_INVALID_SYNTAX);
++            return nullptr;
++        }
++        return bi;
+     }
+ 
+     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_BIGINT);
+     return nullptr;
+ }
+ 
+ // ES 2019 draft 6.1.6
+ double
+@@ -514,38 +520,38 @@ js::StringToBigIntImpl(const Range<const
+     }
+ 
+     if (sign.valueOr(1) < 0)
+         mpz_neg(res->num_, res->num_);
+ 
+     return true;
+ }
+ 
+-BigInt*
++JS::Result<BigInt*, JS::OOM&>
+ js::StringToBigInt(JSContext* cx, HandleString str, uint8_t radix)
+ {
+     RootedBigInt res(cx, BigInt::create(cx));
++    if (!res)
++        return cx->alreadyReportedOOM();
+ 
+     JSLinearString* linear = str->ensureLinear(cx);
+     if (!linear)
+-        return nullptr;
++        return cx->alreadyReportedOOM();
+ 
+     {
+         JS::AutoCheckCannotGC nogc;
+         if (linear->hasLatin1Chars()) {
+             if (StringToBigIntImpl(linear->latin1Range(nogc), radix, res))
+-                return res;
++                return res.get();
+         } else {
+             if (StringToBigIntImpl(linear->twoByteRange(nogc), radix, res))
+-                return res;
++                return res.get();
+         }
+     }
+ 
+-    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+-                              JSMSG_BIGINT_INVALID_SYNTAX);
+     return nullptr;
+ }
+ 
+ size_t
+ BigInt::byteLength(BigInt* x)
+ {
+     if (mpz_sgn(x->num_) == 0)
+         return 0;
+diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
+--- a/js/src/vm/BigIntType.h
++++ b/js/src/vm/BigIntType.h
+@@ -12,16 +12,17 @@
+ 
+ #include <gmp.h>
+ 
+ #include "gc/Barrier.h"
+ #include "gc/GC.h"
+ #include "gc/Heap.h"
+ #include "js/AllocPolicy.h"
+ #include "js/GCHashTable.h"
++#include "js/Result.h"
+ #include "js/RootingAPI.h"
+ #include "js/TypeDecls.h"
+ #include "vm/StringType.h"
+ 
+ namespace js {
+ 
+ template <typename CharT>
+ static bool StringToBigIntImpl(const mozilla::Range<const CharT>& chars,
+@@ -116,17 +117,18 @@ static_assert(sizeof(BigInt) >= js::gc::
+ namespace js {
+ 
+ extern JSAtom*
+ BigIntToAtom(JSContext* cx, JS::BigInt* bi);
+ 
+ extern JS::BigInt*
+ NumberToBigInt(JSContext* cx, double d);
+ 
+-extern JS::BigInt*
++// Convert a string to a BigInt, returning nullptr if parsing fails.
++extern JS::Result<JS::BigInt*, JS::OOM&>
+ StringToBigInt(JSContext* cx, JS::Handle<JSString*> str, uint8_t radix);
+ 
+ extern JS::BigInt*
+ ToBigInt(JSContext* cx, JS::Handle<JS::Value> v);
+ 
+ } // namespace js
+ 
+ #endif
+

+ 110 - 0
frg/work-js/mozilla-release/patches/1486173-2-63a1.patch

@@ -0,0 +1,110 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1535132580 -10800
+# Node ID c62f40111003f108aa6bef93af6b289688ea1d97
+# Parent  24a3e06645b36a4c04d4450cd434fe61380761b1
+bug 1486173 - Part 2: Add BigInt methods for equality comparison. r=jandem
+
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -438,16 +438,75 @@ BigInt::numberValue(BigInt* x)
+     // mpz_get_d may cause a hardware overflow trap, so use
+     // mpz_get_d_2exp to get the fractional part and exponent
+     // separately.
+     signed long int exp;
+     double d = mpz_get_d_2exp(&exp, x->num_);
+     return ldexp(d, exp);
+ }
+ 
++bool
++BigInt::equal(BigInt* lhs, BigInt* rhs)
++{
++    if (lhs == rhs)
++        return true;
++    if (mpz_cmp(lhs->num_, rhs->num_) == 0)
++        return true;
++    return false;
++}
++
++bool
++BigInt::equal(BigInt* lhs, double rhs)
++{
++    // The result of mpz_cmp_d is undefined for comparisons to NaN.
++    if (mozilla::IsNaN(rhs))
++        return false;
++    if (mpz_cmp_d(lhs->num_, rhs) == 0)
++        return true;
++    return false;
++}
++
++// BigInt proposal section 3.2.5
++JS::Result<bool>
++BigInt::looselyEqual(JSContext* cx, HandleBigInt lhs, HandleValue rhs)
++{
++    // Step 1.
++    if (rhs.isBigInt())
++        return equal(lhs, rhs.toBigInt());
++
++    // Steps 2-5 (not applicable).
++
++    // Steps 6-7.
++    if (rhs.isString()) {
++        RootedBigInt rhsBigInt(cx);
++        RootedString rhsString(cx, rhs.toString());
++        MOZ_TRY_VAR(rhsBigInt, StringToBigInt(cx, rhsString, 0));
++        if (!rhsBigInt)
++            return false;
++        return equal(lhs, rhsBigInt);
++    }
++
++    // Steps 8-9 (not applicable).
++
++    // Steps 10-11.
++    if (rhs.isObject()) {
++        RootedValue rhsPrimitive(cx, rhs);
++        if (!ToPrimitive(cx, &rhsPrimitive))
++            return cx->alreadyReportedError();
++        return looselyEqual(cx, lhs, rhsPrimitive);
++    }
++
++    // Step 12.
++    if (rhs.isNumber())
++        return equal(lhs, rhs.toNumber());
++
++    // Step 13.
++    return false;
++}
++
+ JSLinearString*
+ BigInt::toString(JSContext* cx, BigInt* x, uint8_t radix)
+ {
+     MOZ_ASSERT(2 <= radix && radix <= 36);
+     // We need two extra chars for '\0' and potentially '-'.
+     size_t strSize = mpz_sizeinbase(x->num_, 10) + 2;
+     UniqueChars str(static_cast<char*>(js_malloc(strSize)));
+     if (!str) {
+diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
+--- a/js/src/vm/BigIntType.h
++++ b/js/src/vm/BigIntType.h
+@@ -92,16 +92,20 @@ class BigInt final : public js::gc::Tenu
+     static bool div(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool mod(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool pow(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool neg(JSContext* cx, Handle<Value> operand, MutableHandle<Value> res);
+ 
+     static double numberValue(BigInt* x);
+     static JSLinearString* toString(JSContext* cx, BigInt* x, uint8_t radix);
+ 
++    static bool equal(BigInt* lhs, BigInt* rhs);
++    static bool equal(BigInt* lhs, double rhs);
++    static JS::Result<bool> looselyEqual(JSContext* cx, HandleBigInt lhs, HandleValue rhs);
++
+     // Return the length in bytes of the representation used by
+     // writeBytes.
+     static size_t byteLength(BigInt* x);
+ 
+     // Write a little-endian representation of a BigInt's absolute value
+     // to a byte array.
+     static void writeBytes(BigInt* x, mozilla::RangedPtr<uint8_t> buffer);
+ };

+ 69 - 0
frg/work-js/mozilla-release/patches/1486173-3-63a1.patch

@@ -0,0 +1,69 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1535132580 -10800
+# Node ID be6163ba4a6a0b8491ccb1ba16aaabcffb448f37
+# Parent  c62f40111003f108aa6bef93af6b289688ea1d97
+bug 1486173 - Part 3: Implement BigInt support for equality operators. r=jandem
+
+diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
+--- a/js/src/vm/Interpreter.cpp
++++ b/js/src/vm/Interpreter.cpp
+@@ -862,16 +862,22 @@ EqualGivenSameType(JSContext* cx, Handle
+     MOZ_ASSERT(SameType(lval, rval));
+ 
+     if (lval.isString())
+         return EqualStrings(cx, lval.toString(), rval.toString(), equal);
+     if (lval.isDouble()) {
+         *equal = (lval.toDouble() == rval.toDouble());
+         return true;
+     }
++#ifdef ENABLE_BIGINT
++    if (lval.isBigInt()) {
++        *equal = BigInt::equal(lval.toBigInt(), rval.toBigInt());
++        return true;
++    }
++#endif
+     if (lval.isGCThing()) {  // objects or symbols
+         *equal = (lval.toGCThing() == rval.toGCThing());
+         return true;
+     }
+     *equal = lval.get().payloadAsRawUint32() == rval.get().payloadAsRawUint32();
+     MOZ_ASSERT_IF(lval.isUndefined() || lval.isNull(), *equal);
+     return true;
+ }
+@@ -965,16 +971,34 @@ js::LooselyEqual(JSContext* cx, HandleVa
+     // Step 11.
+     if (lval.isObject() && (rval.isString() || rval.isNumber() || rval.isSymbol())) {
+         RootedValue lvalue(cx, lval);
+         if (!ToPrimitive(cx, &lvalue))
+             return false;
+         return LooselyEqual(cx, lvalue, rval, result);
+     }
+ 
++#ifdef ENABLE_BIGINT
++    if (lval.isBigInt()) {
++        RootedBigInt lbi(cx, lval.toBigInt());
++        bool tmpResult;
++        JS_TRY_VAR_OR_RETURN_FALSE(cx, tmpResult, BigInt::looselyEqual(cx, lbi, rval));
++        *result = tmpResult;
++        return true;
++    }
++
++    if (rval.isBigInt()) {
++        RootedBigInt rbi(cx, rval.toBigInt());
++        bool tmpResult;
++        JS_TRY_VAR_OR_RETURN_FALSE(cx, tmpResult, BigInt::looselyEqual(cx, rbi, lval));
++        *result = tmpResult;
++        return true;
++    }
++#endif
++
+     // Step 12.
+     *result = false;
+     return true;
+ }
+ 
+ bool
+ js::StrictlyEqual(JSContext* cx, HandleValue lval, HandleValue rval, bool* equal)
+ {
+

+ 612 - 0
frg/work-js/mozilla-release/patches/1488698-2-PARTIAL-biginttype-64a1.patch

@@ -0,0 +1,612 @@
+# HG changeset patch
+# User Jan de Mooij <jdemooij@mozilla.com>
+# Date 1536225096 -7200
+# Node ID 9f1df06ee3066e30ca84e270e37087f632969ca6
+# Parent  d8f92aedbf923d168a4d228855cc331a8cf7dbe9
+Bug 1488698 - Always use braces for if/for/while statements in js/src/vm, part 2. r=mgaudet
+
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -71,80 +71,88 @@ BigInt::init()
+         mp_set_memory_functions(js_malloc, js_mp_realloc, js_mp_free);
+     }
+ }
+ 
+ BigInt*
+ BigInt::create(JSContext* cx)
+ {
+     BigInt* x = Allocate<BigInt>(cx);
+-    if (!x)
++    if (!x) {
+         return nullptr;
++    }
+     mpz_init(x->num_); // to zero
+     return x;
+ }
+ 
+ BigInt*
+ BigInt::createFromDouble(JSContext* cx, double d)
+ {
+     BigInt* x = Allocate<BigInt>(cx);
+-    if (!x)
++    if (!x) {
+         return nullptr;
++    }
+     mpz_init_set_d(x->num_, d);
+     return x;
+ }
+ 
+ BigInt*
+ BigInt::createFromBoolean(JSContext* cx, bool b)
+ {
+     BigInt* x = Allocate<BigInt>(cx);
+-    if (!x)
++    if (!x) {
+         return nullptr;
++    }
+     mpz_init_set_ui(x->num_, b);
+     return x;
+ }
+ 
+ BigInt*
+ BigInt::createFromBytes(JSContext* cx, int sign, void* bytes, size_t nbytes)
+ {
+     BigInt* x = Allocate<BigInt>(cx);
+-    if (!x)
++    if (!x) {
+         return nullptr;
++    }
+     // Initialize num_ to zero before calling mpz_import.
+     mpz_init(x->num_);
+ 
+-    if (nbytes == 0)
++    if (nbytes == 0) {
+         return x;
++    }
+ 
+     mpz_import(x->num_, nbytes,
+                -1, // order: least significant word first
+                1, // size: one byte per "word"
+                0, // endianness: native
+                0, // nail bits: none; use full words
+                bytes);
+-    if (sign < 0)
++    if (sign < 0) {
+         mpz_neg(x->num_, x->num_);
++    }
+     return x;
+ }
+ 
+ // BigInt proposal section 5.1.1
+ static bool
+ IsInteger(double d)
+ {
+     // Step 1 is an assertion checked by the caller.
+     // Step 2.
+-    if (!mozilla::IsFinite(d))
++    if (!mozilla::IsFinite(d)) {
+         return false;
++    }
+ 
+     // Step 3.
+     double i = JS::ToInteger(d);
+ 
+     // Step 4.
+-    if (i != d)
++    if (i != d) {
+         return false;
++    }
+ 
+     // Step 5.
+     return true;
+ }
+ 
+ // BigInt proposal section 5.1.2
+ BigInt*
+ js::NumberToBigInt(JSContext* cx, double d)
+@@ -160,51 +168,55 @@ js::NumberToBigInt(JSContext* cx, double
+     // Step 3.
+     return BigInt::createFromDouble(cx, d);
+ }
+ 
+ BigInt*
+ BigInt::copy(JSContext* cx, HandleBigInt x)
+ {
+     BigInt* bi = Allocate<BigInt>(cx);
+-    if (!bi)
++    if (!bi) {
+         return nullptr;
++    }
+     mpz_init_set(bi->num_, x->num_);
+     return bi;
+ }
+ 
+ // BigInt proposal section 1.1.7
+ BigInt*
+ BigInt::add(JSContext* cx, HandleBigInt x, HandleBigInt y)
+ {
+     BigInt* z = create(cx);
+-    if (!z)
++    if (!z) {
+         return nullptr;
++    }
+     mpz_add(z->num_, x->num_, y->num_);
+     return z;
+ }
+ 
+ // BigInt proposal section 1.1.8
+ BigInt*
+ BigInt::sub(JSContext* cx, HandleBigInt x, HandleBigInt y)
+ {
+     BigInt* z = create(cx);
+-    if (!z)
++    if (!z) {
+         return nullptr;
++    }
+     mpz_sub(z->num_, x->num_, y->num_);
+     return z;
+ }
+ 
+ // BigInt proposal section 1.1.4
+ BigInt*
+ BigInt::mul(JSContext* cx, HandleBigInt x, HandleBigInt y)
+ {
+     BigInt* z = create(cx);
+-    if (!z)
++    if (!z) {
+         return nullptr;
++    }
+     mpz_mul(z->num_, x->num_, y->num_);
+     return z;
+ }
+ 
+ // BigInt proposal section 1.1.5
+ BigInt*
+ BigInt::div(JSContext* cx, HandleBigInt x, HandleBigInt y)
+ {
+@@ -212,18 +224,19 @@ BigInt::div(JSContext* cx, HandleBigInt 
+     if (mpz_size(y->num_) == 0) {
+         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+                                   JSMSG_BIGINT_DIVISION_BY_ZERO);
+         return nullptr;
+     }
+ 
+     // Steps 2-3.
+     BigInt* z = create(cx);
+-    if (!z)
++    if (!z) {
+         return nullptr;
++    }
+     mpz_tdiv_q(z->num_, x->num_, y->num_);
+     return z;
+ }
+ 
+ // BigInt proposal section 1.1.6
+ BigInt*
+ BigInt::mod(JSContext* cx, HandleBigInt x, HandleBigInt y)
+ {
+@@ -231,18 +244,19 @@ BigInt::mod(JSContext* cx, HandleBigInt 
+     if (mpz_size(y->num_) == 0) {
+         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+                                   JSMSG_BIGINT_DIVISION_BY_ZERO);
+         return nullptr;
+     }
+ 
+     // Steps 2-4.
+     BigInt* z = create(cx);
+-    if (!z)
++    if (!z) {
+         return nullptr;
++    }
+     mpz_tdiv_r(z->num_, x->num_, y->num_);
+     return z;
+ }
+ 
+ // BigInt proposal section 1.1.3
+ BigInt*
+ BigInt::pow(JSContext* cx, HandleBigInt x, HandleBigInt y)
+ {
+@@ -258,30 +272,32 @@ BigInt::pow(JSContext* cx, HandleBigInt 
+         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+                                   JSMSG_BIGINT_TOO_LARGE);
+         return nullptr;
+     }
+     unsigned long int power = mpz_get_ui(y->num_);
+ 
+     // Steps 2-3.
+     BigInt* z = create(cx);
+-    if (!z)
++    if (!z) {
+         return nullptr;
++    }
+ 
+     mpz_pow_ui(z->num_, x->num_, power);
+     return z;
+ }
+ 
+ // BigInt proposal section 1.1.1
+ BigInt*
+ BigInt::neg(JSContext* cx, HandleBigInt x)
+ {
+     BigInt* res = create(cx);
+-    if (!res)
++    if (!res) {
+         return nullptr;
++    }
+     mpz_neg(res->num_, x->num_);
+     return res;
+ }
+ 
+ static bool
+ ValidBigIntOperands(JSContext* cx, HandleValue lhs, HandleValue rhs)
+ {
+     MOZ_ASSERT(lhs.isBigInt() || rhs.isBigInt());
+@@ -293,132 +309,148 @@ ValidBigIntOperands(JSContext* cx, Handl
+     }
+ 
+     return true;
+ }
+ 
+ bool
+ BigInt::add(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+ {
+-    if (!ValidBigIntOperands(cx, lhs, rhs))
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
+         return false;
++    }
+ 
+     RootedBigInt lhsBigInt(cx, lhs.toBigInt());
+     RootedBigInt rhsBigInt(cx, rhs.toBigInt());
+     BigInt* resBigInt = BigInt::add(cx, lhsBigInt, rhsBigInt);
+-    if (!resBigInt)
++    if (!resBigInt) {
+         return false;
++    }
+     res.setBigInt(resBigInt);
+     return true;
+ }
+ 
+ bool
+ BigInt::sub(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+ {
+-    if (!ValidBigIntOperands(cx, lhs, rhs))
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
+         return false;
++    }
+ 
+     RootedBigInt lhsBigInt(cx, lhs.toBigInt());
+     RootedBigInt rhsBigInt(cx, rhs.toBigInt());
+     BigInt* resBigInt = BigInt::sub(cx, lhsBigInt, rhsBigInt);
+-    if (!resBigInt)
++    if (!resBigInt) {
+         return false;
++    }
+     res.setBigInt(resBigInt);
+     return true;
+ }
+ 
+ bool
+ BigInt::mul(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+ {
+-    if (!ValidBigIntOperands(cx, lhs, rhs))
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
+         return false;
++    }
+ 
+     RootedBigInt lhsBigInt(cx, lhs.toBigInt());
+     RootedBigInt rhsBigInt(cx, rhs.toBigInt());
+     BigInt* resBigInt = BigInt::mul(cx, lhsBigInt, rhsBigInt);
+-    if (!resBigInt)
++    if (!resBigInt) {
+         return false;
++    }
+     res.setBigInt(resBigInt);
+     return true;
+ }
+ 
+ bool
+ BigInt::div(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+ {
+-    if (!ValidBigIntOperands(cx, lhs, rhs))
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
+         return false;
++    }
+ 
+     RootedBigInt lhsBigInt(cx, lhs.toBigInt());
+     RootedBigInt rhsBigInt(cx, rhs.toBigInt());
+     BigInt* resBigInt = BigInt::div(cx, lhsBigInt, rhsBigInt);
+-    if (!resBigInt)
++    if (!resBigInt) {
+         return false;
++    }
+     res.setBigInt(resBigInt);
+     return true;
+ }
+ 
+ bool
+ BigInt::mod(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+ {
+-    if (!ValidBigIntOperands(cx, lhs, rhs))
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
+         return false;
++    }
+ 
+     RootedBigInt lhsBigInt(cx, lhs.toBigInt());
+     RootedBigInt rhsBigInt(cx, rhs.toBigInt());
+     BigInt* resBigInt = BigInt::mod(cx, lhsBigInt, rhsBigInt);
+-    if (!resBigInt)
++    if (!resBigInt) {
+         return false;
++    }
+     res.setBigInt(resBigInt);
+     return true;
+ }
+ 
+ bool
+ BigInt::pow(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
+ {
+-    if (!ValidBigIntOperands(cx, lhs, rhs))
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
+         return false;
++    }
+ 
+     RootedBigInt lhsBigInt(cx, lhs.toBigInt());
+     RootedBigInt rhsBigInt(cx, rhs.toBigInt());
+     BigInt* resBigInt = BigInt::pow(cx, lhsBigInt, rhsBigInt);
+-    if (!resBigInt)
++    if (!resBigInt) {
+         return false;
++    }
+     res.setBigInt(resBigInt);
+     return true;
+ }
+ 
+ bool
+ BigInt::neg(JSContext* cx, HandleValue operand, MutableHandleValue res)
+ {
+     MOZ_ASSERT(operand.isBigInt());
+ 
+     RootedBigInt operandBigInt(cx, operand.toBigInt());
+     BigInt* resBigInt = BigInt::neg(cx, operandBigInt);
+-    if (!resBigInt)
++    if (!resBigInt) {
+         return false;
++    }
+     res.setBigInt(resBigInt);
+     return true;
+ }
+ 
+ // BigInt proposal section 7.3
+ BigInt*
+ js::ToBigInt(JSContext* cx, HandleValue val)
+ {
+     RootedValue v(cx, val);
+ 
+     // Step 1.
+-    if (!ToPrimitive(cx, JSTYPE_NUMBER, &v))
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, &v)) {
+         return nullptr;
++    }
+ 
+     // Step 2.
+-    if (v.isBigInt())
++    if (v.isBigInt()) {
+         return v.toBigInt();
++    }
+ 
+-    if (v.isBoolean())
++    if (v.isBoolean()) {
+         return BigInt::createFromBoolean(cx, v.toBoolean());
++    }
+ 
+     if (v.isString()) {
+         RootedString str(cx, v.toString());
+         BigInt* bi;
+         JS_TRY_VAR_OR_RETURN_NULL(cx, bi, StringToBigInt(cx, str, 0));
+         if (!bi) {
+             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+                                       JSMSG_BIGINT_INVALID_SYNTAX);
+@@ -441,67 +473,75 @@ BigInt::numberValue(BigInt* x)
+     signed long int exp;
+     double d = mpz_get_d_2exp(&exp, x->num_);
+     return ldexp(d, exp);
+ }
+ 
+ bool
+ BigInt::equal(BigInt* lhs, BigInt* rhs)
+ {
+-    if (lhs == rhs)
++    if (lhs == rhs) {
+         return true;
+-    if (mpz_cmp(lhs->num_, rhs->num_) == 0)
++    }
++    if (mpz_cmp(lhs->num_, rhs->num_) == 0) {
+         return true;
++    }
+     return false;
+ }
+ 
+ bool
+ BigInt::equal(BigInt* lhs, double rhs)
+ {
+     // The result of mpz_cmp_d is undefined for comparisons to NaN.
+-    if (mozilla::IsNaN(rhs))
++    if (mozilla::IsNaN(rhs)) {
+         return false;
+-    if (mpz_cmp_d(lhs->num_, rhs) == 0)
++    }
++    if (mpz_cmp_d(lhs->num_, rhs) == 0) {
+         return true;
++    }
+     return false;
+ }
+ 
+ // BigInt proposal section 3.2.5
+ JS::Result<bool>
+ BigInt::looselyEqual(JSContext* cx, HandleBigInt lhs, HandleValue rhs)
+ {
+     // Step 1.
+-    if (rhs.isBigInt())
++    if (rhs.isBigInt()) {
+         return equal(lhs, rhs.toBigInt());
++    }
+ 
+     // Steps 2-5 (not applicable).
+ 
+     // Steps 6-7.
+     if (rhs.isString()) {
+         RootedBigInt rhsBigInt(cx);
+         RootedString rhsString(cx, rhs.toString());
+         MOZ_TRY_VAR(rhsBigInt, StringToBigInt(cx, rhsString, 0));
+-        if (!rhsBigInt)
++        if (!rhsBigInt) {
+             return false;
++        }
+         return equal(lhs, rhsBigInt);
+     }
+ 
+     // Steps 8-9 (not applicable).
+ 
+     // Steps 10-11.
+     if (rhs.isObject()) {
+         RootedValue rhsPrimitive(cx, rhs);
+-        if (!ToPrimitive(cx, &rhsPrimitive))
++        if (!ToPrimitive(cx, &rhsPrimitive)) {
+             return cx->alreadyReportedError();
++        }
+         return looselyEqual(cx, lhs, rhsPrimitive);
+     }
+ 
+     // Step 12.
+-    if (rhs.isNumber())
++    if (rhs.isNumber()) {
+         return equal(lhs, rhs.toNumber());
++    }
+ 
+     // Step 13.
+     return false;
+ }
+ 
+ JSLinearString*
+ BigInt::toString(JSContext* cx, BigInt* x, uint8_t radix)
+ {
+@@ -548,77 +588,87 @@ js::StringToBigIntImpl(const Range<const
+             } else if (s[1] == 'o' || s[1] == 'O') {
+                 radix = 8;
+                 s += 2;
+             } else if (s[1] == 'b' || s[1] == 'B') {
+                 radix = 2;
+                 s += 2;
+             }
+ 
+-            if (radix != 10 && s == end)
++            if (radix != 10 && s == end) {
+                 return false;
++            }
+         }
+     }
+ 
+-    if (sign && radix != 10)
++    if (sign && radix != 10) {
+         return false;
++    }
+ 
+     mpz_set_ui(res->num_, 0);
+ 
+     for (; s < end; s++) {
+         unsigned digit;
+         if (!mozilla::IsAsciiAlphanumeric(s[0])) {
+             s = SkipSpace(s.get(), end.get());
+-            if (s == end)
++            if (s == end) {
+                 break;
++            }
+             return false;
+         }
+         digit = mozilla::AsciiAlphanumericToNumber(s[0]);
+-        if (digit >= radix)
++        if (digit >= radix) {
+             return false;
++        }
+         mpz_mul_ui(res->num_, res->num_, radix);
+         mpz_add_ui(res->num_, res->num_, digit);
+     }
+ 
+-    if (sign.valueOr(1) < 0)
++    if (sign.valueOr(1) < 0) {
+         mpz_neg(res->num_, res->num_);
++    }
+ 
+     return true;
+ }
+ 
+ JS::Result<BigInt*, JS::OOM&>
+ js::StringToBigInt(JSContext* cx, HandleString str, uint8_t radix)
+ {
+     RootedBigInt res(cx, BigInt::create(cx));
+-    if (!res)
++    if (!res) {
+         return cx->alreadyReportedOOM();
++    }
+ 
+     JSLinearString* linear = str->ensureLinear(cx);
+-    if (!linear)
++    if (!linear) {
+         return cx->alreadyReportedOOM();
++    }
+ 
+     {
+         JS::AutoCheckCannotGC nogc;
+         if (linear->hasLatin1Chars()) {
+-            if (StringToBigIntImpl(linear->latin1Range(nogc), radix, res))
++            if (StringToBigIntImpl(linear->latin1Range(nogc), radix, res)) {
+                 return res.get();
++            }
+         } else {
+-            if (StringToBigIntImpl(linear->twoByteRange(nogc), radix, res))
++            if (StringToBigIntImpl(linear->twoByteRange(nogc), radix, res)) {
+                 return res.get();
++            }
+         }
+     }
+ 
+     return nullptr;
+ }
+ 
+ size_t
+ BigInt::byteLength(BigInt* x)
+ {
+-    if (mpz_sgn(x->num_) == 0)
++    if (mpz_sgn(x->num_) == 0) {
+         return 0;
++    }
+     return JS_HOWMANY(mpz_sizeinbase(x->num_, 2), 8);
+ }
+ 
+ void
+ BigInt::writeBytes(BigInt* x, RangedPtr<uint8_t> buffer)
+ {
+ #ifdef DEBUG
+     // Check that the buffer being filled is large enough to hold the
+@@ -639,18 +689,19 @@ BigInt::finalize(js::FreeOp* fop)
+ {
+     mpz_clear(num_);
+ }
+ 
+ JSAtom*
+ js::BigIntToAtom(JSContext* cx, BigInt* bi)
+ {
+     JSString* str = BigInt::toString(cx, bi, 10);
+-    if (!str)
++    if (!str) {
+         return nullptr;
++    }
+     return AtomizeString(cx, str);
+ }
+ 
+ bool
+ BigInt::toBoolean()
+ {
+     return mpz_sgn(num_) != 0;
+ }

+ 279 - 0
frg/work-js/mozilla-release/patches/1490387-1-64a1.patch

@@ -0,0 +1,279 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1537242653 0
+# Node ID e69d3f0b89678aa1230f34f6877435e25d8acdca
+# Parent  7aa742bff8fbae4338e258a4477d5397d0d6f7ad
+bug 1490387 - Part 1: Add BigInt methods for bitwise operations. r=jandem
+
+Differential Revision: https://phabricator.services.mozilla.com/D5555
+
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -292,16 +292,105 @@ BigInt::neg(JSContext* cx, HandleBigInt 
+     BigInt* res = create(cx);
+     if (!res) {
+         return nullptr;
+     }
+     mpz_neg(res->num_, x->num_);
+     return res;
+ }
+ 
++// BigInt proposal section 1.1.9. BigInt::leftShift ( x, y )
++BigInt*
++BigInt::lsh(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    BigInt* z = create(cx);
++    if (!z) {
++        return nullptr;
++    }
++
++    // Step 1.
++    if (mpz_sgn(y->num_) < 0) {
++        mpz_fdiv_q_2exp(z->num_, x->num_, mpz_get_ui(y->num_));
++        return z;
++    }
++
++    // Step 2.
++    mpz_mul_2exp(z->num_, x->num_, mpz_get_ui(y->num_));
++    return z;
++}
++
++// BigInt proposal section 1.1.10. BigInt::signedRightShift ( x, y )
++BigInt*
++BigInt::rsh(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    BigInt* z = create(cx);
++    if (!z) {
++        return nullptr;
++    }
++
++    // Step 1 of BigInt::leftShift(x, -y).
++    if (mpz_sgn(y->num_) >= 0) {
++        mpz_fdiv_q_2exp(z->num_, x->num_, mpz_get_ui(y->num_));
++        return z;
++    }
++
++    // Step 2 of BigInt::leftShift(x, -y).
++    mpz_mul_2exp(z->num_, x->num_, mpz_get_ui(y->num_));
++    return z;
++}
++
++// BigInt proposal section 1.1.17. BigInt::bitwiseAND ( x, y )
++BigInt*
++BigInt::bitAnd(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    BigInt* z = create(cx);
++    if (!z) {
++        return nullptr;
++    }
++    mpz_and(z->num_, x->num_, y->num_);
++    return z;
++}
++
++// BigInt proposal section 1.1.18. BigInt::bitwiseXOR ( x, y )
++BigInt*
++BigInt::bitXor(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    BigInt* z = create(cx);
++    if (!z) {
++        return nullptr;
++    }
++    mpz_xor(z->num_, x->num_, y->num_);
++    return z;
++}
++
++// BigInt proposal section 1.1.19. BigInt::bitwiseOR ( x, y )
++BigInt*
++BigInt::bitOr(JSContext* cx, HandleBigInt x, HandleBigInt y)
++{
++    BigInt* z = create(cx);
++    if (!z) {
++        return nullptr;
++    }
++    mpz_ior(z->num_, x->num_, y->num_);
++    return z;
++}
++
++// BigInt proposal section 1.1.2. BigInt::bitwiseNOT ( x )
++BigInt*
++BigInt::bitNot(JSContext* cx, HandleBigInt x)
++{
++    BigInt* z = create(cx);
++    if (!z) {
++        return nullptr;
++    }
++    mpz_neg(z->num_, x->num_);
++    mpz_sub_ui(z->num_, z->num_, 1);
++    return z;
++}
++
+ static bool
+ ValidBigIntOperands(JSContext* cx, HandleValue lhs, HandleValue rhs)
+ {
+     MOZ_ASSERT(lhs.isBigInt() || rhs.isBigInt());
+ 
+     if (!lhs.isBigInt() || !rhs.isBigInt()) {
+         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
+                                   JSMSG_BIGINT_TO_NUMBER);
+@@ -422,16 +511,115 @@ BigInt::neg(JSContext* cx, HandleValue o
+     BigInt* resBigInt = BigInt::neg(cx, operandBigInt);
+     if (!resBigInt) {
+         return false;
+     }
+     res.setBigInt(resBigInt);
+     return true;
+ }
+ 
++bool
++BigInt::lsh(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
++        return false;
++    }
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::lsh(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt) {
++        return false;
++    }
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::rsh(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
++        return false;
++    }
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::rsh(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt) {
++        return false;
++    }
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::bitAnd(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
++        return false;
++    }
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::bitAnd(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt) {
++        return false;
++    }
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::bitXor(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
++        return false;
++    }
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::bitXor(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt) {
++        return false;
++    }
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::bitOr(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res)
++{
++    if (!ValidBigIntOperands(cx, lhs, rhs)) {
++        return false;
++    }
++
++    RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++    RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++    BigInt* resBigInt = BigInt::bitOr(cx, lhsBigInt, rhsBigInt);
++    if (!resBigInt) {
++        return false;
++    }
++    res.setBigInt(resBigInt);
++    return true;
++}
++
++bool
++BigInt::bitNot(JSContext* cx, HandleValue operand, MutableHandleValue res)
++{
++    MOZ_ASSERT(operand.isBigInt());
++
++    RootedBigInt operandBigInt(cx, operand.toBigInt());
++    BigInt* resBigInt = BigInt::bitNot(cx, operandBigInt);
++    if (!resBigInt) {
++        return false;
++    }
++    res.setBigInt(resBigInt);
++    return true;
++}
++
+ // BigInt proposal section 7.3
+ BigInt*
+ js::ToBigInt(JSContext* cx, HandleValue val)
+ {
+     RootedValue v(cx, val);
+ 
+     // Step 1.
+     if (!ToPrimitive(cx, JSTYPE_NUMBER, &v)) {
+diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
+--- a/js/src/vm/BigIntType.h
++++ b/js/src/vm/BigIntType.h
+@@ -79,28 +79,40 @@ class BigInt final : public js::gc::Tenu
+     static BigInt* copy(JSContext* cx, Handle<BigInt*> x);
+     static BigInt* add(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* sub(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* mul(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* div(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* mod(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* pow(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
+     static BigInt* neg(JSContext* cx, Handle<BigInt*> x);
++    static BigInt* lsh(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* rsh(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* bitAnd(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* bitXor(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* bitOr(JSContext* cx, Handle<BigInt*> x, Handle<BigInt*> y);
++    static BigInt* bitNot(JSContext* cx, Handle<BigInt*> x);
+ 
+     // Type-checking versions of arithmetic operations. These methods
+     // must be called with at least one BigInt operand. Binary
+     // operations with throw a TypeError if one of the operands is not a
+     // BigInt value.
+     static bool add(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool sub(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool mul(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool div(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool mod(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool pow(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
+     static bool neg(JSContext* cx, Handle<Value> operand, MutableHandle<Value> res);
++    static bool lsh(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool rsh(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool bitAnd(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool bitXor(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool bitOr(JSContext* cx, Handle<Value> lhs, Handle<Value> rhs, MutableHandle<Value> res);
++    static bool bitNot(JSContext* cx, Handle<Value> operand, MutableHandle<Value> res);
+ 
+     static double numberValue(BigInt* x);
+     static JSLinearString* toString(JSContext* cx, BigInt* x, uint8_t radix);
+ 
+     static bool equal(BigInt* lhs, BigInt* rhs);
+     static bool equal(BigInt* lhs, double rhs);
+     static JS::Result<bool> looselyEqual(JSContext* cx, HandleBigInt lhs, HandleValue rhs);
+ 
+

+ 84 - 0
frg/work-js/mozilla-release/patches/1490387-2-64a1.patch

@@ -0,0 +1,84 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1537242945 0
+# Node ID b74cf577c4015db47ad19fca177beb7f9221c8aa
+# Parent  4a02e23b3352d588d34977162dbc48d8645d85cb
+bug 1490387 - Part 2: Implement ToInt32OrBigInt operation. r=jandem
+
+Differential Revision: https://phabricator.services.mozilla.com/D5556
+
+diff --git a/js/src/jsnum.cpp b/js/src/jsnum.cpp
+--- a/js/src/jsnum.cpp
++++ b/js/src/jsnum.cpp
+@@ -1749,16 +1749,39 @@ js::ToInt32Slow(JSContext* cx, const Han
+     } else {
+         if (!ToNumberSlow(cx, v, &d))
+             return false;
+     }
+     *out = ToInt32(d);
+     return true;
+ }
+ 
++bool
++js::ToInt32OrBigIntSlow(JSContext* cx, MutableHandleValue vp)
++{
++    MOZ_ASSERT(!vp.isInt32());
++    if (vp.isDouble()) {
++        vp.setInt32(ToInt32(vp.toDouble()));
++        return true;
++    }
++
++    if (!ToNumeric(cx, vp)) {
++        return false;
++    }
++
++#ifdef ENABLE_BIGINT
++    if (vp.isBigInt()) {
++        return true;
++    }
++#endif
++
++    vp.setInt32(ToInt32(vp.toNumber()));
++    return true;
++}
++
+ JS_PUBLIC_API(bool)
+ js::ToUint32Slow(JSContext* cx, const HandleValue v, uint32_t* out)
+ {
+     MOZ_ASSERT(!v.isInt32());
+     double d;
+     if (v.isDouble()) {
+         d = v.toDouble();
+     } else {
+diff --git a/js/src/jsnum.h b/js/src/jsnum.h
+--- a/js/src/jsnum.h
++++ b/js/src/jsnum.h
+@@ -182,16 +182,28 @@ ToNumeric(JSContext* cx, JS::MutableHand
+         return true;
+ #ifdef ENABLE_BIGINT
+     if (vp.isBigInt())
+         return true;
+ #endif
+     return ToNumericSlow(cx, vp);
+ }
+ 
++bool
++ToInt32OrBigIntSlow(JSContext* cx, JS::MutableHandleValue vp);
++
++MOZ_ALWAYS_INLINE MOZ_MUST_USE bool
++ToInt32OrBigInt(JSContext* cx, JS::MutableHandleValue vp)
++{
++    if (vp.isInt32()) {
++        return true;
++    }
++    return ToInt32OrBigIntSlow(cx, vp);
++}
++
+ MOZ_MUST_USE bool
+ num_parseInt(JSContext* cx, unsigned argc, Value* vp);
+ 
+ }  /* namespace js */
+ 
+ /*
+  * Similar to strtod except that it replaces overflows with infinities of the
+  * correct sign, and underflows with zeros of the correct sign.  Guaranteed to

+ 904 - 0
frg/work-js/mozilla-release/patches/1490387-3-64a1.patch

@@ -0,0 +1,904 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1537243493 0
+# Node ID d5c22661c86025e0098509d8d6183c4af99214ce
+# Parent  b74cf577c4015db47ad19fca177beb7f9221c8aa
+bug 1490387 - Part 3: Implement BigInt support for bitwise operators. r=jandem
+
+Differential Revision: https://phabricator.services.mozilla.com/D5557
+
+diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
+--- a/js/src/jit/BaselineIC.cpp
++++ b/js/src/jit/BaselineIC.cpp
+@@ -6029,21 +6029,20 @@ DoUnaryArithFallback(JSContext* cx, Base
+ 
+     RootedScript script(cx, frame->script());
+     jsbytecode* pc = stub->icEntry()->pc(script);
+     JSOp op = JSOp(*pc);
+     FallbackICSpew(cx, stub, "UnaryArith(%s)", CodeName[op]);
+ 
+     switch (op) {
+       case JSOP_BITNOT: {
+-        int32_t result;
+-        if (!BitNot(cx, val, &result)) {
++        RootedValue valCopy(cx, val);
++        if (!BitNot(cx, &valCopy, res)) {
+             return false;
+         }
+-        res.setInt32(result);
+         break;
+       }
+       case JSOP_NEG: {
+         // We copy val here because the original value is needed below.
+         RootedValue valCopy(cx, val);
+         if (!NegOperation(cx, &valCopy, res)) {
+             return false;
+         }
+@@ -6160,57 +6159,47 @@ DoBinaryArithFallback(JSContext* cx, Bas
+         }
+         break;
+       case JSOP_POW:
+         if (!PowValues(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+         break;
+       case JSOP_BITOR: {
+-        int32_t result;
+-        if (!BitOr(cx, lhs, rhs, &result)) {
++        if (!BitOr(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+-        ret.setInt32(result);
+         break;
+       }
+       case JSOP_BITXOR: {
+-        int32_t result;
+-        if (!BitXor(cx, lhs, rhs, &result)) {
++        if (!BitXor(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+-        ret.setInt32(result);
+         break;
+       }
+       case JSOP_BITAND: {
+-        int32_t result;
+-        if (!BitAnd(cx, lhs, rhs, &result)) {
++        if (!BitAnd(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+-        ret.setInt32(result);
+         break;
+       }
+       case JSOP_LSH: {
+-        int32_t result;
+-        if (!BitLsh(cx, lhs, rhs, &result)) {
++        if (!BitLsh(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+-        ret.setInt32(result);
+         break;
+       }
+       case JSOP_RSH: {
+-        int32_t result;
+-        if (!BitRsh(cx, lhs, rhs, &result)) {
++        if (!BitRsh(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+-        ret.setInt32(result);
+         break;
+       }
+       case JSOP_URSH: {
+-        if (!UrshOperation(cx, lhs, rhs, ret)) {
++        if (!UrshOperation(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+         break;
+       }
+       default:
+         MOZ_CRASH("Unhandled baseline arith op");
+     }
+ 
+diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
+--- a/js/src/jit/CodeGenerator.cpp
++++ b/js/src/jit/CodeGenerator.cpp
+@@ -11293,27 +11293,27 @@ static const VMFunction ThrowInfoCodeGen
+ 
+ void
+ CodeGenerator::visitThrow(LThrow* lir)
+ {
+     pushArg(ToValue(lir, LThrow::Value));
+     callVM(ThrowInfoCodeGen, lir);
+ }
+ 
+-typedef bool (*BitNotFn)(JSContext*, HandleValue, int* p);
++typedef bool (*BitNotFn)(JSContext*, MutableHandleValue, MutableHandleValue);
+ static const VMFunction BitNotInfo = FunctionInfo<BitNotFn>(BitNot, "BitNot");
+ 
+ void
+ CodeGenerator::visitBitNotV(LBitNotV* lir)
+ {
+     pushArg(ToValue(lir, LBitNotV::Input));
+     callVM(BitNotInfo, lir);
+ }
+ 
+-typedef bool (*BitopFn)(JSContext*, HandleValue, HandleValue, int* p);
++typedef bool (*BitopFn)(JSContext*, MutableHandleValue, MutableHandleValue, MutableHandleValue);
+ static const VMFunction BitAndInfo = FunctionInfo<BitopFn>(BitAnd, "BitAnd");
+ static const VMFunction BitOrInfo = FunctionInfo<BitopFn>(BitOr, "BitOr");
+ static const VMFunction BitXorInfo = FunctionInfo<BitopFn>(BitXor, "BitXor");
+ static const VMFunction BitLhsInfo = FunctionInfo<BitopFn>(BitLsh, "BitLsh");
+ static const VMFunction BitRhsInfo = FunctionInfo<BitopFn>(BitRsh, "BitRsh");
+ 
+ void
+ CodeGenerator::visitBitOpV(LBitOpV* lir)
+diff --git a/js/src/jit/IonIC.cpp b/js/src/jit/IonIC.cpp
+--- a/js/src/jit/IonIC.cpp
++++ b/js/src/jit/IonIC.cpp
+@@ -562,21 +562,20 @@ IonUnaryArithIC::update(JSContext* cx, H
+ {
+     IonScript* ionScript = outerScript->ionScript();
+     RootedScript script(cx, ic->script());
+     jsbytecode* pc = ic->pc();
+     JSOp op = JSOp(*pc);
+ 
+     switch (op) {
+       case JSOP_BITNOT: {
+-        int32_t result;
+-        if (!BitNot(cx, val, &result)) {
++        RootedValue valCopy(cx, val);
++        if (!BitNot(cx, &valCopy, res)) {
+             return false;
+         }
+-        res.setInt32(result);
+         break;
+       }
+       case JSOP_NEG: {
+         // We copy val here because the original value is needed below.
+         RootedValue valCopy(cx, val);
+         if (!NegOperation(cx, &valCopy, res)) {
+             return false;
+         }
+@@ -644,37 +643,31 @@ IonBinaryArithIC::update(JSContext* cx, 
+         }
+         break;
+       case JSOP_MOD:
+         if (!ModValues(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+         break;
+       case JSOP_BITOR: {
+-        int32_t result;
+-        if (!BitOr(cx, lhs, rhs, &result)) {
++        if (!BitOr(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+-        ret.setInt32(result);
+         break;
+       }
+       case JSOP_BITXOR: {
+-        int32_t result;
+-        if (!BitXor(cx, lhs, rhs, &result)) {
++        if (!BitXor(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+-        ret.setInt32(result);
+         break;
+       }
+       case JSOP_BITAND: {
+-        int32_t result;
+-        if (!BitAnd(cx, lhs, rhs, &result)) {
++        if (!BitAnd(cx, &lhsCopy, &rhsCopy, ret)) {
+             return false;
+         }
+-        ret.setInt32(result);
+         break;
+       }
+      default:
+         MOZ_CRASH("Unhandled binary arith op");
+     }
+ 
+     if (ic->state().maybeTransition()) {
+         ic->discardStubs(cx->zone());
+diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp
+--- a/js/src/jit/MIR.cpp
++++ b/js/src/jit/MIR.cpp
+@@ -2672,43 +2672,47 @@ MBinaryBitwiseInstruction::foldUnnecessa
+ 
+ void
+ MBinaryBitwiseInstruction::infer(BaselineInspector*, jsbytecode*)
+ {
+     if (getOperand(0)->mightBeType(MIRType::Object) || getOperand(0)->mightBeType(MIRType::Symbol) ||
+         getOperand(1)->mightBeType(MIRType::Object) || getOperand(1)->mightBeType(MIRType::Symbol))
+     {
+         specialization_ = MIRType::None;
++        setResultType(MIRType::Value);
+     } else {
+         specializeAs(MIRType::Int32);
+     }
+ }
+ 
+ void
+ MBinaryBitwiseInstruction::specializeAs(MIRType type)
+ {
+     MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Int64);
+-    MOZ_ASSERT(this->type() == type);
++    MOZ_ASSERT(this->type() == MIRType::Value || this->type() == type);
+ 
+     specialization_ = type;
++    setResultType(type);
+ 
+     if (isBitOr() || isBitAnd() || isBitXor()) {
+         setCommutative();
+     }
+ }
+ 
+ void
+ MShiftInstruction::infer(BaselineInspector*, jsbytecode*)
+ {
+     if (getOperand(0)->mightBeType(MIRType::Object) || getOperand(1)->mightBeType(MIRType::Object) ||
+         getOperand(0)->mightBeType(MIRType::Symbol) || getOperand(1)->mightBeType(MIRType::Symbol))
+     {
+         specialization_ = MIRType::None;
++        setResultType(MIRType::Value);
+     } else {
+         specialization_ = MIRType::Int32;
++        setResultType(MIRType::Int32);
+     }
+ }
+ 
+ void
+ MUrsh::infer(BaselineInspector* inspector, jsbytecode* pc)
+ {
+     if (getOperand(0)->mightBeType(MIRType::Object) || getOperand(1)->mightBeType(MIRType::Object) ||
+         getOperand(0)->mightBeType(MIRType::Symbol) || getOperand(1)->mightBeType(MIRType::Symbol))
+@@ -3788,17 +3792,17 @@ MCompare::cacheOperandMightEmulateUndefi
+     markNoOperandEmulatesUndefined();
+ }
+ 
+ MBitNot*
+ MBitNot::NewInt32(TempAllocator& alloc, MDefinition* input)
+ {
+     MBitNot* ins = new(alloc) MBitNot(input);
+     ins->specialization_ = MIRType::Int32;
+-    MOZ_ASSERT(ins->type() == MIRType::Int32);
++    ins->setResultType(MIRType::Int32);
+     return ins;
+ }
+ 
+ MDefinition*
+ MBitNot::foldsTo(TempAllocator& alloc)
+ {
+     if (specialization_ != MIRType::Int32) {
+         return this;
+diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
+--- a/js/src/jit/MIR.h
++++ b/js/src/jit/MIR.h
+@@ -4836,17 +4836,17 @@ class MBitNot
+   : public MUnaryInstruction,
+     public BitwisePolicy::Data
+ {
+   protected:
+     explicit MBitNot(MDefinition* input)
+       : MUnaryInstruction(classOpcode, input)
+     {
+         specialization_ = MIRType::None;
+-        setResultType(MIRType::Int32);
++        setResultType(MIRType::Value);
+         setMovable();
+     }
+ 
+   public:
+     INSTRUCTION_HEADER(BitNot)
+     TRIVIAL_NEW_WRAPPERS
+ 
+     static MBitNot* NewInt32(TempAllocator& alloc, MDefinition* input);
+@@ -5000,17 +5000,17 @@ class MBinaryBitwiseInstruction
+     public BitwisePolicy::Data
+ {
+   protected:
+     MBinaryBitwiseInstruction(Opcode op, MDefinition* left, MDefinition* right, MIRType type)
+       : MBinaryInstruction(op, left, right), maskMatchesLeftRange(false),
+         maskMatchesRightRange(false)
+     {
+         MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Int64);
+-        setResultType(type);
++        setResultType(MIRType::Value);
+         setMovable();
+     }
+ 
+     void specializeAs(MIRType type);
+     bool maskMatchesLeftRange;
+     bool maskMatchesRightRange;
+ 
+   public:
+diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp
+--- a/js/src/jit/Recover.cpp
++++ b/js/src/jit/Recover.cpp
+@@ -158,24 +158,23 @@ MBitNot::writeRecoverData(CompactBufferW
+ 
+ RBitNot::RBitNot(CompactBufferReader& reader)
+ { }
+ 
+ bool
+ RBitNot::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue operand(cx, iter.read());
++    RootedValue result(cx);
+ 
+-    int32_t result;
+-    if (!js::BitNot(cx, operand, &result)) {
++    if (!js::BitNot(cx, &operand, &result)) {
+         return false;
+     }
+ 
+-    RootedValue rootedResult(cx, js::Int32Value(result));
+-    iter.storeInstructionResult(rootedResult);
++    iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+ MBitAnd::writeRecoverData(CompactBufferWriter& writer) const
+ {
+     MOZ_ASSERT(canRecoverOnBailout());
+     writer.writeUnsigned(uint32_t(RInstruction::Recover_BitAnd));
+@@ -185,25 +184,24 @@ MBitAnd::writeRecoverData(CompactBufferW
+ RBitAnd::RBitAnd(CompactBufferReader& reader)
+ { }
+ 
+ bool
+ RBitAnd::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue lhs(cx, iter.read());
+     RootedValue rhs(cx, iter.read());
+-    int32_t result;
++    RootedValue result(cx);
+     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
+ 
+-    if (!js::BitAnd(cx, lhs, rhs, &result)) {
++    if (!js::BitAnd(cx, &lhs, &rhs, &result)) {
+         return false;
+     }
+ 
+-    RootedValue rootedResult(cx, js::Int32Value(result));
+-    iter.storeInstructionResult(rootedResult);
++    iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+ MBitOr::writeRecoverData(CompactBufferWriter& writer) const
+ {
+     MOZ_ASSERT(canRecoverOnBailout());
+     writer.writeUnsigned(uint32_t(RInstruction::Recover_BitOr));
+@@ -213,25 +211,24 @@ MBitOr::writeRecoverData(CompactBufferWr
+ RBitOr::RBitOr(CompactBufferReader& reader)
+ {}
+ 
+ bool
+ RBitOr::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue lhs(cx, iter.read());
+     RootedValue rhs(cx, iter.read());
+-    int32_t result;
++    RootedValue result(cx);
+     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
+ 
+-    if (!js::BitOr(cx, lhs, rhs, &result)) {
++    if (!js::BitOr(cx, &lhs, &rhs, &result)) {
+         return false;
+     }
+ 
+-    RootedValue asValue(cx, js::Int32Value(result));
+-    iter.storeInstructionResult(asValue);
++    iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+ MBitXor::writeRecoverData(CompactBufferWriter& writer) const
+ {
+     MOZ_ASSERT(canRecoverOnBailout());
+     writer.writeUnsigned(uint32_t(RInstruction::Recover_BitXor));
+@@ -241,24 +238,23 @@ MBitXor::writeRecoverData(CompactBufferW
+ RBitXor::RBitXor(CompactBufferReader& reader)
+ { }
+ 
+ bool
+ RBitXor::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue lhs(cx, iter.read());
+     RootedValue rhs(cx, iter.read());
++    RootedValue result(cx);
+ 
+-    int32_t result;
+-    if (!js::BitXor(cx, lhs, rhs, &result)) {
++    if (!js::BitXor(cx, &lhs, &rhs, &result)) {
+         return false;
+     }
+ 
+-    RootedValue rootedResult(cx, js::Int32Value(result));
+-    iter.storeInstructionResult(rootedResult);
++    iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+ MLsh::writeRecoverData(CompactBufferWriter& writer) const
+ {
+     MOZ_ASSERT(canRecoverOnBailout());
+     writer.writeUnsigned(uint32_t(RInstruction::Recover_Lsh));
+@@ -268,25 +264,24 @@ MLsh::writeRecoverData(CompactBufferWrit
+ RLsh::RLsh(CompactBufferReader& reader)
+ {}
+ 
+ bool
+ RLsh::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue lhs(cx, iter.read());
+     RootedValue rhs(cx, iter.read());
+-    int32_t result;
++    RootedValue result(cx);
+     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
+ 
+-    if (!js::BitLsh(cx, lhs, rhs, &result)) {
++    if (!js::BitLsh(cx, &lhs, &rhs, &result)) {
+         return false;
+     }
+ 
+-    RootedValue asValue(cx, js::Int32Value(result));
+-    iter.storeInstructionResult(asValue);
++    iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+ MRsh::writeRecoverData(CompactBufferWriter& writer) const
+ {
+     MOZ_ASSERT(canRecoverOnBailout());
+     writer.writeUnsigned(uint32_t(RInstruction::Recover_Rsh));
+@@ -296,25 +291,24 @@ MRsh::writeRecoverData(CompactBufferWrit
+ RRsh::RRsh(CompactBufferReader& reader)
+ { }
+ 
+ bool
+ RRsh::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue lhs(cx, iter.read());
+     RootedValue rhs(cx, iter.read());
++    RootedValue result(cx);
+     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
+ 
+-    int32_t result;
+-    if (!js::BitRsh(cx, lhs, rhs, &result)) {
++    if (!js::BitRsh(cx, &lhs, &rhs, &result)) {
+         return false;
+     }
+ 
+-    RootedValue rootedResult(cx, js::Int32Value(result));
+-    iter.storeInstructionResult(rootedResult);
++    iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+ MUrsh::writeRecoverData(CompactBufferWriter& writer) const
+ {
+     MOZ_ASSERT(canRecoverOnBailout());
+     writer.writeUnsigned(uint32_t(RInstruction::Recover_Ursh));
+@@ -327,17 +321,17 @@ RUrsh::RUrsh(CompactBufferReader& reader
+ bool
+ RUrsh::recover(JSContext* cx, SnapshotIterator& iter) const
+ {
+     RootedValue lhs(cx, iter.read());
+     RootedValue rhs(cx, iter.read());
+     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
+ 
+     RootedValue result(cx);
+-    if (!js::UrshOperation(cx, lhs, rhs, &result)) {
++    if (!js::UrshOperation(cx, &lhs, &rhs, &result)) {
+         return false;
+     }
+ 
+     iter.storeInstructionResult(result);
+     return true;
+ }
+ 
+ bool
+diff --git a/js/src/jit/TypePolicy.cpp b/js/src/jit/TypePolicy.cpp
+--- a/js/src/jit/TypePolicy.cpp
++++ b/js/src/jit/TypePolicy.cpp
+@@ -409,17 +409,17 @@ TestPolicy::adjustInputs(TempAllocator& 
+ bool
+ BitwisePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
+ {
+     MIRType specialization = ins->typePolicySpecialization();
+     if (specialization == MIRType::None) {
+         return BoxInputsPolicy::staticAdjustInputs(alloc, ins);
+     }
+ 
+-    MOZ_ASSERT(ins->type() == specialization);
++    MOZ_ASSERT(ins->type() == MIRType::Value || ins->type() == specialization);
+     MOZ_ASSERT(specialization == MIRType::Int32 || specialization == MIRType::Double);
+ 
+     // This policy works for both unary and binary bitwise operations.
+     for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
+         MDefinition* in = ins->getOperand(i);
+         if (in->type() == MIRType::Int32) {
+             continue;
+         }
+diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h
+--- a/js/src/jit/shared/LIR-shared.h
++++ b/js/src/jit/shared/LIR-shared.h
+@@ -2857,17 +2857,17 @@ class LBitNotI : public LInstructionHelp
+     LIR_HEADER(BitNotI)
+ 
+     LBitNotI()
+       : LInstructionHelper(classOpcode)
+     {}
+ };
+ 
+ // Call a VM function to perform a BITNOT operation.
+-class LBitNotV : public LCallInstructionHelper<1, BOX_PIECES, 0>
++class LBitNotV : public LCallInstructionHelper<BOX_PIECES, BOX_PIECES, 0>
+ {
+   public:
+     LIR_HEADER(BitNotV)
+ 
+     static const size_t Input = 0;
+ 
+     explicit LBitNotV(const LBoxAllocation& input)
+       : LCallInstructionHelper(classOpcode)
+@@ -2922,17 +2922,17 @@ class LBitOpI64 : public LInstructionHel
+     }
+ 
+     JSOp bitop() const {
+         return op_;
+     }
+ };
+ 
+ // Call a VM function to perform a bitwise operation.
+-class LBitOpV : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
++class LBitOpV : public LCallInstructionHelper<BOX_PIECES, 2 * BOX_PIECES, 0>
+ {
+     JSOp jsop_;
+ 
+   public:
+     LIR_HEADER(BitOpV)
+ 
+     LBitOpV(JSOp jsop, const LBoxAllocation& lhs, const LBoxAllocation& rhs)
+       : LCallInstructionHelper(classOpcode),
+diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
+--- a/js/src/vm/Interpreter-inl.h
++++ b/js/src/vm/Interpreter-inl.h
+@@ -798,86 +798,134 @@ GreaterThanOperation(JSContext* cx, Muta
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ GreaterThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
+     RELATIONAL_OP(>=);
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-BitNot(JSContext* cx, HandleValue in, int* out)
++BitNot(JSContext* cx, MutableHandleValue in, MutableHandleValue out)
+ {
+-    int i;
+-    if (!ToInt32(cx, in, &i)) {
++    if (!ToInt32OrBigInt(cx, in)) {
+         return false;
+     }
+-    *out = ~i;
++
++#ifdef ENABLE_BIGINT
++    if (in.isBigInt()) {
++        return BigInt::bitNot(cx, in, out);
++    }
++#endif
++
++    out.setInt32(~in.toInt32());
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-BitXor(JSContext* cx, HandleValue lhs, HandleValue rhs, int* out)
++BitXor(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue out)
+ {
+-    int left, right;
+-    if (!ToInt32(cx, lhs, &left) || !ToInt32(cx, rhs, &right)) {
++    if (!ToInt32OrBigInt(cx, lhs) || !ToInt32OrBigInt(cx, rhs)) {
+         return false;
+     }
+-    *out = left ^ right;
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt()) {
++        return BigInt::bitXor(cx, lhs, rhs, out);
++    }
++#endif
++
++    out.setInt32(lhs.toInt32() ^ rhs.toInt32());
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-BitOr(JSContext* cx, HandleValue lhs, HandleValue rhs, int* out)
++BitOr(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue out)
+ {
+-    int left, right;
+-    if (!ToInt32(cx, lhs, &left) || !ToInt32(cx, rhs, &right)) {
++    if (!ToInt32OrBigInt(cx, lhs) || !ToInt32OrBigInt(cx, rhs)) {
+         return false;
+     }
+-    *out = left | right;
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt()) {
++        return BigInt::bitOr(cx, lhs, rhs, out);
++    }
++#endif
++
++    out.setInt32(lhs.toInt32() | rhs.toInt32());
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-BitAnd(JSContext* cx, HandleValue lhs, HandleValue rhs, int* out)
++BitAnd(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue out)
+ {
+-    int left, right;
+-    if (!ToInt32(cx, lhs, &left) || !ToInt32(cx, rhs, &right)) {
++    if (!ToInt32OrBigInt(cx, lhs) || !ToInt32OrBigInt(cx, rhs)) {
+         return false;
+     }
+-    *out = left & right;
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt()) {
++        return BigInt::bitAnd(cx, lhs, rhs, out);
++    }
++#endif
++
++    out.setInt32(lhs.toInt32() & rhs.toInt32());
++    return true;
++}
++
++static MOZ_ALWAYS_INLINE bool
++BitLsh(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue out)
++{
++    if (!ToInt32OrBigInt(cx, lhs) || !ToInt32OrBigInt(cx, rhs)) {
++        return false;
++    }
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt()) {
++        return BigInt::lsh(cx, lhs, rhs, out);
++    }
++#endif
++
++    out.setInt32(lhs.toInt32() << (rhs.toInt32() & 31));
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-BitLsh(JSContext* cx, HandleValue lhs, HandleValue rhs, int* out)
++BitRsh(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue out)
+ {
+-    int32_t left, right;
+-    if (!ToInt32(cx, lhs, &left) || !ToInt32(cx, rhs, &right)) {
++    if (!ToInt32OrBigInt(cx, lhs) || !ToInt32OrBigInt(cx, rhs)) {
+         return false;
+     }
+-    *out = uint32_t(left) << (right & 31);
++
++#ifdef ENABLE_BIGINT
++    if (lhs.isBigInt() || rhs.isBigInt()) {
++        return BigInt::rsh(cx, lhs, rhs, out);
++    }
++#endif
++
++    out.setInt32(lhs.toInt32() >> (rhs.toInt32() & 31));
+     return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-BitRsh(JSContext* cx, HandleValue lhs, HandleValue rhs, int* out)
++UrshOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue out)
+ {
+-    int32_t left, right;
+-    if (!ToInt32(cx, lhs, &left) || !ToInt32(cx, rhs, &right)) {
++#ifdef ENABLE_BIGINT
++    if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs)) {
+         return false;
+     }
+-    *out = left >> (right & 31);
+-    return true;
+-}
+ 
+-static MOZ_ALWAYS_INLINE bool
+-UrshOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue out)
+-{
++    if (lhs.isBigInt() || rhs.isBigInt()) {
++        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
++                                  JSMSG_BIGINT_TO_NUMBER);
++        return false;
++    }
++#endif
++
+     uint32_t left;
+-    int32_t  right;
++    int32_t right;
+     if (!ToUint32(cx, lhs, &left) || !ToInt32(cx, rhs, &right)) {
+         return false;
+     }
+     left >>= right & 31;
+     out.setNumber(uint32_t(left));
+     return true;
+ }
+ 
+diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
+--- a/js/src/vm/Interpreter.cpp
++++ b/js/src/vm/Interpreter.cpp
+@@ -2695,42 +2695,52 @@ CASE(JSOP_BINDNAME)
+ END_CASE(JSOP_BINDNAME)
+ 
+ CASE(JSOP_BINDVAR)
+ {
+     PUSH_OBJECT(REGS.fp()->varObj());
+ }
+ END_CASE(JSOP_BINDVAR)
+ 
+-#define BITWISE_OP(OP)                                                        \
+-    JS_BEGIN_MACRO                                                            \
+-        int32_t i, j;                                                         \
+-        if (!ToInt32(cx, REGS.stackHandleAt(-2), &i))                         \
+-            goto error;                                                       \
+-        if (!ToInt32(cx, REGS.stackHandleAt(-1), &j))                         \
+-            goto error;                                                       \
+-        i = i OP j;                                                           \
+-        REGS.sp--;                                                            \
+-        REGS.sp[-1].setInt32(i);                                              \
+-    JS_END_MACRO
+-
+ CASE(JSOP_BITOR)
+-    BITWISE_OP(|);
++{
++    MutableHandleValue lhs = REGS.stackHandleAt(-2);
++    MutableHandleValue rhs = REGS.stackHandleAt(-1);
++    MutableHandleValue res = REGS.stackHandleAt(-2);
++    if (!BitOr(cx, lhs, rhs, res)) {
++        goto error;
++    }
++    REGS.sp--;
++}
+ END_CASE(JSOP_BITOR)
+ 
+ CASE(JSOP_BITXOR)
+-    BITWISE_OP(^);
++{
++    MutableHandleValue lhs = REGS.stackHandleAt(-2);
++    MutableHandleValue rhs = REGS.stackHandleAt(-1);
++    MutableHandleValue res = REGS.stackHandleAt(-2);
++    if (!BitXor(cx, lhs, rhs, res)) {
++        goto error;
++    }
++    REGS.sp--;
++}
+ END_CASE(JSOP_BITXOR)
+ 
+ CASE(JSOP_BITAND)
+-    BITWISE_OP(&);
++{
++    MutableHandleValue lhs = REGS.stackHandleAt(-2);
++    MutableHandleValue rhs = REGS.stackHandleAt(-1);
++    MutableHandleValue res = REGS.stackHandleAt(-2);
++    if (!BitAnd(cx, lhs, rhs, res)) {
++        goto error;
++    }
++    REGS.sp--;
++}
+ END_CASE(JSOP_BITAND)
+ 
+-#undef BITWISE_OP
+-
+ CASE(JSOP_EQ)
+     if (!LooseEqualityOp<true>(cx, REGS)) {
+         goto error;
+     }
+ END_CASE(JSOP_EQ)
+ 
+ CASE(JSOP_NE)
+     if (!LooseEqualityOp<false>(cx, REGS)) {
+@@ -2829,44 +2839,46 @@ CASE(JSOP_GE)
+         goto error;
+     }
+     TRY_BRANCH_AFTER_COND(cond, 2);
+     REGS.sp[-2].setBoolean(cond);
+     REGS.sp--;
+ }
+ END_CASE(JSOP_GE)
+ 
+-#define SIGNED_SHIFT_OP(OP, TYPE)                                             \
+-    JS_BEGIN_MACRO                                                            \
+-        int32_t i, j;                                                         \
+-        if (!ToInt32(cx, REGS.stackHandleAt(-2), &i))                         \
+-            goto error;                                                       \
+-        if (!ToInt32(cx, REGS.stackHandleAt(-1), &j))                         \
+-            goto error;                                                       \
+-        i = TYPE(i) OP (j & 31);                                              \
+-        REGS.sp--;                                                            \
+-        REGS.sp[-1].setInt32(i);                                              \
+-    JS_END_MACRO
+-
+ CASE(JSOP_LSH)
+-    SIGNED_SHIFT_OP(<<, uint32_t);
++{
++    MutableHandleValue lhs = REGS.stackHandleAt(-2);
++    MutableHandleValue rhs = REGS.stackHandleAt(-1);
++    MutableHandleValue res = REGS.stackHandleAt(-2);
++    if (!BitLsh(cx, lhs, rhs, res)) {
++        goto error;
++    }
++    REGS.sp--;
++}
+ END_CASE(JSOP_LSH)
+ 
+ CASE(JSOP_RSH)
+-    SIGNED_SHIFT_OP(>>, int32_t);
++{
++    MutableHandleValue lhs = REGS.stackHandleAt(-2);
++    MutableHandleValue rhs = REGS.stackHandleAt(-1);
++    MutableHandleValue res = REGS.stackHandleAt(-2);
++    if (!BitRsh(cx, lhs, rhs, res)) {
++        goto error;
++    }
++    REGS.sp--;
++}
+ END_CASE(JSOP_RSH)
+ 
+-#undef SIGNED_SHIFT_OP
+-
+ CASE(JSOP_URSH)
+ {
+-    HandleValue lval = REGS.stackHandleAt(-2);
+-    HandleValue rval = REGS.stackHandleAt(-1);
++    MutableHandleValue lhs = REGS.stackHandleAt(-2);
++    MutableHandleValue rhs = REGS.stackHandleAt(-1);
+     MutableHandleValue res = REGS.stackHandleAt(-2);
+-    if (!UrshOperation(cx, lval, rval, res)) {
++    if (!UrshOperation(cx, lhs, rhs, res)) {
+         goto error;
+     }
+     REGS.sp--;
+ }
+ END_CASE(JSOP_URSH)
+ 
+ CASE(JSOP_ADD)
+ {
+@@ -2945,22 +2957,21 @@ CASE(JSOP_NOT)
+     bool cond = ToBoolean(REGS.stackHandleAt(-1));
+     REGS.sp--;
+     PUSH_BOOLEAN(!cond);
+ }
+ END_CASE(JSOP_NOT)
+ 
+ CASE(JSOP_BITNOT)
+ {
+-    int32_t i;
+-    HandleValue value = REGS.stackHandleAt(-1);
+-    if (!BitNot(cx, value, &i)) {
++    MutableHandleValue value = REGS.stackHandleAt(-1);
++    MutableHandleValue res = REGS.stackHandleAt(-1);
++    if (!BitNot(cx, value, res)) {
+         goto error;
+     }
+-    REGS.sp[-1].setInt32(i);
+ }
+ END_CASE(JSOP_BITNOT)
+ 
+ CASE(JSOP_NEG)
+ {
+     ReservedRooted<Value> val(&rootValue0, REGS.sp[-1]);
+     MutableHandleValue res = REGS.stackHandleAt(-1);
+     if (!NegOperation(cx, &val, res)) {
+

+ 392 - 0
frg/work-js/mozilla-release/patches/1492669-65a1.patch

@@ -0,0 +1,392 @@
+# HG changeset patch
+# User Robin Templeton <robin@igalia.com>
+# Date 1540461611 0
+# Node ID 81837314ba09b55b0dfe6423b8308e5808bafd32
+# Parent  d8f92aedbf923d168a4d228855cc331a8cf7dbe9
+bug 1492669 - Implement BigInt support for relational comparison operators. r=jandem
+
+Differential Revision: https://phabricator.services.mozilla.com/D6558
+
+diff --git a/js/src/vm/BigIntType.cpp b/js/src/vm/BigIntType.cpp
+--- a/js/src/vm/BigIntType.cpp
++++ b/js/src/vm/BigIntType.cpp
+@@ -23,16 +23,18 @@
+ #include "js/Initialization.h"
+ #include "js/Utility.h"
+ #include "vm/JSContext.h"
+ #include "vm/SelfHosting.h"
+ 
+ using namespace js;
+ 
+ using mozilla::Maybe;
++using mozilla::Some;
++using mozilla::Nothing;
+ using mozilla::Range;
+ using mozilla::RangedPtr;
+ 
+ // The following functions are wrappers for use with
+ // mp_set_memory_functions. GMP passes extra arguments to the realloc
+ // and free functions not needed by the JS allocation interface.
+ // js_malloc has the signature expected for GMP's malloc function, so no
+ // wrapper is required.
+@@ -497,16 +499,99 @@ BigInt::looselyEqual(JSContext* cx, Hand
+     // Step 12.
+     if (rhs.isNumber())
+         return equal(lhs, rhs.toNumber());
+ 
+     // Step 13.
+     return false;
+ }
+ 
++// BigInt proposal section 1.1.12. BigInt::lessThan ( x, y )
++bool
++BigInt::lessThan(BigInt* x, BigInt* y)
++{
++    return mpz_cmp(x->num_, y->num_) < 0;
++}
++
++Maybe<bool>
++BigInt::lessThan(BigInt* lhs, double rhs)
++{
++    if (mozilla::IsNaN(rhs)) {
++        return Maybe<bool>(Nothing());
++    }
++    return Some(mpz_cmp_d(lhs->num_, rhs) < 0);
++}
++
++Maybe<bool>
++BigInt::lessThan(double lhs, BigInt* rhs)
++{
++    if (mozilla::IsNaN(lhs)) {
++        return Maybe<bool>(Nothing());
++    }
++    return Some(-mpz_cmp_d(rhs->num_, lhs) < 0);
++}
++
++bool
++BigInt::lessThan(JSContext* cx, HandleBigInt lhs, HandleString rhs, Maybe<bool>& res)
++{
++    RootedBigInt rhsBigInt(cx);
++    JS_TRY_VAR_OR_RETURN_FALSE(cx, rhsBigInt, StringToBigInt(cx, rhs, 0));
++    if (!rhsBigInt) {
++        res = Nothing();
++        return true;
++    }
++    res = Some(lessThan(lhs, rhsBigInt));
++    return true;
++}
++
++bool
++BigInt::lessThan(JSContext* cx, HandleString lhs, HandleBigInt rhs, Maybe<bool>& res)
++{
++    RootedBigInt lhsBigInt(cx);
++    JS_TRY_VAR_OR_RETURN_FALSE(cx, lhsBigInt, StringToBigInt(cx, lhs, 0));
++    if (!lhsBigInt) {
++        res = Nothing();
++        return true;
++    }
++    res = Some(lessThan(lhsBigInt, rhs));
++    return true;
++}
++
++bool
++BigInt::lessThan(JSContext* cx, HandleValue lhs, HandleValue rhs, Maybe<bool>& res)
++{
++    if (lhs.isBigInt()) {
++        if (rhs.isString()) {
++            RootedBigInt lhsBigInt(cx, lhs.toBigInt());
++            RootedString rhsString(cx, rhs.toString());
++            return lessThan(cx, lhsBigInt, rhsString, res);
++        }
++
++        if (rhs.isNumber()) {
++            res = lessThan(lhs.toBigInt(), rhs.toNumber());
++            return true;
++        }
++
++        MOZ_ASSERT(rhs.isBigInt());
++        res = Some(lessThan(lhs.toBigInt(), rhs.toBigInt()));
++        return true;
++    }
++
++    MOZ_ASSERT(rhs.isBigInt());
++    if (lhs.isString()) {
++        RootedString lhsString(cx, lhs.toString());
++        RootedBigInt rhsBigInt(cx, rhs.toBigInt());
++        return lessThan(cx, lhsString, rhsBigInt, res);
++    }
++
++    MOZ_ASSERT(lhs.isNumber());
++    res = lessThan(lhs.toNumber(), rhs.toBigInt());
++    return true;
++}
++
+ JSLinearString*
+ BigInt::toString(JSContext* cx, BigInt* x, uint8_t radix)
+ {
+     MOZ_ASSERT(2 <= radix && radix <= 36);
+     // We need two extra chars for '\0' and potentially '-'.
+     size_t strSize = mpz_sizeinbase(x->num_, 10) + 2;
+     UniqueChars str(static_cast<char*>(js_malloc(strSize)));
+     if (!str) {
+diff --git a/js/src/vm/BigIntType.h b/js/src/vm/BigIntType.h
+--- a/js/src/vm/BigIntType.h
++++ b/js/src/vm/BigIntType.h
+@@ -96,16 +96,26 @@ class BigInt final : public js::gc::Tenu
+ 
+     static double numberValue(BigInt* x);
+     static JSLinearString* toString(JSContext* cx, BigInt* x, uint8_t radix);
+ 
+     static bool equal(BigInt* lhs, BigInt* rhs);
+     static bool equal(BigInt* lhs, double rhs);
+     static JS::Result<bool> looselyEqual(JSContext* cx, HandleBigInt lhs, HandleValue rhs);
+ 
++    static bool lessThan(BigInt* x, BigInt* y);
++
++    // These methods return Nothing when the non-BigInt operand is NaN
++    // or a string that can't be interpreted as a BigInt.
++    static mozilla::Maybe<bool> lessThan(BigInt* lhs, double rhs);
++    static mozilla::Maybe<bool> lessThan(double lhs, BigInt* rhs);
++    static bool lessThan(JSContext* cx, HandleBigInt lhs, HandleString rhs, mozilla::Maybe<bool>& res);
++    static bool lessThan(JSContext* cx, HandleString lhs, HandleBigInt rhs, mozilla::Maybe<bool>& res);
++    static bool lessThan(JSContext* cx, HandleValue lhs, HandleValue rhs, mozilla::Maybe<bool>& res);
++
+     // Return the length in bytes of the representation used by
+     // writeBytes.
+     static size_t byteLength(BigInt* x);
+ 
+     // Write a little-endian representation of a BigInt's absolute value
+     // to a byte array.
+     static void writeBytes(BigInt* x, mozilla::RangedPtr<uint8_t> buffer);
+ };
+diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h
+--- a/js/src/vm/Interpreter-inl.h
++++ b/js/src/vm/Interpreter-inl.h
+@@ -4,16 +4,18 @@
+  * License, v. 2.0. If a copy of the MPL was not distributed with this
+  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+ 
+ #ifndef vm_Interpreter_inl_h
+ #define vm_Interpreter_inl_h
+ 
+ #include "vm/Interpreter.h"
+ 
++#include "mozilla/Maybe.h"
++
+ #include "jsnum.h"
+ 
+ #include "builtin/String.h"
+ #include "jit/Ion.h"
+ #include "vm/ArgumentsObject.h"
+ #include "vm/JSCompartment.h"
+ 
+ #include "vm/EnvironmentObject-inl.h"
+@@ -703,61 +705,173 @@ ProcessCallSiteObjOperation(JSContext* c
+         if (!FreezeObject(cx, raw))
+             return false;
+         if (!FreezeObject(cx, cso))
+             return false;
+     }
+     return true;
+ }
+ 
+-#define RELATIONAL_OP(OP)                                                     \
+-    JS_BEGIN_MACRO                                                            \
+-        /* Optimize for two int-tagged operands (typical loop control). */    \
+-        if (lhs.isInt32() && rhs.isInt32()) {                                 \
+-            *res = lhs.toInt32() OP rhs.toInt32();                            \
+-        } else {                                                              \
+-            if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs))                         \
+-                return false;                                                 \
+-            if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs))                         \
+-                return false;                                                 \
+-            if (lhs.isString() && rhs.isString()) {                           \
+-                JSString* l = lhs.toString();                                 \
+-                JSString* r = rhs.toString();                                 \
+-                int32_t result;                                               \
+-                if (!CompareStrings(cx, l, r, &result))                       \
+-                    return false;                                             \
+-                *res = result OP 0;                                           \
+-            } else {                                                          \
+-                double l, r;                                                  \
+-                if (!ToNumber(cx, lhs, &l) || !ToNumber(cx, rhs, &r))         \
+-                    return false;                                             \
+-                *res = (l OP r);                                              \
+-            }                                                                 \
+-        }                                                                     \
+-        return true;                                                          \
+-    JS_END_MACRO
++// BigInt proposal 3.2.4 Abstract Relational Comparison
++// Returns Nothing when at least one operand is a NaN, or when
++// ToNumeric or StringToBigInt can't interpret a string as a numeric
++// value. (These cases correspond to a NaN result in the spec.)
++// Otherwise, return a boolean to indicate whether lhs is less than
++// rhs. The operands must be primitives; the caller is responsible for
++// evaluating them in the correct order.
++static MOZ_ALWAYS_INLINE bool
++LessThanImpl(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs,
++             mozilla::Maybe<bool>& res)
++{
++    // Steps 1 and 2 are performed by the caller.
++
++    // Step 3.
++    if (lhs.isString() && rhs.isString()) {
++        JSString* l = lhs.toString();
++        JSString* r = rhs.toString();
++        int32_t result;
++        if (!CompareStrings(cx, l, r, &result)) {
++            return false;
++        }
++        res = mozilla::Some(result < 0);
++        return true;
++    }
++
++#ifdef ENABLE_BIGINT
++    // Step 4a.
++    if (lhs.isBigInt() && rhs.isString()) {
++        return BigInt::lessThan(cx, lhs, rhs, res);
++    }
+ 
+-static MOZ_ALWAYS_INLINE bool
+-LessThanOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
+-    RELATIONAL_OP(<);
++    // Step 4b.
++    if (lhs.isString() && rhs.isBigInt()) {
++        return BigInt::lessThan(cx, lhs, rhs, res);
++    }
++#endif
++
++    // Steps 4c and 4d.
++    if (!ToNumeric(cx, lhs) || !ToNumeric(cx, rhs)) {
++        return false;
++    }
++
++#ifdef ENABLE_BIGINT
++    // Steps 4e-j.
++    if (lhs.isBigInt() || rhs.isBigInt()) {
++        return BigInt::lessThan(cx, lhs, rhs, res);
++    }
++#endif
++
++    // Step 4e for Number operands.
++    MOZ_ASSERT(lhs.isNumber() && rhs.isNumber());
++    double lhsNum = lhs.toNumber();
++    double rhsNum = rhs.toNumber();
++
++    if (mozilla::IsNaN(lhsNum) || mozilla::IsNaN(rhsNum)) {
++        res = mozilla::Maybe<bool>(mozilla::Nothing());
++        return true;
++    }
++
++    res = mozilla::Some(lhsNum < rhsNum);
++    return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-LessThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
+-    RELATIONAL_OP(<=);
++LessThanOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
++{
++    if (lhs.isInt32() && rhs.isInt32()) {
++        *res = lhs.toInt32() < rhs.toInt32();
++        return true;
++    }
++
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) {
++        return false;
++    }
++
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) {
++        return false;
++    }
++
++    mozilla::Maybe<bool> tmpResult;
++    if (!LessThanImpl(cx, lhs, rhs, tmpResult)) {
++        return false;
++    }
++    *res = tmpResult.valueOr(false);
++    return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-GreaterThanOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
+-    RELATIONAL_OP(>);
++LessThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
++{
++    if (lhs.isInt32() && rhs.isInt32()) {
++        *res = lhs.toInt32() <= rhs.toInt32();
++        return true;
++    }
++
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) {
++        return false;
++    }
++
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) {
++        return false;
++    }
++
++    mozilla::Maybe<bool> tmpResult;
++    if (!LessThanImpl(cx, rhs, lhs, tmpResult)) {
++        return false;
++    }
++    *res = !tmpResult.valueOr(true);
++    return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+-GreaterThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res) {
+-    RELATIONAL_OP(>=);
++GreaterThanOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
++{
++    if (lhs.isInt32() && rhs.isInt32()) {
++        *res = lhs.toInt32() > rhs.toInt32();
++        return true;
++    }
++
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) {
++        return false;
++    }
++
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) {
++        return false;
++    }
++
++    mozilla::Maybe<bool> tmpResult;
++    if (!LessThanImpl(cx, rhs, lhs, tmpResult)) {
++        return false;
++    }
++    *res = tmpResult.valueOr(false);
++    return true;
++}
++
++static MOZ_ALWAYS_INLINE bool
++GreaterThanOrEqualOperation(JSContext* cx, MutableHandleValue lhs, MutableHandleValue rhs, bool* res)
++{
++    if (lhs.isInt32() && rhs.isInt32()) {
++        *res = lhs.toInt32() >= rhs.toInt32();
++        return true;
++    }
++
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, lhs)) {
++        return false;
++    }
++
++    if (!ToPrimitive(cx, JSTYPE_NUMBER, rhs)) {
++        return false;
++    }
++
++    mozilla::Maybe<bool> tmpResult;
++    if (!LessThanImpl(cx, lhs, rhs, tmpResult)) {
++        return false;
++    }
++    *res = !tmpResult.valueOr(true);
++    return true;
+ }
+ 
+ static MOZ_ALWAYS_INLINE bool
+ BitNot(JSContext* cx, HandleValue in, int* out)
+ {
+     int i;
+     if (!ToInt32(cx, in, &i))
+         return false;

+ 0 - 360
frg/work-js/mozilla-release/patches/L-1429656-59a1.patch

@@ -1,360 +0,0 @@
-# HG changeset patch
-# User Jessica Jong <jjong@mozilla.com>
-# Date 1515998567 -28800
-# Node ID 52397f10a40b2dc2c2e07440e1b9c986eec112fa
-# Parent  b584c2d1fb904386cd94f1da1169d115e641fa9a
-Bug 1429656 - Implement ShadowRoot.activeElement. r=smaug
-
-diff --git a/dom/base/DocumentOrShadowRoot.cpp b/dom/base/DocumentOrShadowRoot.cpp
---- a/dom/base/DocumentOrShadowRoot.cpp
-+++ b/dom/base/DocumentOrShadowRoot.cpp
-@@ -1,16 +1,18 @@
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* vim: set ts=8 sts=2 et sw=2 tw=80: */
- /* This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #include "DocumentOrShadowRoot.h"
- #include "mozilla/dom/StyleSheetList.h"
-+#include "nsDocument.h"
-+#include "nsFocusManager.h"
- 
- namespace mozilla {
- namespace dom {
- 
- DocumentOrShadowRoot::DocumentOrShadowRoot(mozilla::dom::ShadowRoot& aShadowRoot)
-   : mAsNode(aShadowRoot)
-   , mKind(Kind::ShadowRoot)
- {}
-@@ -80,10 +82,53 @@ DocumentOrShadowRoot::GetElementsByTagNa
- }
- 
- already_AddRefed<nsContentList>
- DocumentOrShadowRoot::GetElementsByClassName(const nsAString& aClasses)
- {
-   return nsContentUtils::GetElementsByClassName(&AsNode(), aClasses);
- }
- 
-+nsIContent*
-+DocumentOrShadowRoot::Retarget(nsIContent* aContent) const
-+{
-+  for (nsIContent* cur = aContent;
-+       cur;
-+       cur = cur->GetContainingShadowHost()) {
-+    if (cur->SubtreeRoot() == &AsNode()) {
-+      return cur;
-+    }
-+  }
-+  return nullptr;
-+}
-+
-+Element*
-+DocumentOrShadowRoot::GetRetargetedFocusedElement()
-+{
-+  if (nsCOMPtr<nsPIDOMWindowOuter> window = AsNode().OwnerDoc()->GetWindow()) {
-+    nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
-+    nsIContent* focusedContent =
-+      nsFocusManager::GetFocusedDescendant(window,
-+                                           nsFocusManager::eOnlyCurrentWindow,
-+                                           getter_AddRefs(focusedWindow));
-+    // be safe and make sure the element is from this document
-+    if (focusedContent && focusedContent->OwnerDoc() == AsNode().OwnerDoc()) {
-+      if (focusedContent->ChromeOnlyAccess()) {
-+        focusedContent = focusedContent->FindFirstNonChromeOnlyAccessContent();
-+      }
-+
-+      if (focusedContent) {
-+        if (!nsDocument::IsWebComponentsEnabled(focusedContent)) {
-+          return focusedContent->AsElement();
-+        }
-+
-+        if (nsIContent* retarget = Retarget(focusedContent)) {
-+          return retarget->AsElement();
-+        }
-+      }
-+    }
-+  }
-+
-+  return nullptr;
-+}
-+
- }
- }
-diff --git a/dom/base/DocumentOrShadowRoot.h b/dom/base/DocumentOrShadowRoot.h
---- a/dom/base/DocumentOrShadowRoot.h
-+++ b/dom/base/DocumentOrShadowRoot.h
-@@ -109,16 +109,25 @@ public:
-                          mozilla::ErrorResult&);
- 
-   already_AddRefed<nsContentList>
-   GetElementsByClassName(const nsAString& aClasses);
- 
-   ~DocumentOrShadowRoot() = default;
- 
- protected:
-+  nsIContent* Retarget(nsIContent* aContent) const;
-+
-+  /**
-+   * If focused element's subtree root is this document or shadow root, return
-+   * focused element, otherwise, get the shadow host recursively until the
-+   * shadow host's subtree root is this document or shadow root.
-+   */
-+  Element* GetRetargetedFocusedElement();
-+
-   nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheets;
-   RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;
- 
-   /*
-    * mIdentifierMap works as follows for IDs:
-    * 1) Attribute changes affect the table immediately (removing and adding
-    *    entries as needed).
-    * 2) Removals from the DOM affect the table immediately
-diff --git a/dom/base/FragmentOrElement.cpp b/dom/base/FragmentOrElement.cpp
---- a/dom/base/FragmentOrElement.cpp
-+++ b/dom/base/FragmentOrElement.cpp
-@@ -1112,16 +1112,25 @@ FragmentOrElement::IsLink(nsIURI** aURI)
- nsXBLBinding*
- FragmentOrElement::DoGetXBLBinding() const
- {
-   MOZ_ASSERT(HasFlag(NODE_MAY_BE_IN_BINDING_MNGR));
-   const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
-   return slots ? slots->mXBLBinding.get() : nullptr;
- }
- 
-+nsIContent*
-+nsIContent::GetContainingShadowHost() const
-+{
-+  if (mozilla::dom::ShadowRoot* shadow = GetContainingShadow()) {
-+    return shadow->GetHost();
-+  }
-+  return nullptr;
-+}
-+
- void
- nsIContent::SetAssignedSlot(HTMLSlotElement* aSlot)
- {
-   ExtendedContentSlots()->mAssignedSlot = aSlot;
- }
- 
- void
- nsIContent::SetXBLInsertionPoint(nsIContent* aContent)
-diff --git a/dom/base/ShadowRoot.cpp b/dom/base/ShadowRoot.cpp
---- a/dom/base/ShadowRoot.cpp
-+++ b/dom/base/ShadowRoot.cpp
-@@ -449,16 +449,22 @@ void
- ShadowRoot::DistributeAllNodes()
- {
- 
-   //XXX Handle <slot>.
- 
-   DistributionChanged();
- }
- 
-+Element*
-+ShadowRoot::GetActiveElement()
-+{
-+  return GetRetargetedFocusedElement();
-+}
-+
- void
- ShadowRoot::GetInnerHTML(nsAString& aInnerHTML)
- {
-   GetMarkup(false, aInnerHTML);
- }
- 
- void
- ShadowRoot::SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError)
-diff --git a/dom/base/ShadowRoot.h b/dom/base/ShadowRoot.h
---- a/dom/base/ShadowRoot.h
-+++ b/dom/base/ShadowRoot.h
-@@ -132,16 +132,18 @@ public:
- 
-   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
- 
-   void AddToIdTable(Element* aElement, nsAtom* aId);
-   void RemoveFromIdTable(Element* aElement, nsAtom* aId);
- 
-   // WebIDL methods.
-   using mozilla::dom::DocumentOrShadowRoot::GetElementById;
-+
-+  Element* GetActiveElement();
-   void GetInnerHTML(nsAString& aInnerHTML);
-   void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
-   void StyleSheetChanged();
- 
-   bool IsComposedDocParticipant() { return mIsComposedDocParticipant; }
-   void SetIsComposedDocParticipant(bool aIsComposedDocParticipant)
-   {
-     mIsComposedDocParticipant = aIsComposedDocParticipant;
-diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
---- a/dom/base/nsDocument.cpp
-+++ b/dom/base/nsDocument.cpp
-@@ -3534,31 +3534,19 @@ nsDocument::GetActiveElement(nsIDOMEleme
-   el.forget(aElement);
-   return NS_OK;
- }
- 
- Element*
- nsIDocument::GetActiveElement()
- {
-   // Get the focused element.
--  if (nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow()) {
--    nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
--    nsIContent* focusedContent =
--      nsFocusManager::GetFocusedDescendant(window,
--                                           nsFocusManager::eOnlyCurrentWindow,
--                                           getter_AddRefs(focusedWindow));
--    // be safe and make sure the element is from this document
--    if (focusedContent && focusedContent->OwnerDoc() == this) {
--      if (focusedContent->ChromeOnlyAccess()) {
--        focusedContent = focusedContent->FindFirstNonChromeOnlyAccessContent();
--      }
--      if (focusedContent) {
--        return focusedContent->AsElement();
--      }
--    }
-+  Element* focusedElement = GetRetargetedFocusedElement();
-+  if (focusedElement) {
-+    return focusedElement;
-   }
- 
-   // No focused element anywhere in this document.  Try to get the BODY.
-   RefPtr<nsHTMLDocument> htmlDoc = AsHTMLDocument();
-   if (htmlDoc) {
-     // Because of IE compatibility, return null when html document doesn't have
-     // a body.
-     return htmlDoc->GetBody();
-diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp
---- a/dom/base/nsFocusManager.cpp
-+++ b/dom/base/nsFocusManager.cpp
-@@ -845,20 +845,21 @@ nsFocusManager::ContentRemoved(nsIDocume
- {
-   NS_ENSURE_ARG(aDocument);
-   NS_ENSURE_ARG(aContent);
- 
-   nsPIDOMWindowOuter *window = aDocument->GetWindow();
-   if (!window)
-     return NS_OK;
- 
--  // if the content is currently focused in the window, or is an ancestor
--  // of the currently focused element, reset the focus within that window.
-+  // if the content is currently focused in the window, or is an
-+  // shadow-including inclusive ancestor of the currently focused element,
-+  // reset the focus within that window.
-   nsIContent* content = window->GetFocusedNode();
--  if (content && nsContentUtils::ContentIsDescendantOf(content, aContent)) {
-+  if (content && nsContentUtils::ContentIsHostIncludingDescendantOf(content, aContent)) {
-     bool shouldShowFocusRing = window->ShouldShowFocusRing();
-     window->SetFocusedNode(nullptr);
- 
-     // if this window is currently focused, clear the global focused
-     // element as well, but don't fire any events.
-     if (window == mFocusedWindow) {
-       mFocusedContent = nullptr;
-     } else {
-diff --git a/dom/base/nsIContent.h b/dom/base/nsIContent.h
---- a/dom/base/nsIContent.h
-+++ b/dom/base/nsIContent.h
-@@ -545,16 +545,24 @@ public:
-    */
-   mozilla::dom::ShadowRoot* GetContainingShadow() const
-   {
-     const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
-     return slots ? slots->mContainingShadow.get() : nullptr;
-   }
- 
-   /**
-+   * Gets the shadow host if this content is in a shadow tree. That is, the host
-+   * of |GetContainingShadow|, if its not null.
-+   *
-+   * @return The shadow host, if this is in shadow tree, or null.
-+   */
-+  nsIContent* GetContainingShadowHost() const;
-+
-+  /**
-    * Gets the assigned slot associated with this content.
-    *
-    * @return The assigned slot element or null.
-    */
-   mozilla::dom::HTMLSlotElement* GetAssignedSlot() const
-   {
-     const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
-     return slots ? slots->mAssignedSlot.get() : nullptr;
-diff --git a/dom/webidl/ShadowRoot.webidl b/dom/webidl/ShadowRoot.webidl
---- a/dom/webidl/ShadowRoot.webidl
-+++ b/dom/webidl/ShadowRoot.webidl
-@@ -15,16 +15,18 @@ enum ShadowRootMode {
-   "open",
-   "closed"
- };
- 
- // https://dom.spec.whatwg.org/#shadowroot
- [Func="nsDocument::IsWebComponentsEnabled"]
- interface ShadowRoot : DocumentFragment
- {
-+  readonly attribute Element? activeElement;
-+
-   // Shadow DOM v1
-   readonly attribute ShadowRootMode mode;
-   readonly attribute Element host;
- 
-   // [deprecated] Shadow DOM v0
-   Element? getElementById(DOMString elementId);
-   HTMLCollection getElementsByTagName(DOMString localName);
-   HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
-diff --git a/testing/web-platform/meta/shadow-dom/ShadowRoot-interface.html.ini b/testing/web-platform/meta/shadow-dom/ShadowRoot-interface.html.ini
-deleted file mode 100644
---- a/testing/web-platform/meta/shadow-dom/ShadowRoot-interface.html.ini
-+++ /dev/null
-@@ -1,7 +0,0 @@
--[ShadowRoot-interface.html]
--  [ShadowRoot.activeElement must return the focused element of the context object when shadow root is open.]
--    expected: FAIL
--
--  [ShadowRoot.activeElement must return the focused element of the context object when shadow root is closed.]
--    expected: FAIL
--
-diff --git a/testing/web-platform/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html.ini b/testing/web-platform/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html.ini
-deleted file mode 100644
---- a/testing/web-platform/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/activeElement-confirm-return-null.html.ini
-+++ /dev/null
-@@ -1,10 +0,0 @@
--[activeElement-confirm-return-null.html]
--  [confirm activeElement return null]
--    expected: FAIL
--
--  [confirm activeElement return null when there is other element in body]
--    expected: FAIL
--
--  [confirm activeElement return null when focus on the element in the outer shadow tree]
--    expected: FAIL
--
-diff --git a/testing/web-platform/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html.ini b/testing/web-platform/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html.ini
-deleted file mode 100644
---- a/testing/web-platform/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-007.html.ini
-+++ /dev/null
-@@ -1,4 +0,0 @@
--[test-007.html]
--  [A_10_01_01_03_01_T01]
--    expected: FAIL
--
-diff --git a/testing/web-platform/meta/shadow-dom/untriaged/user-interaction/active-element/test-001.html.ini b/testing/web-platform/meta/shadow-dom/untriaged/user-interaction/active-element/test-001.html.ini
-deleted file mode 100644
---- a/testing/web-platform/meta/shadow-dom/untriaged/user-interaction/active-element/test-001.html.ini
-+++ /dev/null
-@@ -1,4 +0,0 @@
--[test-001.html]
--  [A_07_03_01_T01]
--    expected: FAIL
--
-diff --git a/testing/web-platform/meta/shadow-dom/untriaged/user-interaction/active-element/test-002.html.ini b/testing/web-platform/meta/shadow-dom/untriaged/user-interaction/active-element/test-002.html.ini
-deleted file mode 100644
---- a/testing/web-platform/meta/shadow-dom/untriaged/user-interaction/active-element/test-002.html.ini
-+++ /dev/null
-@@ -1,4 +0,0 @@
--[test-002.html]
--  [A_07_03_02_T01]
--    expected: FAIL
--
-

+ 0 - 143
frg/work-js/mozilla-release/patches/L-1430299-59a1.patch

@@ -1,143 +0,0 @@
-# HG changeset patch
-# User Jessica Jong <jjong@mozilla.com>
-# Date 1516258335 -28800
-# Node ID ac355333d769a212121b18352be37d3434e8aa9e
-# Parent  710b3c4c7a2904b70f11ea83b571dce5ec0e5180
-Bug 1430299 - Add DocumentOrShadowRoot interface. r=smaug
-
-diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl
---- a/dom/webidl/Document.webidl
-+++ b/dom/webidl/Document.webidl
-@@ -132,17 +132,16 @@ partial interface Document {
-   //(HTML only)WindowProxy open(DOMString url, DOMString name, DOMString features, optional boolean replace);
-   //(HTML only)void close();
-   //(HTML only)void write(DOMString... text);
-   //(HTML only)void writeln(DOMString... text);
- 
-   // user interaction
-   [Pure]
-   readonly attribute WindowProxy? defaultView;
--  readonly attribute Element? activeElement;
-   [Throws]
-   boolean hasFocus();
-   //(HTML only)         attribute DOMString designMode;
-   //(HTML only)boolean execCommand(DOMString commandId);
-   //(HTML only)boolean execCommand(DOMString commandId, boolean showUI);
-   //(HTML only)boolean execCommand(DOMString commandId, boolean showUI, DOMString value);
-   //(HTML only)boolean queryCommandEnabled(DOMString commandId);
-   //(HTML only)boolean queryCommandIndeterm(DOMString commandId);
-@@ -269,18 +268,16 @@ partial interface Document {
- partial interface Document {
-   readonly attribute boolean hidden;
-   readonly attribute VisibilityState visibilityState;
-            attribute EventHandler onvisibilitychange;
- };
- 
- // http://dev.w3.org/csswg/cssom/#extensions-to-the-document-interface
- partial interface Document {
--    [Constant]
--    readonly attribute StyleSheetList styleSheets;
-     attribute DOMString? selectedStyleSheetSet;
-     readonly attribute DOMString? lastStyleSheetSet;
-     readonly attribute DOMString? preferredStyleSheetSet;
-     [Constant]
-     readonly attribute DOMStringList styleSheetSets;
-     void enableStyleSheetsForSet (DOMString? name);
- };
- 
-@@ -477,8 +474,9 @@ partial interface Document {
- Document implements XPathEvaluator;
- Document implements GlobalEventHandlers;
- Document implements DocumentAndElementEventHandlers;
- Document implements TouchEventHandlers;
- Document implements ParentNode;
- Document implements OnErrorEventHandlerForNodes;
- Document implements GeometryUtils;
- Document implements FontFaceSource;
-+Document implements DocumentOrShadowRoot;
-diff --git a/dom/webidl/DocumentOrShadowRoot.webidl b/dom/webidl/DocumentOrShadowRoot.webidl
-new file mode 100644
---- /dev/null
-+++ b/dom/webidl/DocumentOrShadowRoot.webidl
-@@ -0,0 +1,29 @@
-+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-+/* This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
-+ * You can obtain one at http://mozilla.org/MPL/2.0/.
-+ *
-+ * The origin of this IDL file is
-+ * https://dom.spec.whatwg.org/#documentorshadowroot
-+ * http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-the-documentorshadowroot-mixin
-+ */
-+
-+[NoInterfaceObject]
-+interface DocumentOrShadowRoot {
-+  // Not implemented yet: bug 1430308.
-+  // Selection? getSelection();
-+  // Not implemented yet: bug 1430301.
-+  // Element? elementFromPoint (float x, float y);
-+  // Not implemented yet: bug 1430301.
-+  // sequence<Element> elementsFromPoint (float x, float y);
-+  // Not implemented yet: bug 1430307.
-+  // CaretPosition? caretPositionFromPoint (float x, float y);
-+
-+  readonly attribute Element? activeElement;
-+  readonly attribute StyleSheetList styleSheets;
-+
-+  // Not implemented yet: bug 1430303.
-+  // readonly attribute Element? pointerLockElement;
-+  // Not implemented yet: bug 1430305.
-+  // readonly attribute Element? fullscreenElement;
-+};
-diff --git a/dom/webidl/ShadowRoot.webidl b/dom/webidl/ShadowRoot.webidl
---- a/dom/webidl/ShadowRoot.webidl
-+++ b/dom/webidl/ShadowRoot.webidl
-@@ -15,25 +15,23 @@ enum ShadowRootMode {
-   "open",
-   "closed"
- };
- 
- // https://dom.spec.whatwg.org/#shadowroot
- [Func="nsDocument::IsShadowDOMEnabled"]
- interface ShadowRoot : DocumentFragment
- {
--  readonly attribute Element? activeElement;
--
-   // Shadow DOM v1
-   readonly attribute ShadowRootMode mode;
-   readonly attribute Element host;
- 
-   // [deprecated] Shadow DOM v0
-   Element? getElementById(DOMString elementId);
-   HTMLCollection getElementsByTagName(DOMString localName);
-   HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
-   HTMLCollection getElementsByClassName(DOMString classNames);
-   [CEReactions, SetterThrows, TreatNullAs=EmptyString]
-   attribute DOMString innerHTML;
-   attribute boolean applyAuthorStyles;
--  readonly attribute StyleSheetList styleSheets;
- };
- 
-+ShadowRoot implements DocumentOrShadowRoot;
-diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build
---- a/dom/webidl/moz.build
-+++ b/dom/webidl/moz.build
-@@ -474,16 +474,17 @@ WEBIDL_FILES = [
-     'DataTransferItemList.webidl',
-     'DecoderDoctorNotification.webidl',
-     'DedicatedWorkerGlobalScope.webidl',
-     'DelayNode.webidl',
-     'DeviceMotionEvent.webidl',
-     'Directory.webidl',
-     'Document.webidl',
-     'DocumentFragment.webidl',
-+    'DocumentOrShadowRoot.webidl',
-     'DocumentTimeline.webidl',
-     'DocumentType.webidl',
-     'DOMCursor.webidl',
-     'DOMError.webidl',
-     'DOMException.webidl',
-     'DOMImplementation.webidl',
-     'DominatorTree.webidl',
-     'DOMMatrix.webidl',
-

+ 0 - 1086
frg/work-js/mozilla-release/patches/L-1535226-68a1.patch

@@ -1,1086 +0,0 @@
-# HG changeset patch
-# User Nicholas Nethercote <nnethercote@mozilla.com>
-# Date 1553131730 0
-# Node ID c36acc45cddcc9ddc89d4e84acf44c0c206eb341
-# Parent  494ebb6edf2a49f6d4f47fad9f00c156ea3d803f
-Bug 1535226 - Remove uses of XP_WIN32 in Gecko. r=glandium
-
-The definitions can't be entirely removed yet because NSS still needs them.
-
-Differential Revision: https://phabricator.services.mozilla.com/D23454
-
-diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
---- a/browser/installer/package-manifest.in
-+++ b/browser/installer/package-manifest.in
-@@ -82,17 +82,17 @@
- @BINPATH@/@DLL_PREFIX@xul@DLL_SUFFIX@
- #endif
- #ifdef XP_MACOSX
- @BINPATH@/@MOZ_CHILD_PROCESS_NAME@.app/
- @BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
- #else
- @BINPATH@/@MOZ_CHILD_PROCESS_NAME@
- #endif
--#ifdef XP_WIN32
-+#ifdef XP_WIN
- @BINPATH@/plugin-hang-ui@BIN_SUFFIX@
- #if MOZ_PACKAGE_MSVC_DLLS
- @BINPATH@/@MSVC_C_RUNTIME_DLL@
- @BINPATH@/@MSVC_CXX_RUNTIME_DLL@
- #endif
- #if MOZ_PACKAGE_WIN_UCRT_DLLS
- @BINPATH@/api-ms-win-*.dll
- @BINPATH@/ucrtbase.dll
-@@ -146,17 +146,17 @@
- @BINPATH@/@DLL_PREFIX@qipcap64@DLL_SUFFIX@
- #else
- @BINPATH@/@DLL_PREFIX@qipcap@DLL_SUFFIX@
- #endif
- #endif
- 
- ; [Components]
- #ifdef ACCESSIBILITY
--#ifdef XP_WIN32
-+#ifdef XP_WIN
- @BINPATH@/Accessible.tlb
- @BINPATH@/AccessibleHandler.dll
- @BINPATH@/AccessibleMarshal.dll
- @BINPATH@/IA2Marshal.dll
- #endif
- #endif
- 
- ; JavaScript components
-diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure
---- a/build/moz.configure/init.configure
-+++ b/build/moz.configure/init.configure
-@@ -984,17 +984,16 @@ add_old_configure_assignment('HOST_OS_AR
- def target_is_windows(target):
-     if target.kernel == 'WINNT':
-         return True
- 
- 
- set_define('_WINDOWS', target_is_windows)
- set_define('WIN32', target_is_windows)
- set_define('XP_WIN', target_is_windows)
--set_define('XP_WIN32', target_is_windows)
- 
- 
- @depends(target)
- def target_is_unix(target):
-     if target.kernel != 'WINNT':
-         return True
- 
- 
-diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
---- a/dom/ipc/ContentParent.cpp
-+++ b/dom/ipc/ContentParent.cpp
-@@ -1660,17 +1660,17 @@ void ContentParent::ActorDestroy(ActorDe
- 
-   // Unregister all the BlobURLs registered by the ContentChild.
-   for (uint32_t i = 0; i < mBlobURLs.Length(); ++i) {
-     BlobURLProtocolHandler::RemoveDataEntry(mBlobURLs[i]);
-   }
- 
-   mBlobURLs.Clear();
- 
--#if defined(XP_WIN32) && defined(ACCESSIBILITY)
-+#if defined(XP_WIN) && defined(ACCESSIBILITY)
-   a11y::AccessibleWrap::ReleaseContentProcessIdFor(ChildID());
- #endif
- 
-   nsTHashtable<nsRefPtrHashKey<BrowsingContextGroup>> groups;
-   mGroups.SwapElements(groups);
- 
-   for (auto iter = groups.Iter(); !iter.Done(); iter.Next()) {
-     iter.Get()->GetKey()->Unsubscribe(this);
-@@ -5192,28 +5192,28 @@ ContentParent::RecvUnstoreAndBroadcastBl
-   BroadcastBlobURLUnregistration(aURI, this);
-   mBlobURLs.RemoveElement(aURI);
- 
-   return IPC_OK();
- }
- 
- mozilla::ipc::IPCResult ContentParent::RecvGetA11yContentId(
-     uint32_t* aContentId) {
--#if defined(XP_WIN32) && defined(ACCESSIBILITY)
-+#if defined(XP_WIN) && defined(ACCESSIBILITY)
-   *aContentId = a11y::AccessibleWrap::GetContentProcessIdFor(ChildID());
-   MOZ_ASSERT(*aContentId);
-   return IPC_OK();
- #else
-   return IPC_FAIL_NO_REASON(this);
- #endif
- }
- 
- mozilla::ipc::IPCResult ContentParent::RecvA11yHandlerControl(
-     const uint32_t& aPid, const IHandlerControlHolder& aHandlerControl) {
--#if defined(XP_WIN32) && defined(ACCESSIBILITY)
-+#if defined(XP_WIN) && defined(ACCESSIBILITY)
-   MOZ_ASSERT(!aHandlerControl.IsNull());
-   RefPtr<IHandlerControl> proxy(aHandlerControl.Get());
-   a11y::AccessibleWrap::SetHandlerControl(aPid, std::move(proxy));
-   return IPC_OK();
- #else
-   return IPC_FAIL_NO_REASON(this);
- #endif
- }
-diff --git a/gfx/src/nsCoord.h b/gfx/src/nsCoord.h
---- a/gfx/src/nsCoord.h
-+++ b/gfx/src/nsCoord.h
-@@ -67,31 +67,31 @@ inline nscoord NSCoordMulDiv(nscoord aMu
- #ifdef NS_COORD_IS_FLOAT
-   return (aMult1 * aMult2 / aDiv);
- #else
-   return (int64_t(aMult1) * int64_t(aMult2) / int64_t(aDiv));
- #endif
- }
- 
- inline nscoord NSToCoordRound(float aValue) {
--#if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__) && \
-+#if defined(XP_WIN) && defined(_M_IX86) && !defined(__GNUC__) && \
-     !defined(__clang__)
-   return NS_lroundup30(aValue);
- #else
-   return nscoord(floorf(aValue + 0.5f));
--#endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
-+#endif /* XP_WIN && _M_IX86 && !__GNUC__ */
- }
- 
- inline nscoord NSToCoordRound(double aValue) {
--#if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__) && \
-+#if defined(XP_WIN) && defined(_M_IX86) && !defined(__GNUC__) && \
-     !defined(__clang__)
-   return NS_lroundup30((float)aValue);
- #else
-   return nscoord(floor(aValue + 0.5f));
--#endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
-+#endif /* XP_WIN && _M_IX86 && !__GNUC__ */
- }
- 
- inline nscoord NSToCoordRoundWithClamp(float aValue) {
- #ifndef NS_COORD_IS_FLOAT
-   // Bounds-check before converting out of float, to avoid overflow
-   if (aValue >= nscoord_MAX) {
-     return nscoord_MAX;
-   }
-diff --git a/js/src/old-configure.in b/js/src/old-configure.in
---- a/js/src/old-configure.in
-+++ b/js/src/old-configure.in
-@@ -407,17 +407,17 @@ dnl System overrides of the defaults for
- dnl ========================================================
- case "$host" in
- *mingw*)
-     if test -n "$_WIN32_MSVC"; then
-         HOST_CFLAGS="$HOST_CFLAGS -nologo"
-     else
-         HOST_CFLAGS="$HOST_CFLAGS -mwindows"
-     fi
--    HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN32 -DXP_WIN -DWIN32 -D_WIN32 -D_CRT_SECURE_NO_WARNINGS"
-+    HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN -DWIN32 -D_WIN32 -D_CRT_SECURE_NO_WARNINGS"
-     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O2}"
-     HOST_BIN_SUFFIX=.exe
- 
-     case "${host_cpu}" in
-     i*86)
-         if test -n "$_WIN32_MSVC"; then
-             HOST_LDFLAGS="$HOST_LDFLAGS -MACHINE:X86"
-         fi
-diff --git a/js/src/vm/Printer.cpp b/js/src/vm/Printer.cpp
---- a/js/src/vm/Printer.cpp
-+++ b/js/src/vm/Printer.cpp
-@@ -429,17 +429,17 @@ void Fprinter::finish() {
- 
- bool Fprinter::put(const char* s, size_t len) {
-   MOZ_ASSERT(file_);
-   int i = fwrite(s, /*size=*/1, /*nitems=*/len, file_);
-   if (size_t(i) != len) {
-     reportOutOfMemory();
-     return false;
-   }
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-   if ((file_ == stderr) && (IsDebuggerPresent())) {
-     UniqueChars buf = DuplicateString(s, len);
-     if (!buf) {
-       reportOutOfMemory();
-       return false;
-     }
-     OutputDebugStringA(buf.get());
-   }
-diff --git a/old-configure.in b/old-configure.in
---- a/old-configure.in
-+++ b/old-configure.in
-@@ -500,17 +500,17 @@ dnl System overrides of the defaults for
- dnl ========================================================
- case "$host" in
- *mingw*)
-     if test -n "$_WIN32_MSVC"; then
-         HOST_CFLAGS="$HOST_CFLAGS -nologo"
-     else
-         HOST_CFLAGS="$HOST_CFLAGS -mwindows"
-     fi
--    HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN32 -DXP_WIN -DWIN32 -D_WIN32 -D_CRT_SECURE_NO_WARNINGS"
-+    HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN -DWIN32 -D_WIN32 -D_CRT_SECURE_NO_WARNINGS"
-     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O2}"
-     HOST_BIN_SUFFIX=.exe
- 
-     case "${host_cpu}" in
-     i*86)
-         if test -n "$_WIN32_MSVC"; then
-             HOST_LDFLAGS="$HOST_LDFLAGS -MACHINE:X86"
-         fi
-diff --git a/security/moz.build b/security/moz.build
---- a/security/moz.build
-+++ b/security/moz.build
-@@ -127,21 +127,23 @@ sandbox_vars = {
-         'WARNINGS_AS_ERRORS': [],
-     },
-     # NSS' build system doesn't currently build NSS with PGO.
-     # We could probably do so, but not without a lot of
-     # careful consideration.
-     'NO_PGO': True,
- }
- if CONFIG['OS_TARGET'] == 'WINNT':
-+    # We want to remove XP_WIN32 eventually. See bug 1535219 for details.
-+    sandbox_vars['CFLAGS'] = ['-DXP_WIN32']
-     if CONFIG['CPU_ARCH'] == 'x86':
-         # This should really be the default.
-         sandbox_vars['ASFLAGS'] = ['-safeseh']
-     if CONFIG['MOZ_FOLD_LIBS_FLAGS']:
--        sandbox_vars['CFLAGS'] = CONFIG['MOZ_FOLD_LIBS_FLAGS']
-+        sandbox_vars['CFLAGS'] += CONFIG['MOZ_FOLD_LIBS_FLAGS']
- if CONFIG['OS_TARGET'] == 'Android':
-     sandbox_vars['CFLAGS'] = [
-         '-include', TOPSRCDIR + '/security/manager/android_stub.h',
-         # Setting sandbox_vars['DEFINES'] is broken currently.
-         '-DCHECK_FORK_GETPID',
-     ]
-     if CONFIG['ANDROID_VERSION']:
-         sandbox_vars['CFLAGS'] += ['-DANDROID_VERSION=' + CONFIG['ANDROID_VERSION']]
-diff --git a/toolkit/components/commandlines/nsCommandLine.cpp b/toolkit/components/commandlines/nsCommandLine.cpp
---- a/toolkit/components/commandlines/nsCommandLine.cpp
-+++ b/toolkit/components/commandlines/nsCommandLine.cpp
-@@ -249,17 +249,17 @@ nsCommandLine::ResolveFile(const nsAStri
-   if (NS_FAILED(rv)) return rv;
- 
-   rv = lf->Normalize();
-   if (NS_FAILED(rv)) return rv;
- 
-   lf.forget(aResult);
-   return NS_OK;
- 
--#elif defined(XP_WIN32)
-+#elif defined(XP_WIN)
-   nsCOMPtr<nsIFile> lf(do_CreateInstance(NS_LOCAL_FILE_CONTRACTID));
-   NS_ENSURE_TRUE(lf, NS_ERROR_OUT_OF_MEMORY);
- 
-   rv = lf->InitWithPath(aArgument);
-   if (NS_FAILED(rv)) {
-     // If it's a relative path, the Init is *going* to fail. We use string magic
-     // and win32 _fullpath. Note that paths of the form "\Relative\To\CurDrive"
-     // are going to fail, and I haven't figured out a way to work around this
-diff --git a/toolkit/crashreporter/client/crashreporter.h b/toolkit/crashreporter/client/crashreporter.h
---- a/toolkit/crashreporter/client/crashreporter.h
-+++ b/toolkit/crashreporter/client/crashreporter.h
-@@ -16,17 +16,17 @@
- #include <vector>
- #include <stdlib.h>
- #include <stdio.h>
- #include <iostream>
- #include <fstream>
- 
- #define MAX_COMMENT_LENGTH 500
- 
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
- 
- #  include <windows.h>
- 
- #  define UI_SNPRINTF _snprintf
- #  define UI_DIR_SEPARATOR "\\"
- 
- std::string WideToUTF8(const std::wstring& wide, bool* success = 0);
- 
-diff --git a/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp b/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp
---- a/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp
-+++ b/toolkit/crashreporter/minidump-analyzer/minidump-analyzer.cpp
-@@ -19,17 +19,17 @@
- #include "google_breakpad/processor/minidump_processor.h"
- #include "google_breakpad/processor/process_state.h"
- #include "google_breakpad/processor/stack_frame.h"
- #include "processor/pathname_stripper.h"
- 
- #include "mozilla/FStream.h"
- #include "mozilla/Unused.h"
- 
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
- 
- #  include <windows.h>
- #  include "mozilla/glue/WindowsDllServices.h"
- 
- #elif defined(XP_UNIX) || defined(XP_MACOSX)
- 
- #  include <sys/types.h>
- #  include <sys/stat.h>
-diff --git a/toolkit/crashreporter/nsDummyExceptionHandler.cpp b/toolkit/crashreporter/nsDummyExceptionHandler.cpp
---- a/toolkit/crashreporter/nsDummyExceptionHandler.cpp
-+++ b/toolkit/crashreporter/nsDummyExceptionHandler.cpp
-@@ -96,17 +96,17 @@ nsresult SetRestartArgs(int argc, char**
- int GetAnnotationTimeCrashFd() { return 7; }
- #endif
- 
- void RegisterChildCrashAnnotationFileDescriptor(ProcessId aProcess,
-                                                 PRFileDesc* aFd) {}
- 
- void DeregisterChildCrashAnnotationFileDescriptor(ProcessId aProcess) {}
- 
--#ifdef XP_WIN32
-+#ifdef XP_WIN
- nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo) {
-   return NS_ERROR_NOT_IMPLEMENTED;
- }
- #endif
- 
- #ifdef XP_LINUX
- bool WriteMinidumpForSigInfo(int signo, siginfo_t* info, void* uc) {
-   return false;
-diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp
---- a/toolkit/crashreporter/nsExceptionHandler.cpp
-+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
-@@ -25,17 +25,17 @@
- #include "mozilla/ipc/CrashReporterClient.h"
- 
- #include "nsThreadUtils.h"
- #include "nsXULAppAPI.h"
- #include "jsfriendapi.h"
- #include "ThreadAnnotation.h"
- #include "private/pprio.h"
- 
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
- #  ifdef WIN32_LEAN_AND_MEAN
- #    undef WIN32_LEAN_AND_MEAN
- #  endif
- 
- #  include "nsXULAppAPI.h"
- #  include "nsIXULAppInfo.h"
- #  include "nsIWindowsRegKey.h"
- #  include "breakpad-client/windows/crash_generation/client_info.h"
-@@ -70,17 +70,17 @@
- #  include "breakpad-client/linux/handler/exception_handler.h"
- #  include "common/linux/eintr_wrapper.h"
- #  include <fcntl.h>
- #  include <sys/types.h>
- #  include <sys/wait.h>
- #  include <unistd.h>
- #else
- #  error "Not yet implemented for this platform"
--#endif  // defined(XP_WIN32)
-+#endif  // defined(XP_WIN)
- 
- #ifdef MOZ_CRASHREPORTER_INJECTOR
- #  include "InjectCrashReporter.h"
- using mozilla::InjectCrashRunnable;
- #endif
- 
- #include <stdlib.h>
- #include <time.h>
-@@ -116,17 +116,17 @@ using google_breakpad::FileID;
- using google_breakpad::kDefaultBuildIdSize;
- using google_breakpad::PageAllocator;
- #endif
- using namespace mozilla;
- using mozilla::ipc::CrashReporterClient;
- 
- namespace CrashReporter {
- 
--#ifdef XP_WIN32
-+#ifdef XP_WIN
- typedef wchar_t XP_CHAR;
- typedef std::wstring xpstring;
- #  define XP_TEXT(x) L##x
- #  define CONVERT_XP_CHAR_TO_UTF16(x) x
- #  define XP_STRLEN(x) wcslen(x)
- #  define my_strlen strlen
- #  define CRASH_REPORTER_FILENAME "crashreporter.exe"
- #  define MINIDUMP_ANALYZER_FILENAME "minidump-analyzer.exe"
-@@ -165,17 +165,17 @@ typedef std::string xpstring;
- #    define XP_STOA(size, buffer, base) sprintf(buffer, "%zu", (size_t)size)
- #    define my_strlen strlen
- #    define sys_close close
- #    define sys_fork fork
- #    define sys_open open
- #    define sys_read read
- #    define sys_write write
- #  endif
--#endif  // XP_WIN32
-+#endif  // XP_WIN
- 
- #if defined(__GNUC__)
- #  define MAYBE_UNUSED __attribute__((unused))
- #else
- #  define MAYBE_UNUSED
- #endif  // defined(__GNUC__)
- 
- #ifndef XP_LINUX
-@@ -854,17 +854,17 @@ void WriteEscapedMozCrashReason(Platform
- // handler from invoking it. See bug 1424304.
- bool MinidumpCallback(
- #ifdef XP_LINUX
-     const MinidumpDescriptor& descriptor,
- #else
-     const XP_CHAR* dump_path, const XP_CHAR* minidump_id,
- #endif
-     void* context,
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-     EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion,
- #endif
-     bool succeeded) {
-   bool returnValue = showOSCrashReporter ? false : succeeded;
- 
-   static XP_CHAR minidumpPath[XP_PATH_MAX];
-   size_t size = XP_PATH_MAX;
-   XP_CHAR* p;
-@@ -1103,17 +1103,17 @@ static size_t EnsureTrailingSlash(XP_CHA
-     aBuf[len] = XP_PATH_SEPARATOR_CHAR;
-     ++len;
-     aBuf[len] = 0;
-   }
-   return len;
- }
- #endif
- 
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
- 
- static size_t BuildTempPath(wchar_t* aBuf, size_t aBufLen) {
-   // first figure out buffer size
-   DWORD pathLen = GetTempPath(0, nullptr);
-   if (pathLen == 0 || pathLen >= aBufLen) {
-     return 0;
-   }
- 
-@@ -1440,25 +1440,25 @@ nsresult SetExceptionHandler(nsIFile* aX
- 
-   nsAutoString libraryPath_temp;
-   rv = libPath->GetPath(libraryPath_temp);
-   if (NS_WARN_IF(NS_FAILED(rv))) {
-     return rv;
-   }
- #  endif  // XP_MACOSX
- 
--#  ifdef XP_WIN32
-+#  ifdef XP_WIN
-   crashReporterPath =
-       reinterpret_cast<wchar_t*>(ToNewUnicode(crashReporterPath_temp));
- #  else
-   crashReporterPath = ToNewCString(crashReporterPath_temp);
- #    ifdef XP_MACOSX
-   libraryPath = ToNewCString(libraryPath_temp);
- #    endif
--#  endif  // XP_WIN32
-+#  endif  // XP_WIN
- #else
-   // On Android, we launch a service defined via MOZ_ANDROID_CRASH_HANDLER
-   const char* androidCrashHandler = PR_GetEnv("MOZ_ANDROID_CRASH_HANDLER");
-   if (androidCrashHandler) {
-     crashReporterPath = strdup(androidCrashHandler);
-   } else {
-     NS_WARNING("No Android crash handler set");
-   }
-@@ -1471,32 +1471,32 @@ nsresult SetExceptionHandler(nsIFile* aX
-       androidStartServiceCommand = (char*)"start-foreground-service";
-     } else {
-       androidStartServiceCommand = (char*)"startservice";
-     }
-   }
- #endif  // !defined(MOZ_WIDGET_ANDROID)
- 
-   // get temp path to use for minidump path
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
-   nsString tempPath;
- #else
-   nsCString tempPath;
- #endif
-   if (!BuildTempPath(tempPath)) {
-     return NS_ERROR_FAILURE;
-   }
- 
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-   ReserveBreakpadVM();
- 
-   // Pre-load psapi.dll to prevent it from being loaded during exception
-   // handling.
-   ::LoadLibraryW(L"psapi.dll");
--#endif  // XP_WIN32
-+#endif  // XP_WIN
- 
- #ifdef MOZ_WIDGET_ANDROID
-   androidUserSerial = getenv("MOZ_ANDROID_USER_SERIAL_NUMBER");
- #endif
- 
-   // Initialize the flag and mutex used to avoid dump processing
-   // once browser termination has begun.
-   NS_ASSERTION(!dumpSafetyLock, "Shouldn't have a lock yet");
-@@ -1525,31 +1525,31 @@ nsresult SetExceptionHandler(nsIFile* aX
- #endif
- 
- #ifdef XP_WIN
-       FPEFilter,
- #else
-       Filter,
- #endif
-       MinidumpCallback, nullptr,
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-       google_breakpad::ExceptionHandler::HANDLER_ALL, GetMinidumpType(),
-       (const wchar_t*)nullptr, nullptr);
- #else
-       true
- #  ifdef XP_MACOSX
-       ,
-       nullptr
- #  endif
- #  ifdef XP_LINUX
-       ,
-       -1
- #  endif
-   );
--#endif  // XP_WIN32
-+#endif  // XP_WIN
- 
-   if (!gExceptionHandler) return NS_ERROR_OUT_OF_MEMORY;
- 
- #ifdef XP_WIN
-   gExceptionHandler->set_handle_debug_exceptions(true);
- 
-   // Initially set sIncludeContextHeap to true for debugging startup crashes
-   // even if the controlling pref value is false.
-@@ -1616,17 +1616,17 @@ bool GetMinidumpPath(nsAString& aPath) {
-       gExceptionHandler->minidump_descriptor().directory().c_str());
- #endif
-   return true;
- }
- 
- nsresult SetMinidumpPath(const nsAString& aPath) {
-   if (!gExceptionHandler) return NS_ERROR_NOT_INITIALIZED;
- 
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-   gExceptionHandler->set_dump_path(
-       std::wstring(char16ptr_t(aPath.BeginReading())));
- #elif defined(XP_LINUX)
-   gExceptionHandler->set_minidump_descriptor(
-       MinidumpDescriptor(NS_ConvertUTF16toUTF8(aPath).BeginReading()));
- #else
-   gExceptionHandler->set_dump_path(NS_ConvertUTF16toUTF8(aPath).BeginReading());
- #endif
-@@ -1743,17 +1743,17 @@ static nsresult SetupCrashReporterDirect
- 
-   EnsureDirectoryExists(directory);
-   xpstring* directoryPath = CreatePathFromFile(directory);
- 
-   if (!directoryPath) {
-     return NS_ERROR_FAILURE;
-   }
- 
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
-   SetEnvironmentVariableW(aEnvVarName, directoryPath->c_str());
- #else
-   setenv(aEnvVarName, directoryPath->c_str(), /* overwrite */ 1);
- #endif
- 
-   delete directoryPath;
- 
-   if (aDirectory) {
-@@ -1807,17 +1807,17 @@ nsresult SetupExtraData(nsIFile* aAppDat
-   nsCOMPtr<nsIFile> lastCrashFile;
-   rv = dataDirectory->Clone(getter_AddRefs(lastCrashFile));
-   NS_ENSURE_SUCCESS(rv, rv);
- 
-   rv = lastCrashFile->AppendNative(NS_LITERAL_CSTRING("LastCrash"));
-   NS_ENSURE_SUCCESS(rv, rv);
-   memset(lastCrashTimeFilename, 0, sizeof(lastCrashTimeFilename));
- 
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
-   nsAutoString filename;
-   rv = lastCrashFile->GetPath(filename);
-   NS_ENSURE_SUCCESS(rv, rv);
- 
-   if (filename.Length() < XP_PATH_MAX)
-     wcsncpy(lastCrashTimeFilename, filename.get(), filename.Length());
- #else
-   nsAutoCString filename;
-@@ -2115,28 +2115,28 @@ static bool GetAnnotation(CrashReporter:
- 
-   data = entry;
-   return true;
- }
- 
- nsresult RegisterAppMemory(void* ptr, size_t length) {
-   if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
- 
--#if defined(XP_LINUX) || defined(XP_WIN32)
-+#if defined(XP_LINUX) || defined(XP_WIN)
-   gExceptionHandler->RegisterAppMemory(ptr, length);
-   return NS_OK;
- #else
-   return NS_ERROR_NOT_IMPLEMENTED;
- #endif
- }
- 
- nsresult UnregisterAppMemory(void* ptr) {
-   if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
- 
--#if defined(XP_LINUX) || defined(XP_WIN32)
-+#if defined(XP_LINUX) || defined(XP_WIN)
-   gExceptionHandler->UnregisterAppMemory(ptr);
-   return NS_OK;
- #else
-   return NS_ERROR_NOT_IMPLEMENTED;
- #endif
- }
- 
- void SetIncludeContextHeap(bool aValue) {
-@@ -2206,17 +2206,17 @@ nsresult SetRestartArgs(int argc, char**
-     envVar += appfile;
-     env = ToNewCString(envVar);
-     PR_SetEnv(env);
-   }
- 
-   return NS_OK;
- }
- 
--#ifdef XP_WIN32
-+#ifdef XP_WIN
- nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo) {
-   if (!gExceptionHandler) return NS_ERROR_NOT_INITIALIZED;
- 
-   return gExceptionHandler->WriteMinidumpForException(aExceptionInfo)
-              ? NS_OK
-              : NS_ERROR_FAILURE;
- }
- #endif
-@@ -2241,17 +2241,17 @@ nsresult AppendObjCExceptionInfoToAppNot
- #endif
- 
- /*
-  * Combined code to get/set the crash reporter submission pref on
-  * different platforms.
-  */
- static nsresult PrefSubmitReports(bool* aSubmitReports, bool writePref) {
-   nsresult rv;
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
-   /*
-    * NOTE! This needs to stay in sync with the preference checking code
-    *       in toolkit/crashreporter/client/crashreporter_win.cpp
-    */
-   nsCOMPtr<nsIXULAppInfo> appinfo =
-       do_GetService("@mozilla.org/xre/app-info;1", &rv);
-   NS_ENSURE_SUCCESS(rv, rv);
- 
-@@ -3369,17 +3369,17 @@ void RenameAdditionalHangMinidump(nsIFil
- 
- static bool PairedDumpCallback(
- #ifdef XP_LINUX
-     const MinidumpDescriptor& descriptor,
- #else
-     const XP_CHAR* dump_path, const XP_CHAR* minidump_id,
- #endif
-     void* context,
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-     EXCEPTION_POINTERS* /*unused*/, MDRawAssertionInfo* /*unused*/,
- #endif
-     bool succeeded) {
-   nsCOMPtr<nsIFile>& minidump = *static_cast<nsCOMPtr<nsIFile>*>(context);
- 
-   xpstring dump;
- #ifdef XP_LINUX
-   dump = descriptor.path();
-@@ -3396,28 +3396,28 @@ static bool PairedDumpCallback(
- 
- static bool PairedDumpCallbackExtra(
- #ifdef XP_LINUX
-     const MinidumpDescriptor& descriptor,
- #else
-     const XP_CHAR* dump_path, const XP_CHAR* minidump_id,
- #endif
-     void* context,
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-     EXCEPTION_POINTERS* /*unused*/, MDRawAssertionInfo* /*unused*/,
- #endif
-     bool succeeded) {
-   PairedDumpCallback(
- #ifdef XP_LINUX
-       descriptor,
- #else
-       dump_path, minidump_id,
- #endif
-       context,
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-       nullptr, nullptr,
- #endif
-       succeeded);
- 
-   nsCOMPtr<nsIFile>& minidump = *static_cast<nsCOMPtr<nsIFile>*>(context);
- 
-   nsCOMPtr<nsIFile> extra;
-   return WriteExtraForMinidump(minidump, 0, /* content */ false,
-@@ -3481,17 +3481,17 @@ bool TakeMinidump(nsIFile** aResult, boo
- 
-   // capture the dump
-   if (!google_breakpad::ExceptionHandler::WriteMinidump(
-           dump_path,
- #ifdef XP_MACOSX
-           true,
- #endif
-           PairedDumpCallback, static_cast<void*>(aResult)
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-                                   ,
-           GetMinidumpType()
- #endif
-               )) {
-     return false;
-   }
- 
-   if (aMoveToPending) {
-@@ -3524,17 +3524,17 @@ bool CreateMinidumpsAndPair(ProcessHandl
-   dump_path = gExceptionHandler->minidump_descriptor().directory();
- #endif
- 
-   // dump the target
-   nsCOMPtr<nsIFile> targetMinidump;
-   if (!google_breakpad::ExceptionHandler::WriteMinidumpForChild(
-           aTargetPid, targetThread, dump_path, PairedDumpCallbackExtra,
-           static_cast<void*>(&targetMinidump)
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-               ,
-           GetMinidumpType()
- #endif
-               )) {
-     return false;
-   }
- 
-   nsCOMPtr<nsIFile> targetExtra;
-@@ -3544,17 +3544,17 @@ bool CreateMinidumpsAndPair(ProcessHandl
-   nsCOMPtr<nsIFile> incomingDump;
-   if (aIncomingDumpToPair == nullptr) {
-     if (!google_breakpad::ExceptionHandler::WriteMinidump(
-             dump_path,
- #ifdef XP_MACOSX
-             true,
- #endif
-             PairedDumpCallback, static_cast<void*>(&incomingDump)
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-                                     ,
-             GetMinidumpType()
- #endif
-                 )) {
-       targetMinidump->Remove(false);
-       targetExtra->Remove(false);
-       return false;
-     }
-@@ -3596,17 +3596,17 @@ bool CreateAdditionalChildMinidump(Proce
-   dump_path = gExceptionHandler->minidump_descriptor().directory();
- #endif
- 
-   // dump the child
-   nsCOMPtr<nsIFile> childMinidump;
-   if (!google_breakpad::ExceptionHandler::WriteMinidumpForChild(
-           childPid, childThread, dump_path, PairedDumpCallback,
-           static_cast<void*>(&childMinidump)
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-               ,
-           GetMinidumpType()
- #endif
-               )) {
-     return false;
-   }
- 
-   RenameAdditionalHangMinidump(childMinidump, parentMinidump, name);
-diff --git a/toolkit/crashreporter/nsExceptionHandler.h b/toolkit/crashreporter/nsExceptionHandler.h
---- a/toolkit/crashreporter/nsExceptionHandler.h
-+++ b/toolkit/crashreporter/nsExceptionHandler.h
-@@ -18,17 +18,17 @@
- #include "CrashAnnotations.h"
- 
- #include <stddef.h>
- #include <stdint.h>
- #include "nsError.h"
- #include "nsString.h"
- #include "prio.h"
- 
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
- #  ifdef WIN32_LEAN_AND_MEAN
- #    undef WIN32_LEAN_AND_MEAN
- #  endif
- #  include <windows.h>
- #endif
- 
- #if defined(XP_MACOSX)
- #  include <mach/mach.h>
-@@ -137,17 +137,17 @@ bool AppendExtraData(nsIFile* extraFile,
-  * @param aDumpFile - the dump file to associate with aOwnerDumpFile.
-  * @param aOwnerDumpFile - the new owner of aDumpFile.
-  * @param aDumpFileProcessType - process name associated with aDumpFile.
-  */
- void RenameAdditionalHangMinidump(nsIFile* aDumpFile,
-                                   const nsIFile* aOwnerDumpFile,
-                                   const nsACString& aDumpFileProcessType);
- 
--#ifdef XP_WIN32
-+#ifdef XP_WIN
- nsresult WriteMinidumpForException(EXCEPTION_POINTERS* aExceptionInfo);
- #endif
- #ifdef XP_LINUX
- bool WriteMinidumpForSigInfo(int signo, siginfo_t* info, void* uc);
- #endif
- #ifdef XP_MACOSX
- nsresult AppendObjCExceptionInfoToAppNotes(void* inException);
- #endif
-@@ -242,17 +242,17 @@ bool CreateMinidumpsAndPair(ProcessHandl
- // a minidump (|parentMinidump|).
- // The resulting dump will get the id of the parent and use the |name| as
- // an extension.
- bool CreateAdditionalChildMinidump(ProcessHandle childPid,
-                                    ThreadId childBlamedThread,
-                                    nsIFile* parentMinidump,
-                                    const nsACString& name);
- 
--#if defined(XP_WIN32) || defined(XP_MACOSX)
-+#if defined(XP_WIN) || defined(XP_MACOSX)
- // Parent-side API for children
- const char* GetChildNotificationPipe();
- 
- #  ifdef MOZ_CRASHREPORTER_INJECTOR
- // Inject a crash report client into an arbitrary process, and inform the
- // callback object when it crashes. Parent process only.
- 
- class InjectorCrashCallback {
-@@ -270,17 +270,17 @@ class InjectorCrashCallback {
- };
- 
- // This method implies OOPInit
- void InjectCrashReporterIntoProcess(DWORD processID, InjectorCrashCallback* cb);
- void UnregisterInjectorCallback(DWORD processID);
- #  endif
- 
- // Child-side API
--#  if defined(XP_WIN32)
-+#  if defined(XP_WIN)
- bool SetRemoteExceptionHandler(const nsACString& crashPipe,
-                                uintptr_t aCrashTimeAnnotationFile);
- #  else
- bool SetRemoteExceptionHandler(const nsACString& crashPipe);
- #  endif
- 
- #else
- // Parent-side API for children
-@@ -293,17 +293,17 @@ bool SetRemoteExceptionHandler(const nsA
- //
- // If crash reporting is disabled, both outparams will be set to -1
- // and |true| will be returned.
- bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd);
- 
- // Child-side API
- bool SetRemoteExceptionHandler();
- 
--#endif  // XP_WIN32
-+#endif  // XP_WIN
- 
- bool UnsetRemoteExceptionHandler();
- 
- #if defined(MOZ_WIDGET_ANDROID)
- // Android creates child process as services so we must explicitly set
- // the handle for the pipe since it can't get remapped to a default value.
- void SetNotificationPipeForChild(int childCrashFd);
- void SetCrashAnnotationPipeForChild(int childCrashAnnotationFd);
-diff --git a/toolkit/crashreporter/test/nsTestCrasher.cpp b/toolkit/crashreporter/test/nsTestCrasher.cpp
---- a/toolkit/crashreporter/test/nsTestCrasher.cpp
-+++ b/toolkit/crashreporter/test/nsTestCrasher.cpp
-@@ -183,17 +183,17 @@ extern "C" NS_EXPORT uint64_t SaveAppMem
-   FILE* fp = fopen("crash-addr", "w");
-   if (!fp) return 0;
-   fprintf(fp, "%p\n", (void*)testData);
-   fclose(fp);
- 
-   return (int64_t)testData;
- }
- 
--#ifdef XP_WIN32
-+#ifdef XP_WIN
- static LONG WINAPI HandleException(EXCEPTION_POINTERS* exinfo) {
-   TerminateProcess(GetCurrentProcess(), 0);
-   return 0;
- }
- 
- extern "C" NS_EXPORT void TryOverrideExceptionHandler() {
-   SetUnhandledExceptionFilter(HandleException);
- }
-diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp
---- a/toolkit/xre/nsAppRunner.cpp
-+++ b/toolkit/xre/nsAppRunner.cpp
-@@ -186,17 +186,17 @@
- #  include "nsCommandLineServiceMac.h"
- #endif
- 
- // for X remote support
- #if defined(MOZ_HAS_REMOTE)
- #  include "nsRemoteService.h"
- #endif
- 
--#if defined(DEBUG) && defined(XP_WIN32)
-+#if defined(DEBUG) && defined(XP_WIN)
- #  include <malloc.h>
- #endif
- 
- #if defined(XP_MACOSX)
- #  include <Carbon/Carbon.h>
- #endif
- 
- #ifdef DEBUG
-@@ -1095,17 +1095,17 @@ nsXULAppInfo::AppendAppNotesToCrashRepor
- 
- NS_IMETHODIMP
- nsXULAppInfo::RegisterAppMemory(uint64_t pointer, uint64_t len) {
-   return CrashReporter::RegisterAppMemory((void*)pointer, len);
- }
- 
- NS_IMETHODIMP
- nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo) {
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-   return CrashReporter::WriteMinidumpForException(
-       static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
- #else
-   return NS_ERROR_NOT_IMPLEMENTED;
- #endif
- }
- 
- NS_IMETHODIMP
-@@ -5035,17 +5035,17 @@ void SetupErrorHandling(const char* prog
-   */
- 
-   HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
-   SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
-       (SetProcessDEPPolicyFunc)GetProcAddress(kernel32, "SetProcessDEPPolicy");
-   if (_SetProcessDEPPolicy) _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
- #endif
- 
--#ifdef XP_WIN32
-+#ifdef XP_WIN
-   // Suppress the "DLL Foo could not be found" dialog, such that if dependent
-   // libraries (such as GDI+) are not preset, we gracefully fail to load those
-   // XPCOM components, instead of being ungraceful.
-   UINT realMode = SetErrorMode(0);
-   realMode |= SEM_FAILCRITICALERRORS;
-   // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
-   // application has crashed" dialog box.  This is mainly useful for
-   // automated testing environments, e.g. tinderbox, where there's no need
-diff --git a/xpcom/build/PoisonIOInterposerBase.cpp b/xpcom/build/PoisonIOInterposerBase.cpp
---- a/xpcom/build/PoisonIOInterposerBase.cpp
-+++ b/xpcom/build/PoisonIOInterposerBase.cpp
-@@ -14,22 +14,22 @@
- 
- #include "prlock.h"
- 
- #ifdef MOZ_REPLACE_MALLOC
- #  include "replace_malloc_bridge.h"
- #endif
- 
- // Auxiliary method to convert file descriptors to ids
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
- #  include <io.h>
- inline intptr_t FileDescriptorToHandle(int aFd) { return _get_osfhandle(aFd); }
- #else
- inline intptr_t FileDescriptorToHandle(int aFd) { return aFd; }
--#endif /* if not XP_WIN32 */
-+#endif /* if not XP_WIN */
- 
- using namespace mozilla;
- 
- namespace {
- 
- struct DebugFilesAutoLockTraits {
-   typedef PRLock* type;
-   typedef const PRLock* const_type;
-diff --git a/xpcom/build/nsXPCOMPrivate.h b/xpcom/build/nsXPCOMPrivate.h
---- a/xpcom/build/nsXPCOMPrivate.h
-+++ b/xpcom/build/nsXPCOMPrivate.h
-@@ -47,17 +47,17 @@ void LogTerm();
-  *
-  * XPCOM_DLL              - name of the loadable xpcom library on disk.
-  * XUL_DLL                - name of the loadable XUL library on disk
-  * XPCOM_SEARCH_KEY       - name of the environment variable that can be
-  *                          modified to include additional search paths.
-  * GRE_CONF_NAME          - Name of the GRE Configuration file
-  */
- 
--#if defined(XP_WIN32)
-+#if defined(XP_WIN)
- 
- #  define XPCOM_SEARCH_KEY "PATH"
- #  define GRE_CONF_NAME "gre.config"
- #  define GRE_WIN_REG_LOC L"Software\\mozilla.org\\GRE"
- #  define XPCOM_DLL XUL_DLL
- #  define LXPCOM_DLL LXUL_DLL
- #  define XUL_DLL "xul.dll"
- #  define LXUL_DLL L"xul.dll"
-diff --git a/xpcom/ds/nsMathUtils.h b/xpcom/ds/nsMathUtils.h
---- a/xpcom/ds/nsMathUtils.h
-+++ b/xpcom/ds/nsMathUtils.h
-@@ -26,17 +26,17 @@ inline float NS_roundf(float aNum) {
- }
- inline int32_t NS_lround(double aNum) {
-   return aNum >= 0.0 ? int32_t(aNum + 0.5) : int32_t(aNum - 0.5);
- }
- 
- /* NS_roundup30 rounds towards infinity for positive and       */
- /* negative numbers.                                           */
- 
--#if defined(XP_WIN32) && defined(_M_IX86) && !defined(__GNUC__) && \
-+#if defined(XP_WIN) && defined(_M_IX86) && !defined(__GNUC__) && \
-     !defined(__clang__)
- inline int32_t NS_lroundup30(float x) {
-   /* Code derived from Laurent de Soras' paper at             */
-   /* http://ldesoras.free.fr/doc/articles/rounding_en.pdf     */
- 
-   /* Rounding up on Windows is expensive using the float to   */
-   /* int conversion and the floor function. A faster          */
-   /* approach is to use f87 rounding while assuming the       */
-@@ -57,17 +57,17 @@ inline int32_t NS_lroundup30(float x) {
-   __asm {
-     fld     x                   ; load fp argument
-     fadd    st, st(0)           ; double it
-     fadd    round_to_nearest    ; add the rounding factor
-     fistp   dword ptr i         ; convert the result to int
-   }
-   return i >> 1; /* divide by 2 */
- }
--#endif /* XP_WIN32 && _M_IX86 && !__GNUC__ */
-+#endif /* XP_WIN && _M_IX86 && !__GNUC__ */
- 
- inline int32_t NS_lroundf(float aNum) {
-   return aNum >= 0.0f ? int32_t(aNum + 0.5f) : int32_t(aNum - 0.5f);
- }
- 
- /*
-  * hypot.  We don't need a super accurate version of this, if a platform
-  * turns up with none of the possibilities below it would be okay to fall
-

+ 0 - 2679
frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-2-buildit-25318-rebase.patch

@@ -1,2679 +0,0 @@
-# HG changeset patch
-# Parent  9db540dae27672be91bc7f334bfc8c5b4bec32f3
-
-diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp
---- a/js/src/builtin/RegExp.cpp
-+++ b/js/src/builtin/RegExp.cpp
-@@ -1,62 +1,75 @@
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-  * vim: set ts=8 sts=4 et sw=4 tw=99:
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #include "builtin/RegExp.h"
- 
-+#include "mozilla/Casting.h"
- #include "mozilla/CheckedInt.h"
- #include "mozilla/TypeTraits.h"
- 
- #include "frontend/TokenStream.h"
--#include "irregexp/RegExpParser.h"
-+#include "irregexp/RegExpAPI.h"
- #include "jit/InlinableNatives.h"
-+#include "js/RegExpFlags.h"  // JS::RegExpFlag, JS::RegExpFlags
- #include "util/StringBuffer.h"
- #include "util/Unicode.h"
- #include "vm/JSContext.h"
- #include "vm/RegExpStatics.h"
- #include "vm/SelfHosting.h"
- 
- #include "vm/JSObject-inl.h"
- #include "vm/NativeObject-inl.h"
- #include "vm/UnboxedObject-inl.h"
- 
- using namespace js;
- using namespace js::unicode;
- 
-+using mozilla::AssertedCast;
- using mozilla::CheckedInt;
- 
-+using JS::RegExpFlag;
-+using JS::RegExpFlags;
-+
- /*
-- * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-- * steps 3, 16-25.
-+ * ES 2021 draft 21.2.5.2.2: Steps 16-28
-+ * https://tc39.es/ecma262/#sec-regexpbuiltinexec
-  */
- bool
--js::CreateRegExpMatchResult(JSContext* cx, HandleString input, const MatchPairs& matches,
-+js::CreateRegExpMatchResult(JSContext* cx,
-+                            HandleRegExpShared re,
-+                            HandleString input,
-+                            const MatchPairs& matches,
-                             MutableHandleValue rval)
- {
-+    MOZ_ASSERT(re);
-     MOZ_ASSERT(input);
- 
-     /*
-      * Create the (slow) result array for a match.
-      *
-      * Array contents:
-      *  0:              matched string
-      *  1..pairCount-1: paren matches
-      *  input:          input string
-      *  index:          start index for the match
-+     *  groups:         named capture groups for the match
-      */
- 
-     /* Get the templateObject that defines the shape and type of the output object */
-     JSObject* templateObject = cx->compartment()->regExps.getOrCreateMatchResultTemplateObject(cx);
--    if (!templateObject)
-+    if (!templateObject) {
-         return false;
-+    }
- 
-+    // Step 16
-     size_t numPairs = matches.length();
-     MOZ_ASSERT(numPairs > 0);
- 
-     /* Step 17. */
-     RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
-     if (!arr)
-         return false;
- 
-diff --git a/js/src/builtin/RegExp.cpp.rej b/js/src/builtin/RegExp.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/builtin/RegExp.cpp.rej
-@@ -0,0 +1,239 @@
-+--- RegExp.cpp
-++++ RegExp.cpp
-+@@ -1,111 +1,175 @@
-+ 
-+-    /* Step 17. */
-++    // Steps 18-19
-+     RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
-+-    if (!arr)
-++    if (!arr) {
-+         return false;
-++    }
-+ 
-+-    /* Steps 22-24.
-+-     * Store a Value for each pair. */
-++    // Step 24 (reordered)
-++    RootedNativeObject groups(cx);
-++    bool groupsInDictionaryMode = false;
-++    if (re->numNamedCaptures() > 0) {
-++        RootedNativeObject groupsTemplate(cx, re->getGroupsTemplate());
-++        if (groupsTemplate->inDictionaryMode()) {
-++            groups = NewObjectWithGivenProto<PlainObject>(cx, nullptr);
-++            groups->setGroup(groupsTemplate->group());
-++            groupsInDictionaryMode = true;
-++        } else {
-++            JS_TRY_VAR_OR_RETURN_FALSE(
-++              cx, groups, NativeObject::createWithTemplate(cx, gc::DefaultHeap, groupsTemplate));
-++        }
-++    }
-++
-++    // Steps 22-23 and 27 a-e.
-++    // Store a Value for each pair.
-+     for (size_t i = 0; i < numPairs; i++) {
-+         const MatchPair& pair = matches[i];
-+ 
-+         if (pair.isUndefined()) {
-+             MOZ_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
-+             arr->setDenseInitializedLength(i + 1);
-+             arr->initDenseElement(i, UndefinedValue());
-+         } else {
-+             JSLinearString* str = NewDependentString(cx, input, pair.start, pair.length());
-+             if (!str)
-+                 return false;
-+             arr->setDenseInitializedLength(i + 1);
-+             arr->initDenseElement(i, StringValue(str));
-+         }
-+     }
-+ 
-++    // Step 27 f.
-++    // The groups template object stores the names of the named captures in the
-++    // the order in which they are defined. The named capture indices vector
-++    // stores the corresponding capture indices. If we are not in dictionary mode,
-++    // we simply fill in the slots with the correct values. In dictionary mode,
-++    // we have to define the properties explicitly.
-++    if (!groupsInDictionaryMode) {
-++        for (uint32_t i = 0; i < re->numNamedCaptures(); i++) {
-++            uint32_t idx = re->getNamedCaptureIndex(i);
-++            groups->setSlot(i, arr->getDenseElement(idx));
-++        }
-++    } else {
-++        AutoIdVector keys(cx);
-++        RootedPlainObject groupsTemplate(cx, re->getGroupsTemplate());
-++        if (!GetPropertyKeys(cx, groupsTemplate, 0, &keys)) {
-++            return false;
-++        }
-++        MOZ_ASSERT(keys.length() == re->numNamedCaptures());
-++        RootedId key(cx);
-++        RootedValue val(cx);
-++        for (uint32_t i = 0; i < keys.length(); i++) {
-++            key = keys[i];
-++            uint32_t idx = re->getNamedCaptureIndex(i);
-++            val = arr->getDenseElement(idx);
-++            if (!NativeDefineDataProperty(cx, groups, key, val, JSPROP_ENUMERATE)) {
-++                return false;
-++            }
-++        }
-++    }
-++
-+     /* Step 20 (reordered).
-+      * Set the |index| property. (TemplateObject positions it in slot 0) */
-+     arr->setSlot(0, Int32Value(matches[0].start));
-+ 
-+     /* Step 21 (reordered).
-+      * Set the |input| property. (TemplateObject positions it in slot 1) */
-+     arr->setSlot(1, StringValue(input));
-+ 
-++    // Steps 25-26 (reordered)
-++    // Set the |groups| property.
-++    arr->setSlot(2, groups ? ObjectValue(*groups) : UndefinedValue());
-++
-+ #ifdef DEBUG
-+     RootedValue test(cx);
-+     RootedId id(cx, NameToId(cx->names().index));
-+     if (!NativeGetProperty(cx, arr, id, &test))
-+         return false;
-+     MOZ_ASSERT(test == arr->getSlot(0));
-+     id = NameToId(cx->names().input);
-+     if (!NativeGetProperty(cx, arr, id, &test))
-+         return false;
-+     MOZ_ASSERT(test == arr->getSlot(1));
-+ #endif
-+ 
-+-    /* Step 25. */
-++    // Step 28.
-+     rval.setObject(*arr);
-+     return true;
-+ }
-+ 
-+ static int32_t
-+ CreateRegExpSearchResult(const MatchPairs& matches)
-+ {
-+     /* Fit the start and limit of match into a int32_t. */
-+@@ -116,29 +180,29 @@ CreateRegExpSearchResult(const MatchPair
-+     return position | (lastIndex << 15);
-+ }
-+ 
-+ /*
-+  * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-+  * steps 3, 9-14, except 12.a.i, 12.c.i.1.
-+  */
-+ static RegExpRunStatus
-+-ExecuteRegExpImpl(JSContext* cx, RegExpStatics* res, MutableHandleRegExpShared re,
-+-                  HandleLinearString input, size_t searchIndex, MatchPairs* matches,
-+-                  size_t* endIndex)
-++ExecuteRegExpImpl(JSContext* cx,
-++                  RegExpStatics* res,
-++                  MutableHandleRegExpShared re,
-++                  HandleLinearString input,
-++                  size_t searchIndex,
-++                  MatchPairs* matches)
-+ {
-+-    RegExpRunStatus status = RegExpShared::execute(cx, re, input, searchIndex, matches, endIndex);
-++    RegExpRunStatus status = RegExpShared::execute(cx, re, input, searchIndex, matches);
-+ 
-+     /* Out of spec: Update RegExpStatics. */
-+     if (status == RegExpRunStatus_Success && res) {
-+-        if (matches) {
-+-            if (!res->updateFromMatchPairs(cx, input, *matches))
-+-                return RegExpRunStatus_Error;
-+-        } else {
-+-            res->updateLazily(cx, input, re, searchIndex);
-++        if (!res->updateFromMatchPairs(cx, input, *matches)) {
-++            return RegExpRunStatus_Error;
-+         }
-+     }
-+     return status;
-+ }
-+ 
-+ /* Legacy ExecuteRegExp behavior is baked into the JSAPI. */
-+ bool
-+ js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
-+@@ -147,17 +211,17 @@ js::ExecuteRegExpLegacy(JSContext* cx, R
-+ {
-+     RootedRegExpShared shared(cx, RegExpObject::getShared(cx, reobj));
-+     if (!shared)
-+         return false;
-+ 
-+     ScopedMatchPairs matches(&cx->tempLifoAlloc());
-+ 
-+     RegExpRunStatus status = ExecuteRegExpImpl(cx, res, &shared, input, *lastIndex,
-+-                                               &matches, nullptr);
-++                                               &matches);
-+     if (status == RegExpRunStatus_Error)
-+         return false;
-+ 
-+     if (status == RegExpRunStatus_Success_NotFound) {
-+         /* ExecuteRegExp() previously returned an array or null. */
-+         rval.setNull();
-+         return true;
-+     }
-+@@ -901,17 +993,17 @@ IsTrailSurrogateWithLeadSurrogate(Handle
-+ }
-+ 
-+ /*
-+  * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-+  * steps 3, 9-14, except 12.a.i, 12.c.i.1.
-+  */
-+ static RegExpRunStatus
-+ ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex,
-+-              MatchPairs* matches, size_t* endIndex)
-++              MatchPairs* matches)
-+ {
-+     /*
-+      * WARNING: Despite the presence of spec step comment numbers, this
-+      *          algorithm isn't consistent with any ES6 version, draft or
-+      *          otherwise.  YOU HAVE BEEN WARNED.
-+      */
-+ 
-+     /* Steps 1-2 performed by the caller. */
-+@@ -979,28 +1071,29 @@ ExecuteRegExp(JSContext* cx, HandleObjec
-+ static bool
-+ RegExpMatcherImpl(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex,
-+                   MutableHandleValue rval)
-+ {
-+     /* Execute regular expression and gather matches. */
-+     ScopedMatchPairs matches(&cx->tempLifoAlloc());
-+ 
-+     /* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */
-+-    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches, nullptr);
-++    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches);
-+     if (status == RegExpRunStatus_Error)
-+         return false;
-+ 
-+     /* Steps 12.a, 12.c. */
-+     if (status == RegExpRunStatus_Success_NotFound) {
-+         rval.setNull();
-+         return true;
-+     }
-+ 
-+     /* Steps 16-25 */
-+-    return CreateRegExpMatchResult(cx, string, matches, rval);
-++    RootedRegExpShared shared(cx, regexp->as<RegExpObject>().getShared());
-++    return CreateRegExpMatchResult(cx, shared, string, matches, rval);
-+ }
-+ 
-+ /*
-+  * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-+  * steps 3, 9-25, except 12.a.i, 12.c.i.1, 15.
-+  */
-+ bool
-+ js::RegExpMatcher(JSContext* cx, unsigned argc, Value* vp)
-+@@ -1048,17 +1144,17 @@ js::RegExpMatcherRaw(JSContext* cx, Hand
-+ static bool
-+ RegExpSearcherImpl(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex,
-+                    int32_t* result)
-+ {
-+     /* Execute regular expression and gather matches. */
-+     ScopedMatchPairs matches(&cx->tempLifoAlloc());
-+ 
-+     /* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */
-+-    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches, nullptr);
-++    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches);
-+     if (status == RegExpRunStatus_Error)
-+         return false;
-+ 
-+     /* Steps 12.a, 12.c. */
-+     if (status == RegExpRunStatus_Success_NotFound) {
-+         *result = -1;
-+         return true;
-+     }
-diff --git a/js/src/builtin/String.js.rej b/js/src/builtin/String.js.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/builtin/String.js.rej
-@@ -0,0 +1,62 @@
-+--- String.js
-++++ String.js
-+@@ -57,16 +57,59 @@ function String_match(regexp) {
-+ 
-+ function String_generic_match(thisValue, regexp) {
-+     WarnDeprecatedStringMethod(STRING_GENERICS_MATCH, "match");
-+     if (thisValue === undefined)
-+         ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "String.match");
-+     return callFunction(String_match, thisValue, regexp);
-+ }
-+ 
-++// String.prototype.matchAll proposal.
-++//
-++// String.prototype.matchAll ( regexp )
-++function String_matchAll(regexp) {
-++    // Step 1.
-++    RequireObjectCoercible(this);
-++
-++    // Step 2.
-++    if (regexp !== undefined && regexp !== null) {
-++        // Steps 2.a-b.
-++        if (IsRegExp(regexp)) {
-++            // Step 2.b.i.
-++            var flags = regexp.flags;
-++
-++            // Step 2.b.ii.
-++            if (flags === undefined || flags === null) {
-++                ThrowTypeError(JSMSG_FLAGS_UNDEFINED_OR_NULL);
-++            }
-++
-++            // Step 2.b.iii.
-++            if (!callFunction(std_String_includes, ToString(flags), "g")) {
-++                ThrowTypeError(JSMSG_REQUIRES_GLOBAL_REGEXP, "matchAll");
-++            }
-++        }
-++
-++        // Step 2.c.
-++        var matcher = GetMethod(regexp, std_matchAll);
-++
-++        // Step 2.d.
-++        if (matcher !== undefined)
-++            return callContentFunction(matcher, regexp, this);
-++    }
-++
-++    // Step 3.
-++    var string = ToString(this);
-++
-++    // Step 4.
-++    var rx = RegExpCreate(regexp, "g");
-++
-++    // Step 5.
-++    return callContentFunction(GetMethod(rx, std_matchAll), rx, string);
-++}
-++
-+ /**
-+  * A helper function implementing the logic for both String.prototype.padStart
-+  * and String.prototype.padEnd as described in ES7 Draft March 29, 2016
-+  */
-+ function String_pad(maxLength, fillString, padEnd = false) {
-+ 
-+     // Steps 1-2.
-+     RequireObjectCoercible(this);
-diff --git a/js/src/builtin/TestingFunctions.cpp.rej b/js/src/builtin/TestingFunctions.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/builtin/TestingFunctions.cpp.rej
-@@ -0,0 +1,28 @@
-+--- TestingFunctions.cpp
-++++ TestingFunctions.cpp
-+@@ -23,24 +23,22 @@
-+ #include "jsiter.h"
-+ #include "jsprf.h"
-+ #include "jswrapper.h"
-+ 
-+ #include "builtin/Promise.h"
-+ #include "builtin/SelfHostingDefines.h"
-+ #ifdef DEBUG
-+ #include "frontend/TokenStream.h"
-+-#include "irregexp/RegExpAST.h"
-+-#include "irregexp/RegExpEngine.h"
-+-#include "irregexp/RegExpParser.h"
-+ #endif
-+ #include "jit/BaselineJIT.h"
-+ #include "jit/InlinableNatives.h"
-+ #include "js/Debug.h"
-+ #include "js/HashTable.h"
-++#include "js/RegExpFlags.h"
-+ #include "js/StructuredClone.h"
-+ #include "js/UbiNode.h"
-+ #include "js/UbiNodeBreadthFirst.h"
-+ #include "js/UbiNodeShortestPaths.h"
-+ #include "js/UniquePtr.h"
-+ #include "js/Vector.h"
-+ #include "vm/AsyncFunction.h"
-+ #include "vm/AsyncIteration.h"
-diff --git a/js/src/frontend/Parser.cpp.rej b/js/src/frontend/Parser.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/Parser.cpp.rej
-@@ -0,0 +1,22 @@
-+--- Parser.cpp
-++++ Parser.cpp
-+@@ -32,17 +32,18 @@
-+ #include "jsopcode.h"
-+ #include "jstypes.h"
-+ 
-+ #include "builtin/ModuleObject.h"
-+ #include "builtin/SelfHostingDefines.h"
-+ #include "frontend/BytecodeCompiler.h"
-+ #include "frontend/FoldConstants.h"
-+ #include "frontend/TokenStream.h"
-+-#include "irregexp/RegExpParser.h"
-++#include "irregexp/RegExpAPI.h"
-++#include "js/RegExpFlags.h"
-+ #include "vm/JSAtom.h"
-+ #include "vm/JSContext.h"
-+ #include "vm/JSFunction.h"
-+ #include "vm/JSScript.h"
-+ #include "vm/RegExpObject.h"
-+ #include "wasm/AsmJS.h"
-+ 
-+ #include "frontend/ParseContext-inl.h"
-diff --git a/js/src/frontend/TokenStream.cpp.rej b/js/src/frontend/TokenStream.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/TokenStream.cpp.rej
-@@ -0,0 +1,38 @@
-+--- TokenStream.cpp
-++++ TokenStream.cpp
-+@@ -20,31 +20,35 @@
-+ 
-+ #include "jsexn.h"
-+ #include "jsnum.h"
-+ 
-+ #include "frontend/BytecodeCompiler.h"
-+ #include "frontend/Parser.h"
-+ #include "frontend/ReservedWords.h"
-+ #include "js/CharacterEncoding.h"
-++#include "js/RegExpFlags.h"  // JS::RegExpFlags
-+ #include "js/UniquePtr.h"
-+ #include "vm/HelperThreads.h"
-+ #include "vm/JSAtom.h"
-+ #include "vm/JSCompartment.h"
-+ #include "vm/JSContext.h"
-+ #include "vm/StringBuffer.h"
-+ #include "vm/Unicode.h"
-+ 
-+ using mozilla::ArrayLength;
-+ using mozilla::MakeScopeExit;
-+ using mozilla::Maybe;
-+ using mozilla::PodAssign;
-+ using mozilla::PodCopy;
-+ using mozilla::PodZero;
-+ 
-++using JS::RegExpFlag;
-++using JS::RegExpFlags;
-++
-+ struct ReservedWordInfo
-+ {
-+     const char* chars;         // C string with reserved word text
-+     js::frontend::TokenKind tokentype;
-+ };
-+ 
-+ static const ReservedWordInfo reservedWords[] = {
-+ #define RESERVED_WORD_INFO(word, name, type) \
-diff --git a/js/src/frontend/TokenStream.h.rej b/js/src/frontend/TokenStream.h.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/frontend/TokenStream.h.rej
-@@ -0,0 +1,25 @@
-+--- TokenStream.h
-++++ TokenStream.h
-+@@ -171,21 +171,21 @@
-+ #include <stdarg.h>
-+ #include <stddef.h>
-+ #include <stdio.h>
-+ 
-+ #include "jspubtd.h"
-+ 
-+ #include "frontend/ErrorReporter.h"
-+ #include "frontend/TokenKind.h"
-++#include "js/RegExpFlags.h"
-+ #include "js/UniquePtr.h"
-+ #include "js/Vector.h"
-+ #include "vm/ErrorReporting.h"
-+ #include "vm/JSContext.h"
-+-#include "vm/RegExpShared.h"
-+ #include "vm/String.h"
-+ #include "vm/Unicode.h"
-+ 
-+ struct KeywordInfo;
-+ 
-+ namespace js {
-+ namespace frontend {
-+ 
-diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
---- a/js/src/jit/CodeGenerator.cpp
-+++ b/js/src/jit/CodeGenerator.cpp
-@@ -23,31 +23,32 @@
- #include "jsnum.h"
- 
- #include "builtin/Eval.h"
- #include "builtin/RegExp.h"
- #include "builtin/SelfHostingDefines.h"
- #include "builtin/String.h"
- #include "builtin/TypedObject.h"
- #include "gc/Nursery.h"
--#include "irregexp/NativeRegExpMacroAssembler.h"
-+#include "irregexp/RegExpTypes.h"
- #include "jit/AtomicOperations.h"
- #include "jit/BaselineCompiler.h"
- #include "jit/IonBuilder.h"
- #include "jit/IonIC.h"
- #include "jit/IonOptimizationLevels.h"
- #include "jit/JitcodeMap.h"
- #include "jit/JitSpewer.h"
- #include "jit/Linker.h"
- #include "jit/Lowering.h"
- #include "jit/MIRGenerator.h"
- #include "jit/MoveEmitter.h"
- #include "jit/RangeAnalysis.h"
- #include "jit/SharedICHelpers.h"
- #include "jit/StackSlotAllocator.h"
-+#include "js/RegExpFlags.h"
- #include "util/Unicode.h"
- #include "vm/AsyncFunction.h"
- #include "vm/AsyncIteration.h"
- #include "vm/MatchPairs.h"
- #include "vm/RegExpObject.h"
- #include "vm/RegExpStatics.h"
- #include "vm/StringType.h"
- #include "vm/TraceLogging.h"
-@@ -1350,235 +1351,105 @@ CodeGenerator::visitRegExp(LRegExp* lir)
-                                    StoreRegisterTo(output));
-     if (lir->mir()->hasShared())
-         masm.createGCObject(output, temp, templateObject, gc::DefaultHeap, ool->entry());
-     else
-         masm.jump(ool->entry());
-     masm.bind(ool->rejoin());
- }
- 
-+static const size_t InputOutputDataSize = sizeof(irregexp::InputOutputData);
-+
- // Amount of space to reserve on the stack when executing RegExps inline.
--static const size_t RegExpReservedStack = sizeof(irregexp::InputOutputData)
-+static const size_t RegExpReservedStack = InputOutputDataSize
-                                         + sizeof(MatchPairs)
-                                         + RegExpObject::MaxPairCount * sizeof(MatchPair);
- 
- static size_t
- RegExpPairsVectorStartOffset(size_t inputOutputDataStartOffset)
- {
--    return inputOutputDataStartOffset + sizeof(irregexp::InputOutputData) + sizeof(MatchPairs);
-+    return inputOutputDataStartOffset + InputOutputDataSize + sizeof(MatchPairs);
- }
- 
- static Address
- RegExpPairCountAddress(MacroAssembler& masm, size_t inputOutputDataStartOffset)
- {
-     return Address(masm.getStackPointer(), inputOutputDataStartOffset
--                                           + sizeof(irregexp::InputOutputData)
-+                                           + InputOutputDataSize
-                                            + MatchPairs::offsetOfPairCount());
- }
- 
--// Prepare an InputOutputData and optional MatchPairs which space has been
--// allocated for on the stack, and try to execute a RegExp on a string input.
--// If the RegExp was successfully executed and matched the input, fallthrough,
--// otherwise jump to notFound or failure.
--static bool
--PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm, Register regexp, Register input,
-+// When the unicode flag is set, if lastIndex points to a trail
-+// surrogate, we should step back to the corresponding lead surrogate.
-+// See ExecuteRegExp in builtin/RegExp.cpp for more detail.
-+static void
-+StepBackToLeadSurrogate(MacroAssembler& masm,
-+                        Register regexpShared,
-+                        Register input,
-                         Register lastIndex,
--                        Register temp1, Register temp2, Register temp3,
--                        size_t inputOutputDataStartOffset,
--                        RegExpShared::CompilationMode mode,
--                        Label* notFound, Label* failure)
--{
--    size_t matchPairsStartOffset = inputOutputDataStartOffset + sizeof(irregexp::InputOutputData);
--    size_t pairsVectorStartOffset = RegExpPairsVectorStartOffset(inputOutputDataStartOffset);
--
--    Address inputStartAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, inputStart));
--    Address inputEndAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, inputEnd));
--    Address matchesPointerAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, matches));
--    Address startIndexAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, startIndex));
--    Address endIndexAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, endIndex));
--    Address matchResultAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, result));
--
--    Address pairCountAddress = RegExpPairCountAddress(masm, inputOutputDataStartOffset);
--    Address pairsPointerAddress(masm.getStackPointer(),
--        matchPairsStartOffset + MatchPairs::offsetOfPairs());
--
--    Address pairsVectorAddress(masm.getStackPointer(), pairsVectorStartOffset);
--
--    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global());
--    if (!res)
--        return false;
--#ifdef JS_USE_LINK_REGISTER
--    if (mode != RegExpShared::MatchOnly)
--        masm.pushReturnAddress();
--#endif
--    if (mode == RegExpShared::Normal) {
--        // First, fill in a skeletal MatchPairs instance on the stack. This will be
--        // passed to the OOL stub in the caller if we aren't able to execute the
--        // RegExp inline, and that stub needs to be able to determine whether the
--        // execution finished successfully.
--        masm.store32(Imm32(1), pairCountAddress);
--        masm.store32(Imm32(-1), pairsVectorAddress);
--        masm.computeEffectiveAddress(pairsVectorAddress, temp1);
--        masm.storePtr(temp1, pairsPointerAddress);
--    }
--
--    // Check for a linear input string.
--    masm.branchIfRopeOrExternal(input, temp1, failure);
--
--    // Get the RegExpShared for the RegExp.
--    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)), temp1);
--    masm.branchPtr(Assembler::Equal, temp1, ImmWord(0), failure);
--
--    // ES6 21.2.2.2 step 2.
--    // See RegExp.cpp ExecuteRegExp for more detail.
--    {
--        Label done;
--
--        masm.branchTest32(Assembler::Zero, Address(temp1, RegExpShared::offsetOfFlags()),
--                          Imm32(UnicodeFlag), &done);
--
--        // If input is latin1, there should not be surrogate pair.
--        masm.branchLatin1String(input, &done);
--
--        // Check if |lastIndex > 0 && lastIndex < input->length()|.
--        // lastIndex should already have no sign here.
--        masm.branchTest32(Assembler::Zero, lastIndex, lastIndex, &done);
--        masm.loadStringLength(input, temp2);
--        masm.branch32(Assembler::AboveOrEqual, lastIndex, temp2, &done);
--
--        // Check if input[lastIndex] is trail surrogate.
--        masm.loadStringChars(input, temp2, CharEncoding::TwoByte);
--        masm.computeEffectiveAddress(BaseIndex(temp2, lastIndex, TimesTwo), temp3);
--        masm.load16ZeroExtend(Address(temp3, 0), temp3);
--
--        masm.branch32(Assembler::Below, temp3, Imm32(unicode::TrailSurrogateMin), &done);
--        masm.branch32(Assembler::Above, temp3, Imm32(unicode::TrailSurrogateMax), &done);
--
--        // Check if input[lastIndex-1] is lead surrogate.
--        masm.move32(lastIndex, temp3);
--        masm.sub32(Imm32(1), temp3);
--        masm.computeEffectiveAddress(BaseIndex(temp2, temp3, TimesTwo), temp3);
--        masm.load16ZeroExtend(Address(temp3, 0), temp3);
--
--        masm.branch32(Assembler::Below, temp3, Imm32(unicode::LeadSurrogateMin), &done);
--        masm.branch32(Assembler::Above, temp3, Imm32(unicode::LeadSurrogateMax), &done);
--
--        // Move lastIndex to lead surrogate.
--        masm.subPtr(Imm32(1), lastIndex);
--
--        masm.bind(&done);
--    }
--
--    if (mode == RegExpShared::Normal) {
--        // Don't handle RegExps with excessive parens.
--        masm.load32(Address(temp1, RegExpShared::offsetOfParenCount()), temp2);
--        masm.branch32(Assembler::AboveOrEqual, temp2, Imm32(RegExpObject::MaxPairCount), failure);
--
--        // Fill in the paren count in the MatchPairs on the stack.
--        masm.add32(Imm32(1), temp2);
--        masm.store32(temp2, pairCountAddress);
--    }
--
--    // Load the code pointer for the type of input string we have, and compute
--    // the input start/end pointers in the InputOutputData.
--    Register codePointer = temp1;
--    {
--        masm.loadStringLength(input, temp3);
--
--        Label isLatin1, done;
--        masm.branchLatin1String(input, &isLatin1);
--        {
--            masm.loadStringChars(input, temp2, CharEncoding::TwoByte);
--            masm.storePtr(temp2, inputStartAddress);
--            masm.lshiftPtr(Imm32(1), temp3);
--            masm.loadPtr(Address(temp1, RegExpShared::offsetOfTwoByteJitCode(mode)),
--                         codePointer);
--            masm.jump(&done);
--        }
--        masm.bind(&isLatin1);
--        {
--            masm.loadStringChars(input, temp2, CharEncoding::Latin1);
--            masm.storePtr(temp2, inputStartAddress);
--            masm.loadPtr(Address(temp1, RegExpShared::offsetOfLatin1JitCode(mode)),
--                         codePointer);
--        }
--        masm.bind(&done);
--
--        masm.addPtr(temp3, temp2);
--        masm.storePtr(temp2, inputEndAddress);
--    }
--
--    // Check the RegExpShared has been compiled for this type of input.
--    masm.branchPtr(Assembler::Equal, codePointer, ImmWord(0), failure);
--    masm.loadPtr(Address(codePointer, JitCode::offsetOfCode()), codePointer);
--
--    // Finish filling in the InputOutputData instance on the stack.
--    if (mode == RegExpShared::Normal) {
--        masm.computeEffectiveAddress(Address(masm.getStackPointer(), matchPairsStartOffset), temp2);
--        masm.storePtr(temp2, matchesPointerAddress);
--    } else {
--        // Use InputOutputData.endIndex itself for output.
--        masm.computeEffectiveAddress(endIndexAddress, temp2);
--        masm.storePtr(temp2, endIndexAddress);
--    }
--    masm.storePtr(lastIndex, startIndexAddress);
--    masm.store32(Imm32(0), matchResultAddress);
--
--    // Save any volatile inputs.
--    LiveGeneralRegisterSet volatileRegs;
--    if (lastIndex.volatile_())
--        volatileRegs.add(lastIndex);
--    if (input.volatile_())
--        volatileRegs.add(input);
--    if (regexp.volatile_())
--        volatileRegs.add(regexp);
--
--#ifdef JS_TRACE_LOGGING
--    if (TraceLogTextIdEnabled(TraceLogger_IrregexpExecute)) {
--        masm.push(temp1);
--        masm.loadTraceLogger(temp1);
--        masm.tracelogStartId(temp1, TraceLogger_IrregexpExecute);
--        masm.pop(temp1);
--    }
--#endif
--
--    // Execute the RegExp.
--    masm.computeEffectiveAddress(Address(masm.getStackPointer(), inputOutputDataStartOffset), temp2);
--    masm.PushRegsInMask(volatileRegs);
--    masm.setupUnalignedABICall(temp3);
--    masm.passABIArg(temp2);
--    masm.callWithABI(codePointer);
--    masm.PopRegsInMask(volatileRegs);
--
--#ifdef JS_TRACE_LOGGING
--    if (TraceLogTextIdEnabled(TraceLogger_IrregexpExecute)) {
--        masm.loadTraceLogger(temp1);
--        masm.tracelogStopId(temp1, TraceLogger_IrregexpExecute);
--    }
--#endif
--
--    Label success;
--    masm.branch32(Assembler::Equal, matchResultAddress,
--                  Imm32(RegExpRunStatus_Success_NotFound), notFound);
--    masm.branch32(Assembler::Equal, matchResultAddress,
--                  Imm32(RegExpRunStatus_Error), failure);
--
--    // Lazily update the RegExpStatics.
--    masm.movePtr(ImmPtr(res), temp1);
--
--    Address pendingInputAddress(temp1, RegExpStatics::offsetOfPendingInput());
--    Address matchesInputAddress(temp1, RegExpStatics::offsetOfMatchesInput());
--    Address lazySourceAddress(temp1, RegExpStatics::offsetOfLazySource());
--    Address lazyIndexAddress(temp1, RegExpStatics::offsetOfLazyIndex());
-+                        Register temp1,
-+                        Register temp2)
-+{
-+    Label done;
-+
-+    // If the unicode flag is not set, there is nothing to do.
-+    masm.branchTest32(Assembler::Zero,
-+                      Address(regexpShared, RegExpShared::offsetOfFlags()),
-+                      Imm32(int32_t(JS::RegExpFlag::Unicode)),
-+                      &done);
-+
-+    // If the input is latin1, there can't be any surrogates.
-+    masm.branchLatin1String(input, &done);
-+
-+    // Check if |lastIndex > 0 && lastIndex < input->length()|.
-+    // lastIndex should already have no sign here.
-+    masm.branchTest32(Assembler::Zero, lastIndex, lastIndex, &done);
-+    masm.loadStringLength(input, temp1);
-+    masm.branch32(Assembler::AboveOrEqual, lastIndex, temp1, &done);
-+
-+    Register charsReg = temp1;
-+    masm.loadStringChars(input, charsReg);
-+
-+    // Check if input[lastIndex] is trail surrogate.
-+    masm.computeEffectiveAddress(BaseIndex(charsReg, lastIndex, TimesTwo), temp2);
-+    masm.load16ZeroExtend(Address(temp2, 0), temp2);
-+
-+    masm.branch32(Assembler::Below, temp2, Imm32(unicode::TrailSurrogateMin), &done);
-+    masm.branch32(Assembler::Above, temp2, Imm32(unicode::TrailSurrogateMax), &done);
-+
-+    // Check if input[lastIndex-1] is lead surrogate.
-+    masm.move32(lastIndex, temp2);
-+    masm.sub32(Imm32(1), temp2);
-+    masm.computeEffectiveAddress(BaseIndex(charsReg, temp2, TimesTwo), temp2);
-+    masm.load16ZeroExtend(Address(temp2, 0), temp2);
-+
-+    masm.branch32(Assembler::Below, temp2, Imm32(unicode::LeadSurrogateMin), &done);
-+    masm.branch32(Assembler::Above, temp2, Imm32(unicode::LeadSurrogateMax), &done);
-+
-+    // Move lastIndex back to lead surrogate.
-+    masm.subPtr(Imm32(1), lastIndex);
-+
-+    masm.bind(&done);
-+}
-+
-+static void
-+UpdateRegExpStatics(MacroAssembler& masm,
-+                    Register regexp,
-+                    Register input,
-+                    Register lastIndex,
-+                    Register staticsReg,
-+                    Register temp1,
-+                    Register temp2,
-+                    bool stringsCanBeInNursery,
-+                    LiveGeneralRegisterSet& volatileRegs)
-+{
-+    Address pendingInputAddress(staticsReg, RegExpStatics::offsetOfPendingInput());
-+    Address matchesInputAddress(staticsReg, RegExpStatics::offsetOfMatchesInput());
-+    Address lazySourceAddress(staticsReg, RegExpStatics::offsetOfLazySource());
-+    Address lazyIndexAddress(staticsReg, RegExpStatics::offsetOfLazyIndex());
- 
-     masm.guardedCallPreBarrier(pendingInputAddress, MIRType::String);
-     masm.guardedCallPreBarrier(matchesInputAddress, MIRType::String);
-     masm.guardedCallPreBarrier(lazySourceAddress, MIRType::String);
- 
-     if (temp1.volatile_())
-         volatileRegs.add(temp1);
- 
-diff --git a/js/src/jit/CodeGenerator.cpp.rej b/js/src/jit/CodeGenerator.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit/CodeGenerator.cpp.rej
-@@ -0,0 +1,299 @@
-+--- CodeGenerator.cpp
-++++ CodeGenerator.cpp
-+@@ -1204,253 +1205,324 @@ CodeGenerator::visitRegExp(LRegExp* lir)
-+ 
-+     masm.guardedCallPreBarrier(pendingInputAddress, MIRType::String);
-+     masm.guardedCallPreBarrier(matchesInputAddress, MIRType::String);
-+     masm.guardedCallPreBarrier(lazySourceAddress, MIRType::String);
-+ 
-+     masm.storePtr(input, pendingInputAddress);
-+     masm.storePtr(input, matchesInputAddress);
-+-    masm.storePtr(lastIndex, Address(temp1, RegExpStatics::offsetOfLazyIndex()));
-+-    masm.store32(Imm32(1), Address(temp1, RegExpStatics::offsetOfPendingLazyEvaluation()));
-+-
-+-    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)), temp2);
-+-    masm.loadPtr(Address(temp2, RegExpShared::offsetOfSource()), temp3);
-+-    masm.storePtr(temp3, lazySourceAddress);
-+-    masm.load32(Address(temp2, RegExpShared::offsetOfFlags()), temp3);
-+-    masm.store32(temp3, Address(temp1, RegExpStatics::offsetOfLazyFlags()));
-+-
-+-    if (mode == RegExpShared::MatchOnly) {
-+-        // endIndex is passed via temp3.
-+-        masm.load32(endIndexAddress, temp3);
-+-    }
-++    masm.storePtr(lastIndex, Address(staticsReg, RegExpStatics::offsetOfLazyIndex()));
-++    masm.store32(Imm32(1), Address(staticsReg, RegExpStatics::offsetOfPendingLazyEvaluation()));
-++
-++    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)),
-++                 temp1);
-++    masm.loadPtr(Address(temp1, RegExpShared::offsetOfSource()), temp2);
-++    masm.storePtr(temp2, lazySourceAddress);
-++    masm.load32(Address(temp1, RegExpShared::offsetOfFlags()), temp2);
-++    masm.store32(temp2, Address(staticsReg, RegExpStatics::offsetOfLazyFlags()));
-++}
-++
-++// Prepare an InputOutputData and optional MatchPairs which space has been
-++// allocated for on the stack, and try to execute a RegExp on a string input.
-++// If the RegExp was successfully executed and matched the input, fallthrough.
-++// Otherwise, jump to notFound or failure.
-++static bool
-++PrepareAndExecuteRegExp(JSContext* cx,
-++                        MacroAssembler& masm,
-++                        Register regexp,
-++                        Register input,
-++                        Register lastIndex,
-++                        Register temp1,
-++                        Register temp2,
-++                        Register temp3,
-++                        size_t inputOutputDataStartOffset,
-++                        bool stringsCanBeInNursery,
-++                        Label* notFound,
-++                        Label* failure)
-++{
-++    using irregexp::InputOutputData;
-++
-++    size_t ioOffset = inputOutputDataStartOffset;
-++    size_t matchPairsOffset = ioOffset + sizeof(InputOutputData);
-++    size_t pairsArrayOffset = matchPairsOffset + sizeof(MatchPairs);
-++
-++    Address inputStartAddress(masm.getStackPointer(),
-++                              ioOffset + offsetof(InputOutputData, inputStart));
-++    Address inputEndAddress(masm.getStackPointer(),
-++                            ioOffset + offsetof(InputOutputData, inputEnd));
-++    Address startIndexAddress(masm.getStackPointer(),
-++                              ioOffset + offsetof(InputOutputData, startIndex));
-++    Address matchesAddress(masm.getStackPointer(), ioOffset + offsetof(InputOutputData, matches));
-++
-++    Address matchPairsAddress(masm.getStackPointer(), matchPairsOffset);
-++    Address pairCountAddress(masm.getStackPointer(),
-++                             matchPairsOffset + MatchPairs::offsetOfPairCount());
-++    Address pairsPointerAddress(masm.getStackPointer(),
-++                                matchPairsOffset + MatchPairs::offsetOfPairs());
-++
-++    Address pairsArrayAddress(masm.getStackPointer(), pairsArrayOffset);
-++
-++    // First, fill in a skeletal MatchPairs instance on the stack. This will be
-++    // passed to the OOL stub in the caller if we aren't able to execute the
-++    // RegExp inline, and that stub needs to be able to determine whether the
-++    // execution finished successfully.
-++
-++    // Initialize MatchPairs::pairCount to 1. The correct value can only
-++    // be determined after loading the RegExpShared. If the RegExpShared
-++    // has Kind::Atom, this is the correct pairCount.
-++    masm.store32(Imm32(1), pairCountAddress);
-++
-++    // Initialize MatchPairs::pairs pointer
-++    masm.store32(Imm32(-1), pairsArrayAddress);
-++    masm.computeEffectiveAddress(pairsArrayAddress, temp1);
-++    masm.storePtr(temp1, pairsPointerAddress);
-++
-++    // Check for a linear input string.
-++    masm.branchIfRopeOrExternal(input, temp1, failure);
-++
-++    // Load the RegExpShared.
-++    Register regexpReg = temp1;
-++
-++    // Get the RegExpShared for the RegExp.
-++    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)),
-++                 regexpReg);
-++    masm.branchPtr(Assembler::Equal, regexpReg, ImmWord(0), failure);
-++
-++    // Handle Atom matches
-++    Label notAtom, checkSuccess;
-++    masm.branchPtr(Assembler::Equal,
-++                   Address(regexpReg, RegExpShared::offsetOfPatternAtom()),
-++                   ImmWord(0), &notAtom);
-++    {
-++      LiveGeneralRegisterSet regsToSave(GeneralRegisterSet::Volatile());
-++      regsToSave.takeUnchecked(temp1);
-++      regsToSave.takeUnchecked(temp2);
-++      regsToSave.takeUnchecked(temp3);
-++
-++      masm.computeEffectiveAddress(matchPairsAddress, temp3);
-++
-++      masm.PushRegsInMask(regsToSave);
-++      masm.setupUnalignedABICall(temp2);
-++      masm.passABIArg(regexpReg);
-++      masm.passABIArg(input);
-++      masm.passABIArg(lastIndex);
-++      masm.passABIArg(temp3);
-++      masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ExecuteRegExpAtomRaw));
-++      masm.storeCallInt32Result(temp1);
-++      masm.PopRegsInMask(regsToSave);
-++
-++      masm.jump(&checkSuccess);
-++    }
-++    masm.bind(&notAtom);
-++
-++    // Don't handle regexps with too many capture pairs.
-++    masm.load32(Address(regexpReg, RegExpShared::offsetOfPairCount()), temp2);
-++    masm.branch32(Assembler::Above, temp2, Imm32(RegExpObject::MaxPairCount), failure);
-++
-++    // Fill in the pair count in the MatchPairs on the stack.
-++    masm.store32(temp2, pairCountAddress);
-++
-++    // Update lastIndex if necessary.
-++    StepBackToLeadSurrogate(masm, regexpReg, input, lastIndex, temp2, temp3);
-++
-++    // Load code pointer and length of input (in bytes).
-++    // Store the input start in the InputOutputData.
-++    Register codePointer = temp1; // Note: temp1 was previously regexpReg.
-++    Register byteLength = temp3;
-++    {
-++        Label isLatin1, done;
-++        masm.loadStringChars(input, temp2);
-++        masm.storePtr(temp2, inputStartAddress);
-++        masm.loadStringLength(input, byteLength);
-++
-++        masm.branchLatin1String(input, &isLatin1);
-++
-++        // Two-byte input
-++        masm.loadPtr(Address(regexpReg, RegExpShared::offsetOfJitCode(/*latin1 =*/false)),
-++                     codePointer);
-++        masm.lshiftPtr(Imm32(1), byteLength);
-++        masm.jump(&done);
-++
-++        // Latin1 input
-++        masm.bind(&isLatin1);
-++        masm.loadPtr(Address(regexpReg, RegExpShared::offsetOfJitCode(/*latin1 = */ true)),
-++                     codePointer);
-++
-++        masm.bind(&done);
-++
-++        // Store end pointer
-++        masm.addPtr(byteLength, temp2);
-++        masm.storePtr(temp2, inputEndAddress);
-++    }
-++
-++    // Guard that the RegExpShared has been compiled for this type of input.
-++    // If it has not been compiled, we fall back to the OOL case, which will
-++    // do a VM call into the interpreter.
-++    // TODO: add an interpreter trampoline?
-++    masm.branchPtr(Assembler::Equal, codePointer, ImmWord(0), failure);
-++    masm.loadPtr(Address(codePointer, JitCode::offsetOfCode()), codePointer);
-++
-++    // Finish filling in the InputOutputData instance on the stack
-++    masm.computeEffectiveAddress(matchPairsAddress, temp2);
-++    masm.storePtr(temp2, matchesAddress);
-++    masm.storePtr(lastIndex, startIndexAddress);
-++
-++    // Save any volatile inputs.
-++    LiveGeneralRegisterSet volatileRegs;
-++    if (lastIndex.volatile_()) {
-++        volatileRegs.add(lastIndex);
-++    }
-++    if (input.volatile_()) {
-++        volatileRegs.add(input);
-++    }
-++    if (regexp.volatile_()) {
-++        volatileRegs.add(regexp);
-++    }
-++
-++#ifdef JS_TRACE_LOGGING
-++    if (TraceLogTextIdEnabled(TraceLogger_IrregexpExecute)) {
-++        masm.loadTraceLogger(temp2);
-++        masm.tracelogStartId(temp2, TraceLogger_IrregexpExecute);
-++    }
-++#endif
-++
-++    // Execute the RegExp.
-++    masm.computeEffectiveAddress(Address(masm.getStackPointer(), inputOutputDataStartOffset),
-++                                 temp2);
-++    masm.PushRegsInMask(volatileRegs);
-++    masm.setupUnalignedABICall(temp3);
-++    masm.passABIArg(temp2);
-++    masm.callWithABI(codePointer);
-++    masm.storeCallInt32Result(temp1);
-++    masm.PopRegsInMask(volatileRegs);
-++
-++#ifdef JS_TRACE_LOGGING
-++    if (TraceLogTextIdEnabled(TraceLogger_IrregexpExecute)) {
-++        masm.loadTraceLogger(temp2);
-++        masm.tracelogStopId(temp2, TraceLogger_IrregexpExecute);
-++    }
-++#endif
-++
-++    Label success;
-++    masm.bind(&checkSuccess);
-++    masm.branch32(Assembler::Equal, temp1, Imm32(RegExpRunStatus_Success_NotFound), notFound);
-++    masm.branch32(Assembler::Equal, temp1, Imm32(RegExpRunStatus_Error), failure);
-++
-++    // Lazily update the RegExpStatics.
-++    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global());
-++    if (!res) {
-++        return false;
-++    }
-++    masm.movePtr(ImmPtr(res), temp1);
-++    UpdateRegExpStatics(masm,
-++                        regexp,
-++                        input,
-++                        lastIndex,
-++                        temp1,
-++                        temp2,
-++                        temp3,
-++                        stringsCanBeInNursery,
-++                        volatileRegs);
-+ 
-+     return true;
-+ }
-+ 
-+ static void
-+ CopyStringChars(MacroAssembler& masm, Register to, Register from, Register len,
-+                 Register byteOpScratch, size_t fromWidth, size_t toWidth);
-+ 
-+@@ -2179,41 +2270,50 @@ JitCompartment::generateRegExpTesterStub
-+     regs.take(input);
-+     regs.take(regexp);
-+     regs.take(lastIndex);
-+ 
-+     Register temp1 = regs.takeAny();
-+     Register temp2 = regs.takeAny();
-+     Register temp3 = regs.takeAny();
-+ 
-+-    masm.reserveStack(sizeof(irregexp::InputOutputData));
-++    masm.reserveStack(RegExpReservedStack);
-+ 
-+     Label notFound, oolEntry;
-+     if (!PrepareAndExecuteRegExp(cx, masm, regexp, input, lastIndex,
-+                                  temp1, temp2, temp3, 0,
-+-                                 RegExpShared::MatchOnly, &notFound, &oolEntry))
-++                                 &notFound, &oolEntry))
-+     {
-+         return nullptr;
-+     }
-+ 
-+     Label done;
-+ 
-+-    // temp3 contains endIndex.
-+-    masm.move32(temp3, result);
-++    // In visitRegExpMatcher and visitRegExpSearcher, we reserve stack space
-++    // before calling the stub. For RegExpTester we call the stub before reserving
-++    // stack space, so the offset of the InputOutputData is 0.
-++    size_t inputOutputDataStartOffset = 0;
-++
-++    size_t pairsVectorStartOffset = RegExpPairsVectorStartOffset(inputOutputDataStartOffset);
-++    Address matchPairLimit(masm.getStackPointer(),
-++                           pairsVectorStartOffset + offsetof(MatchPair, limit));
-++
-++    // RegExpTester returns the end index of the match to update lastIndex.
-++    masm.load32(matchPairLimit, result);
-+     masm.jump(&done);
-+ 
-+     masm.bind(&notFound);
-+     masm.move32(Imm32(RegExpTesterResultNotFound), result);
-+     masm.jump(&done);
-+ 
-+     masm.bind(&oolEntry);
-+     masm.move32(Imm32(RegExpTesterResultFailed), result);
-+ 
-+     masm.bind(&done);
-+-    masm.freeStack(sizeof(irregexp::InputOutputData));
-++    masm.freeStack(RegExpReservedStack);
-+     masm.ret();
-+ 
-+     Linker linker(masm);
-+     AutoFlushICache afc("RegExpTesterStub");
-+     JitCode* code = linker.newCode<CanGC>(cx, OTHER_CODE);
-+     if (!code)
-+         return nullptr;
-+ 
-diff --git a/js/src/jit/JitOptions.h.rej b/js/src/jit/JitOptions.h.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit/JitOptions.h.rej
-@@ -0,0 +1,20 @@
-+--- JitOptions.h
-++++ JitOptions.h
-+@@ -72,16 +72,17 @@ struct DefaultJitOptions
-+     bool fullDebugChecks;
-+     bool limitScriptSize;
-+     bool osr;
-+     bool asmJSAtomicsEnable;
-+     bool wasmFoldOffsets;
-+     bool ionInterruptWithoutSignals;
-+     bool simulatorAlwaysInterrupt;
-+     uint32_t baselineWarmUpThreshold;
-++    uint32_t regexpWarmUpThreshold;
-+     uint32_t exceptionBailoutThreshold;
-+     uint32_t frequentBailoutThreshold;
-+     uint32_t maxStackArgs;
-+     uint32_t osrPcMismatchesBeforeRecompile;
-+     uint32_t smallFunctionMaxBytecodeLength_;
-+     uint32_t jumpThreshold;
-+     uint32_t branchPruningHitCountFactor;
-+     uint32_t branchPruningInstFactor;
-diff --git a/js/src/jit/MCallOptimize.cpp.rej b/js/src/jit/MCallOptimize.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit/MCallOptimize.cpp.rej
-@@ -0,0 +1,21 @@
-+--- MCallOptimize.cpp
-++++ MCallOptimize.cpp
-+@@ -38,16 +39,18 @@
-+ #include "vm/NativeObject-inl.h"
-+ #include "vm/StringObject-inl.h"
-+ #include "vm/UnboxedObject-inl.h"
-+ 
-+ using mozilla::ArrayLength;
-+ using mozilla::AssertedCast;
-+ 
-+ using JS::DoubleNaNValue;
-++using JS::RegExpFlag;
-++using JS::RegExpFlags;
-+ using JS::TrackedOutcome;
-+ using JS::TrackedStrategy;
-+ using JS::TrackedTypeSite;
-+ 
-+ namespace js {
-+ namespace jit {
-+ 
-+ IonBuilder::InliningResult
-diff --git a/js/src/jit/MacroAssembler.h.rej b/js/src/jit/MacroAssembler.h.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit/MacroAssembler.h.rej
-@@ -0,0 +1,33 @@
-+--- MacroAssembler.h
-++++ MacroAssembler.h
-+@@ -2558,16 +2558,30 @@ class MacroAssembler : public MacroAssem
-+     // on the stack, such that the JitFrameLayout would be correctly aligned on
-+     // the JitStackAlignment.
-+     void alignJitStackBasedOnNArgs(Register nargs);
-+     void alignJitStackBasedOnNArgs(uint32_t nargs);
-+ 
-+     inline void assertStackAlignment(uint32_t alignment, int32_t offset = 0);
-+ };
-+ 
-++// StackMacroAssembler checks no GC will happen while it's on the stack.
-++class MOZ_RAII StackMacroAssembler : public MacroAssembler
-++{
-++    JS::AutoCheckCannotGC nogc;
-++
-++  public:
-++    StackMacroAssembler()
-++      : MacroAssembler()
-++    {}
-++    explicit StackMacroAssembler(JSContext* cx)
-++      : MacroAssembler(cx)
-++    {}
-++};
-++
-+ //{{{ check_macroassembler_style
-+ inline uint32_t
-+ MacroAssembler::framePushed() const
-+ {
-+     return framePushed_;
-+ }
-+ 
-+ inline void
-diff --git a/js/src/jsapi-tests/tests.h.rej b/js/src/jsapi-tests/tests.h.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/jsapi-tests/tests.h.rej
-@@ -0,0 +1,20 @@
-+--- tests.h
-++++ tests.h
-+@@ -13,16 +13,17 @@
-+ #include <errno.h>
-+ #include <stdio.h>
-+ #include <stdlib.h>
-+ #include <string.h>
-+ 
-+ #include "jsalloc.h"
-+ #include "jsgc.h"
-+ 
-++#include "js/RegExpFlags.h"
-+ #include "js/Vector.h"
-+ #include "vm/JSContext.h"
-+ 
-+ /* Note: Aborts on OOM. */
-+ class JSAPITestString {
-+     js::Vector<char, 0, js::SystemAllocPolicy> chars;
-+ 
-+   public:
-diff --git a/js/src/jsapi.cpp.rej b/js/src/jsapi.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/jsapi.cpp.rej
-@@ -0,0 +1,38 @@
-+--- jsapi.cpp
-++++ jsapi.cpp
-+@@ -38,17 +38,16 @@
-+ #include "jsweakmap.h"
-+ #include "jswrapper.h"
-+ 
-+ #include "builtin/AtomicsObject.h"
-+ #include "builtin/Eval.h"
-+ #include "builtin/JSON.h"
-+ #include "builtin/MapObject.h"
-+ #include "builtin/Promise.h"
-+-#include "builtin/RegExp.h"
-+ #include "builtin/Stream.h"
-+ #include "builtin/SymbolObject.h"
-+ #ifdef ENABLE_SIMD
-+ # include "builtin/SIMD.h"
-+ #endif
-+ #ifdef ENABLE_BINARYDATA
-+ # include "builtin/TypedObject.h"
-+ #endif
-+@@ -75,17 +74,16 @@
-+ #include "vm/ErrorObject.h"
-+ #include "vm/HelperThreads.h"
-+ #include "vm/Interpreter.h"
-+ #include "vm/JSAtom.h"
-+ #include "vm/JSContext.h"
-+ #include "vm/JSFunction.h"
-+ #include "vm/JSObject.h"
-+ #include "vm/JSScript.h"
-+-#include "vm/RegExpStatics.h"
-+ #include "vm/Runtime.h"
-+ #include "vm/SavedStacks.h"
-+ #include "vm/SelfHosting.h"
-+ #include "vm/Shape.h"
-+ #include "vm/String.h"
-+ #include "vm/StringBuffer.h"
-+ #include "vm/Symbol.h"
-+ #include "vm/WrapperObject.h"
-diff --git a/js/src/moz.build.rej b/js/src/moz.build.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/moz.build.rej
-@@ -0,0 +1,67 @@
-+--- moz.build
-++++ moz.build
-+@@ -139,16 +139,18 @@ EXPORTS.js += [
-+     '../public/LegacyIntTypes.h',
-+     '../public/MemoryMetrics.h',
-+     '../public/Principals.h',
-+     '../public/ProfilingFrameIterator.h',
-+     '../public/ProfilingStack.h',
-+     '../public/Proxy.h',
-+     '../public/Realm.h',
-+     '../public/RefCounted.h',
-++    '../public/RegExp.h',
-++    '../public/RegExpFlags.h',
-+     '../public/RequiredDefines.h',
-+     '../public/Result.h',
-+     '../public/RootingAPI.h',
-+     '../public/SliceBudget.h',
-+     '../public/Stream.h',
-+     '../public/StructuredClone.h',
-+     '../public/SweepingAPI.h',
-+     '../public/TraceKind.h',
-+@@ -163,16 +165,20 @@ EXPORTS.js += [
-+     '../public/UbiNodeShortestPaths.h',
-+     '../public/UniquePtr.h',
-+     '../public/Utility.h',
-+     '../public/Value.h',
-+     '../public/Vector.h',
-+     '../public/WeakMapPtr.h',
-+ ]
-+ 
-++SOURCES += [
-++    'util/Text.cpp',
-++]
-++
-+ UNIFIED_SOURCES += [
-+     'builtin/AtomicsObject.cpp',
-+     'builtin/DataViewObject.cpp',
-+     'builtin/Eval.cpp',
-+     'builtin/intl/Collator.cpp',
-+     'builtin/intl/CommonFunctions.cpp',
-+     'builtin/intl/DateTimeFormat.cpp',
-+     'builtin/intl/IntlObject.cpp',
-+@@ -192,24 +198,16 @@ UNIFIED_SOURCES += [
-+     'builtin/Stream.cpp',
-+     'builtin/SymbolObject.cpp',
-+     'builtin/TestingFunctions.cpp',
-+     'builtin/TypedObject.cpp',
-+     'builtin/WeakMapObject.cpp',
-+     'builtin/WeakSetObject.cpp',
-+     'ds/Bitmap.cpp',
-+     'ds/LifoAlloc.cpp',
-+-    'irregexp/NativeRegExpMacroAssembler.cpp',
-+-    'irregexp/RegExpAST.cpp',
-+-    'irregexp/RegExpCharacters.cpp',
-+-    'irregexp/RegExpEngine.cpp',
-+-    'irregexp/RegExpInterpreter.cpp',
-+-    'irregexp/RegExpMacroAssembler.cpp',
-+-    'irregexp/RegExpParser.cpp',
-+-    'irregexp/RegExpStack.cpp',
-+     'jsalloc.cpp',
-+     'jsapi.cpp',
-+     'jsarray.cpp',
-+     'jsbool.cpp',
-+     'jsdate.cpp',
-+     'jsexn.cpp',
-+     'jsfriendapi.cpp',
-+     'jsgc.cpp',
-diff --git a/js/src/shell/js.cpp.rej b/js/src/shell/js.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/shell/js.cpp.rej
-@@ -0,0 +1,24 @@
-+--- js.cpp
-++++ js.cpp
-+@@ -70,19 +70,21 @@
-+ #include "builtin/TestingFunctions.h"
-+ #include "frontend/Parser.h"
-+ #include "gc/GCInternals.h"
-+ #include "jit/arm/Simulator-arm.h"
-+ #include "jit/InlinableNatives.h"
-+ #include "jit/Ion.h"
-+ #include "jit/JitcodeMap.h"
-+ #include "jit/OptimizationTracking.h"
-++#include "jit/OptimizationTracking.h"
-+ #include "js/Debug.h"
-+ #include "js/GCVector.h"
-+ #include "js/Initialization.h"
-++#include "js/RegExp.h"  // JS::ObjectIsRegExp
-+ #include "js/StructuredClone.h"
-+ #include "js/SweepingAPI.h"
-+ #include "js/TrackedOptimizationInfo.h"
-+ #include "perf/jsperf.h"
-+ #include "shell/jsoptparse.h"
-+ #include "shell/jsshell.h"
-+ #include "shell/OSObject.h"
-+ #include "threading/ConditionVariable.h"
-diff --git a/js/src/util/Text.cpp.rej b/js/src/util/Text.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/util/Text.cpp.rej
-@@ -0,0 +1,40 @@
-+--- Text.cpp
-++++ Text.cpp
-+@@ -0,0 +1,37 @@
-++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-++ * vim: set ts=8 sts=2 et sw=2 tw=80:
-++ * This Source Code Form is subject to the terms of the Mozilla Public
-++ * License, v. 2.0. If a copy of the MPL was not distributed with this
-++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-++
-++#include "util/Text.h"
-++
-++#include "mozilla/Assertions.h"
-++#include "util/Unicode.h"
-++
-++using namespace JS;
-++using namespace js;
-++
-++size_t
-++js::unicode::CountCodePoints(const char16_t* begin, const char16_t* end)
-++{
-++    MOZ_ASSERT(begin <= end);
-++
-++    size_t count = 0;
-++
-++    const char16_t* ptr = begin;
-++    while (ptr < end) {
-++        count++;
-++
-++        if (!IsLeadSurrogate(*ptr++)) {
-++            continue;
-++        }
-++
-++        if (ptr < end && IsTrailSurrogate(*ptr)) {
-++            ptr++;
-++        }
-++    }
-++    MOZ_ASSERT(ptr == end, "should have consumed the full range");
-++
-++    return count;
-++}
-diff --git a/js/src/util/Text.h.rej b/js/src/util/Text.h.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/util/Text.h.rej
-@@ -0,0 +1,30 @@
-+--- Text.h
-++++ Text.h
-+@@ -0,0 +1,27 @@
-++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-++ * vim: set ts=8 sts=2 et sw=2 tw=80:
-++ * This Source Code Form is subject to the terms of the Mozilla Public
-++ * License, v. 2.0. If a copy of the MPL was not distributed with this
-++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-++
-++#ifndef util_Text_h
-++#define util_Text_h
-++
-++#include <stddef.h>
-++
-++namespace js {
-++
-++namespace unicode {
-++/**
-++ * Count the number of code points in [begin, end].
-++ *
-++ * Every sequence of 16-bit units is considered valid.  Lone surrogates are
-++ * treated as if they represented a code point of the same value.
-++ */
-++extern size_t
-++CountCodePoints(const char16_t* begin, const char16_t* end);
-++} // namespace unicode
-++
-++} // namespace js
-++
-++#endif // util_Text_h
-diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h
---- a/js/src/vm/GlobalObject.h
-+++ b/js/src/vm/GlobalObject.h
-@@ -773,16 +773,17 @@ class GlobalObject : public NativeObject
- 
-     // Infallibly test whether the given value is the eval function for this global.
-     bool valueIsEval(const Value& val);
- 
-     // Implemented in vm/Iteration.cpp.
-     static bool initIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
-     static bool initArrayIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
-     static bool initStringIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
-+    static bool initRegExpStringIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
- 
-     // Implemented in vm/GeneratorObject.cpp.
-     static bool initGenerators(JSContext* cx, Handle<GlobalObject*> global);
- 
-     static bool initAsyncFunction(JSContext* cx, Handle<GlobalObject*> global);
- 
-     static bool initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global);
- 
-diff --git a/js/src/vm/Iteration.cpp.rej b/js/src/vm/Iteration.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/vm/Iteration.cpp.rej
-@@ -0,0 +1,20 @@
-+--- Iteration.cpp
-++++ Iteration.cpp
-+@@ -15,16 +15,17 @@
-+ #include "mozilla/PodOperations.h"
-+ #include "mozilla/Unused.h"
-+ 
-+ #include "jsarray.h"
-+ #include "jsopcode.h"
-+ #include "jstypes.h"
-+ #include "jsutil.h"
-+ 
-++#include "builtin/SelfHostingDefines.h"
-+ #include "ds/Sort.h"
-+ #include "gc/FreeOp.h"
-+ #include "gc/Marking.h"
-+ #include "js/Proxy.h"
-+ #include "vm/GeneratorObject.h"
-+ #include "vm/GlobalObject.h"
-+ #include "vm/Interpreter.h"
-+ #include "vm/JSAtom.h"
-diff --git a/js/src/vm/JSContext.cpp.rej b/js/src/vm/JSContext.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/vm/JSContext.cpp.rej
-@@ -0,0 +1,20 @@
-+--- JSContext.cpp
-++++ JSContext.cpp
-+@@ -36,16 +36,17 @@
-+ #include "jsprf.h"
-+ #include "jspubtd.h"
-+ #include "jsstr.h"
-+ #include "jstypes.h"
-+ #include "jswin.h"
-+ 
-+ #include "gc/FreeOp.h"
-+ #include "gc/Marking.h"
-++#include "irregexp/RegExpAPI.h"
-+ #include "jit/Ion.h"
-+ #include "jit/PcScriptCache.h"
-+ #include "js/CharacterEncoding.h"
-+ #include "vm/ErrorReporting.h"
-+ #include "vm/HelperThreads.h"
-+ #include "vm/JSAtom.h"
-+ #include "vm/JSCompartment.h"
-+ #include "vm/JSFunction.h"
-diff --git a/js/src/vm/MatchPairs.h.rej b/js/src/vm/MatchPairs.h.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/vm/MatchPairs.h.rej
-@@ -0,0 +1,33 @@
-+--- MatchPairs.h
-++++ MatchPairs.h
-+@@ -74,29 +74,29 @@ class MatchPairs
-+     friend class RegExpStatics;
-+ 
-+     /* MatchPair buffer allocator: set pairs_ and pairCount_. */
-+     virtual bool allocOrExpandArray(size_t pairCount) = 0;
-+ 
-+     bool initArrayFrom(MatchPairs& copyFrom);
-+     void forgetArray() { pairs_ = nullptr; }
-+ 
-++  public:
-+     void checkAgainst(size_t inputLength) {
-+ #ifdef DEBUG
-+         for (size_t i = 0; i < pairCount_; i++) {
-+             const MatchPair& p = (*this)[i];
-+             MOZ_ASSERT(p.check());
-+             if (p.isUndefined())
-+                 continue;
-+             MOZ_ASSERT(size_t(p.limit) <= inputLength);
-+         }
-+ #endif
-+     }
-+ 
-+-  public:
-+     /* Querying functions in the style of RegExpStatics. */
-+     bool   empty() const           { return pairCount_ == 0; }
-+     size_t pairCount() const       { MOZ_ASSERT(pairCount_ > 0); return pairCount_; }
-+     size_t parenCount() const      { return pairCount_ - 1; }
-+ 
-+     static size_t offsetOfPairs() { return offsetof(MatchPairs, pairs_); }
-+     static size_t offsetOfPairCount() { return offsetof(MatchPairs, pairCount_); }
-+ 
-diff --git a/js/src/vm/RegExpObject.cpp.rej b/js/src/vm/RegExpObject.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/vm/RegExpObject.cpp.rej
-@@ -0,0 +1,584 @@
-+--- RegExpObject.cpp
-++++ RegExpObject.cpp
-+@@ -11,49 +11,59 @@
-+ 
-+ #include "jshashutil.h"
-+ #include "jsstr.h"
-+ #ifdef DEBUG
-+ #include "jsutil.h"
-+ #endif
-+ 
-+ #include "builtin/RegExp.h"
-++#include "builtin/SelfHostingDefines.h"
-+ #include "frontend/TokenStream.h"
-+-#ifdef DEBUG
-+-#include "irregexp/RegExpBytecode.h"
-+-#endif
-+-#include "irregexp/RegExpParser.h"
-++#include "irregexp/RegExpAPI.h"
-+ #include "vm/MatchPairs.h"
-+ #include "vm/RegExpStatics.h"
-+ #include "vm/StringBuffer.h"
-+ #include "vm/TraceLogging.h"
-+ #ifdef DEBUG
-+ #include "vm/Unicode.h"
-+ #endif
-+ #include "vm/Xdr.h"
-+ 
-+ #include "vm/JSObject-inl.h"
-+ #include "vm/NativeObject-inl.h"
-+ #include "vm/Shape-inl.h"
-+ 
-++#include "js/RegExp.h"
-++#include "js/RegExpFlags.h"
-++
-+ using namespace js;
-+ 
-+ using mozilla::ArrayLength;
-+ using mozilla::DebugOnly;
-+ using mozilla::Maybe;
-+ using mozilla::PodCopy;
-++using JS::RegExpFlag;
-++using JS::RegExpFlags;
-+ using js::frontend::TokenStream;
-+ 
-+ using JS::AutoCheckCannotGC;
-+ 
-+-JS_STATIC_ASSERT(IgnoreCaseFlag == JSREG_FOLD);
-+-JS_STATIC_ASSERT(GlobalFlag == JSREG_GLOB);
-+-JS_STATIC_ASSERT(MultilineFlag == JSREG_MULTILINE);
-+-JS_STATIC_ASSERT(StickyFlag == JSREG_STICKY);
-+-JS_STATIC_ASSERT(UnicodeFlag == JSREG_UNICODE);
-++static_assert(RegExpFlag::Global == REGEXP_GLOBAL_FLAG,
-++              "self-hosted JS and /g flag bits must agree");
-++static_assert(RegExpFlag::IgnoreCase == REGEXP_IGNORECASE_FLAG,
-++              "self-hosted JS and /i flag bits must agree");
-++static_assert(RegExpFlag::Multiline == REGEXP_MULTILINE_FLAG,
-++              "self-hosted JS and /m flag bits must agree");
-++static_assert(RegExpFlag::DotAll == REGEXP_DOTALL_FLAG,
-++              "self-hosted JS and /s flag bits must agree");
-++static_assert(RegExpFlag::Unicode == REGEXP_UNICODE_FLAG,
-++              "self-hosted JS and /u flag bits must agree");
-++static_assert(RegExpFlag::Sticky == REGEXP_STICKY_FLAG,
-++              "self-hosted JS and /y flag bits must agree");
-+ 
-+ RegExpObject*
-+ js::RegExpAlloc(JSContext* cx, NewObjectKind newKind, HandleObject proto /* = nullptr */)
-+ {
-+     Rooted<RegExpObject*> regexp(cx, NewObjectWithClassProto<RegExpObject>(cx, proto, newKind));
-+     if (!regexp)
-+         return nullptr;
-+ 
-+@@ -963,257 +583,331 @@ js::StringHasRegExpMetaChars(JSLinearStr
-+     if (str->hasLatin1Chars())
-+         return HasRegExpMetaChars(str->latin1Chars(nogc), str->length());
-+ 
-+     return HasRegExpMetaChars(str->twoByteChars(nogc), str->length());
-+ }
-+ 
-+ /* RegExpShared */
-+ 
-+-RegExpShared::RegExpShared(JSAtom* source, RegExpFlag flags)
-+-  : source(source), flags(flags), canStringMatch(false), parenCount(0)
-++RegExpShared::RegExpShared(JSAtom* source, RegExpFlags flags)
-++  : source(source)
-++  , flags(flags)
-++  , pairCount_(0)
-+ {}
-+ 
-+ void
-+ RegExpShared::traceChildren(JSTracer* trc)
-+ {
-+     // Discard code to avoid holding onto ExecutablePools.
-+     if (IsMarkingTrace(trc) && trc->runtime()->gc.isShrinkingGC())
-+         discardJitCode();
-+ 
-+     TraceNullableEdge(trc, &source, "RegExpShared source");
-+-    for (auto& comp : compilationArray)
-+-        TraceNullableEdge(trc, &comp.jitCode, "RegExpShared code");
-++    if (kind() == RegExpShared::Kind::Atom) {
-++        TraceNullableEdge(trc, &patternAtom_, "RegExpShared pattern atom");
-++    } else {
-++        for (auto& comp : compilationArray) {
-++            TraceNullableEdge(trc, &comp.jitCode, "RegExpShared code");
-++        }
-++        TraceNullableEdge(trc, &groupsTemplate_, "RegExpShared groups template");
-++    }
-+ }
-+ 
-+ void
-+ RegExpShared::discardJitCode()
-+ {
-+     for (auto& comp : compilationArray)
-+         comp.jitCode = nullptr;
-+ 
-+     // We can also purge the tables used by JIT code.
-+     tables.clearAndFree();
-+ }
-+ 
-++
-+ void
-+ RegExpShared::finalize(FreeOp* fop)
-+ {
-+-    for (auto& comp : compilationArray)
-+-        js_free(comp.byteCode);
-++    for (auto& comp : compilationArray) {
-++        if (comp.byteCode) {
-++            js_free(comp.byteCode);
-++        }
-++    }
-++    if (namedCaptureIndices_) {
-++        js_free(namedCaptureIndices_);
-++    }
-+     tables.~JitCodeTables();
-+ }
-+ 
-+-/* static */ bool
-+-RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleLinearString input,
-+-                      CompilationMode mode, ForceByteCodeEnum force)
-++/* static */
-++bool
-++RegExpShared::compileIfNecessary(JSContext* cx,
-++                                 MutableHandleRegExpShared re,
-++                                 HandleLinearString input,
-++                                 RegExpShared::CodeKind codeKind)
-+ {
-+-    TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
-+-    AutoTraceLog logCompile(logger, TraceLogger_IrregexpCompile);
-++  if (codeKind == RegExpShared::CodeKind::Any) {
-++    // We start by interpreting regexps, then compile them once they are
-++    // sufficiently hot. For very long input strings, we tier up eagerly.
-++    codeKind = RegExpShared::CodeKind::Bytecode;
-++    if (re->markedForTierUp(cx) || input->length() > 1000) {
-++      codeKind = RegExpShared::CodeKind::Jitcode;
-++    }
-++  }
-++
-++  // Fall back to bytecode if native codegen is not available.
-++  if (!IsNativeRegExpEnabled(cx) && codeKind == RegExpShared::CodeKind::Jitcode) {
-++    codeKind = RegExpShared::CodeKind::Bytecode;
-++  }
-+ 
-+-    RootedAtom pattern(cx, re->source);
-+-    return compile(cx, re, pattern, input, mode, force);
-++  bool needsCompile = false;
-++  if (re->kind() == RegExpShared::Kind::Unparsed) {
-++    needsCompile = true;
-++  }
-++
-++  if (re->kind() == RegExpShared::Kind::RegExp) {
-++    if (!re->isCompiled(input->hasLatin1Chars(), codeKind)) {
-++      needsCompile = true;
-++    }
-++  }
-++
-++  if (needsCompile) {
-++    return irregexp::CompilePattern(cx, re, input, codeKind);
-++  }
-++  return true;
-+ }
-+ 
-+-/* static */ bool
-+-RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pattern,
-+-                      HandleLinearString input, CompilationMode mode, ForceByteCodeEnum force)
-++/* static */
-++RegExpRunStatus
-++RegExpShared::execute(JSContext* cx,
-++                      MutableHandleRegExpShared re,
-++                      HandleLinearString input,
-++                      size_t start,
-++                      MatchPairs* matches)
-+ {
-+-    if (!re->ignoreCase() && !StringHasRegExpMetaChars(pattern))
-+-        re->canStringMatch = true;
-+-
-+-    CompileOptions options(cx);
-+-    frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
-++    MOZ_ASSERT(matches);
-+ 
-+-    LifoAllocScope scope(&cx->tempLifoAlloc());
-++    // TODO: Add tracelogger support
-+ 
-+-    /* Parse the pattern. */
-+-    irregexp::RegExpCompileData data;
-+-    if (!irregexp::ParsePattern(dummyTokenStream, cx->tempLifoAlloc(), pattern,
-+-                                re->multiline(), mode == MatchOnly, re->unicode(),
-+-                                re->ignoreCase(), re->global(), re->sticky(), &data))
-+-    {
-+-        return false;
-++    /* Compile the code at point-of-use. */
-++    if (!compileIfNecessary(cx, re, input, RegExpShared::CodeKind::Any)) {
-++        return RegExpRunStatus_Error;
-+     }
-+ 
-+-    re->parenCount = data.capture_count;
-+-
-+-    JitCodeTables tables;
-+-    irregexp::RegExpCode code = irregexp::CompilePattern(cx, re, &data, input,
-+-                                                         false /* global() */,
-+-                                                         re->ignoreCase(),
-+-                                                         input->hasLatin1Chars(),
-+-                                                         mode == MatchOnly,
-+-                                                         force == ForceByteCode,
-+-                                                         re->sticky(),
-+-                                                         re->unicode(),
-+-                                                         tables);
-+-    if (code.empty())
-+-        return false;
-+-
-+-    MOZ_ASSERT(!code.jitCode || !code.byteCode);
-+-    MOZ_ASSERT_IF(force == ForceByteCode, code.byteCode);
-+-
-+-    RegExpCompilation& compilation = re->compilation(mode, input->hasLatin1Chars());
-+-    if (code.jitCode) {
-+-        // First copy the tables. GC can purge the tables if the RegExpShared
-+-        // has no JIT code, so it's important to do this right before setting
-+-        // compilation.jitCode (to ensure no purging happens between adding the
-+-        // tables and setting the JIT code).
-+-        for (size_t i = 0; i < tables.length(); i++) {
-+-            if (!re->addTable(std::move(tables[i]))) {
-+-                ReportOutOfMemory(cx);
-+-                return false;
-+-            }
-+-        }
-+-        compilation.jitCode = code.jitCode;
-+-    } else if (code.byteCode) {
-+-        MOZ_ASSERT(tables.empty(), "RegExpInterpreter does not use data tables");
-+-        compilation.byteCode = code.byteCode;
-++    /*
-++     * Ensure sufficient memory for output vector.
-++     * No need to initialize it. The RegExp engine fills them in on a match.
-++     */
-++    if (!matches->allocOrExpandArray(re->pairCount())) {
-++        ReportOutOfMemory(cx);
-++        return RegExpRunStatus_Error;
-+     }
-+ 
-+-    return true;
-+-}
-+-
-+-/* static */ bool
-+-RegExpShared::compileIfNecessary(JSContext* cx, MutableHandleRegExpShared re,
-+-                                 HandleLinearString input, CompilationMode mode,
-+-                                 ForceByteCodeEnum force)
-+-{
-+-    if (re->isCompiled(mode, input->hasLatin1Chars(), force))
-+-        return true;
-+-    return compile(cx, re, input, mode, force);
-+-}
-+-
-+-/* static */ RegExpRunStatus
-+-RegExpShared::execute(JSContext* cx, MutableHandleRegExpShared re, HandleLinearString input,
-+-                      size_t start, MatchPairs* matches, size_t* endIndex)
-+-{
-+-    MOZ_ASSERT_IF(matches, !endIndex);
-+-    MOZ_ASSERT_IF(!matches, endIndex);
-+-    TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
-+-
-+-    CompilationMode mode = matches ? Normal : MatchOnly;
-+-
-+-    /* Compile the code at point-of-use. */
-+-    if (!compileIfNecessary(cx, re, input, mode, DontForceByteCode))
-+-        return RegExpRunStatus_Error;
-++    if (re->kind() == RegExpShared::Kind::Atom) {
-++        return RegExpShared::executeAtom(re, input, start, matches);
-++    }
-+ 
-+     /*
-+      * Ensure sufficient memory for output vector.
-+      * No need to initialize it. The RegExp engine fills them in on a match.
-+      */
-+-    if (matches && !matches->allocOrExpandArray(re->pairCount())) {
-++    if (!matches->allocOrExpandArray(re->pairCount())) {
-+         ReportOutOfMemory(cx);
-+         return RegExpRunStatus_Error;
-+     }
-+ 
-+-    size_t length = input->length();
-+-
-+-    // Reset the Irregexp backtrack stack if it grows during execution.
-+-    irregexp::RegExpStackScope stackScope(cx);
-++    uint32_t interruptRetries = 0;
-++    const uint32_t maxInterruptRetries = 4;
-++    do {
-++        RegExpRunStatus result = irregexp::Execute(cx, re, input, start, matches);
-+ 
-+-    if (re->canStringMatch) {
-+-        MOZ_ASSERT(re->pairCount() == 1);
-+-        size_t sourceLength = re->source->length();
-+-        if (re->sticky()) {
-+-            // First part checks size_t overflow.
-+-            if (sourceLength + start < sourceLength || sourceLength + start > length)
-+-                return RegExpRunStatus_Success_NotFound;
-+-            if (!HasSubstringAt(input, re->source, start))
-+-                return RegExpRunStatus_Success_NotFound;
-+-
-+-            if (matches) {
-+-                (*matches)[0].start = start;
-+-                (*matches)[0].limit = start + sourceLength;
-+-
-+-                matches->checkAgainst(length);
-+-            } else if (endIndex) {
-+-                *endIndex = start + sourceLength;
-++        if (result == RegExpRunStatus_Error) {
-++          /* Execute can return RegExpRunStatus_Error:
-++           *
-++           *  1. If the native stack overflowed
-++           *  2. If the backtrack stack overflowed
-++           *  3. If an interrupt was requested during execution.
-++           *
-++           * In the first two cases, we want to throw an error. In the
-++           * third case, we want to handle the interrupt and try again.
-++           * We cap the number of times we will retry.
-++           */
-++          if (cx->hasPendingInterrupt()) {
-++            if (!CheckForInterrupt(cx)) {
-++              return RegExpRunStatus_Error;
-+             }
-+-            return RegExpRunStatus_Success;
-++            if (interruptRetries++ < maxInterruptRetries) {
-++              // The initial execution may have been interpreted, or the
-++              // interrupt may have triggered a GC that discarded jitcode.
-++              // To maximize the chance of succeeding before being
-++              // interrupted again, we want to ensure we are compiled.
-++              if (!compileIfNecessary(cx, re, input,
-++                                      RegExpShared::CodeKind::Jitcode)) {
-++                return RegExpRunStatus_Error;
-++              }
-++              continue;
-++            }
-++          }
-++          // If we have run out of retries, this regexp takes too long to
-++          // execute.
-++          ReportOverRecursed(cx);
-++          return RegExpRunStatus_Error;
-+         }
-+ 
-+-        int res = StringFindPattern(input, re->source, start);
-+-        if (res == -1)
-+-            return RegExpRunStatus_Success_NotFound;
-++        MOZ_ASSERT(result == RegExpRunStatus_Success ||
-++                   result == RegExpRunStatus_Success_NotFound);
-++
-++        return result;
-++    } while (true);
-++
-++    MOZ_CRASH("Unreachable");
-++}
-++
-++void RegExpShared::useAtomMatch(HandleAtom pattern) {
-++  MOZ_ASSERT(kind() == RegExpShared::Kind::Unparsed);
-++  kind_ = RegExpShared::Kind::Atom;
-++  patternAtom_ = pattern;
-++  pairCount_ = 1;
-++}
-++
-++void RegExpShared::useRegExpMatch(size_t pairCount) {
-++  MOZ_ASSERT(kind() == RegExpShared::Kind::Unparsed);
-++  kind_ = RegExpShared::Kind::RegExp;
-++  pairCount_ = pairCount;
-++  ticks_ = jit::JitOptions.regexpWarmUpThreshold;
-++}
-++
-++/* static */
-++bool
-++RegExpShared::initializeNamedCaptures(JSContext* cx,
-++                                      HandleRegExpShared re,
-++                                      HandleNativeObject namedCaptures)
-++{
-++    MOZ_ASSERT(!re->groupsTemplate_);
-++    MOZ_ASSERT(!re->namedCaptureIndices_);
-++
-++    // The irregexp parser returns named capture information in the form
-++    // of an ArrayObject, where even elements store the capture name and
-++    // odd elements store the corresponding capture index. We create a
-++    // template object with a property for each capture name, and store
-++    // the capture indices as a heap-allocated array.
-++    MOZ_ASSERT(namedCaptures->getDenseInitializedLength() % 2 == 0);
-++    uint32_t numNamedCaptures = namedCaptures->getDenseInitializedLength() / 2;
-++
-++    // Create a plain template object.
-++    RootedPlainObject templateObject(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr, TenuredObject));
-++    if (!templateObject) {
-++        return false;
-++    }
-++
-++    // Create a new group for the template.
-++    Rooted<TaggedProto> proto(cx, templateObject->taggedProto());
-++    ObjectGroup* group =
-++      ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto);
-++    if (!group) {
-++        return false;
-++    }
-++    templateObject->setGroup(group);
-+ 
-+-        if (matches) {
-+-            (*matches)[0].start = res;
-+-            (*matches)[0].limit = res + sourceLength;
-++    // Initialize the properties of the template.
-++    RootedId id(cx);
-++    RootedValue dummyString(cx, StringValue(cx->runtime()->emptyString));
-++    for (uint32_t i = 0; i < numNamedCaptures; i++) {
-++        JSString* name = namedCaptures->getDenseElement(i * 2).toString();
-++        id = NameToId(name->asAtom().asPropertyName());
-++        if (!NativeDefineDataProperty(cx, templateObject, id, dummyString,
-++                                      JSPROP_ENUMERATE)) {
-++          return false;
-++        }
-++        AddTypePropertyId(cx, templateObject, id, UndefinedValue());
-++    }
-++
-++    // Allocate the capture index array.
-++    uint32_t arraySize = numNamedCaptures * sizeof(uint32_t);
-++    uint32_t* captureIndices = static_cast<uint32_t*>(js_malloc(arraySize));
-++    if (!captureIndices) {
-++        ReportOutOfMemory(cx);
-++        return false;
-++    }
-++
-++    // Populate the capture index array
-++    for (uint32_t i = 0; i < numNamedCaptures; i++) {
-++        captureIndices[i] = namedCaptures->getDenseElement(i * 2 + 1).toInt32();
-++    }
-++
-++    re->numNamedCaptures_ = numNamedCaptures;
-++    re->groupsTemplate_ = templateObject;
-++    re->namedCaptureIndices_ = captureIndices;
-++    // js::AddCellMemory(re, arraySize, MemoryUse::RegExpSharedNamedCaptureData);
-++    return true;
-++}
-+ 
-+-            matches->checkAgainst(length);
-+-        } else if (endIndex) {
-+-            *endIndex = res + sourceLength;
-++void RegExpShared::tierUpTick() {
-++  MOZ_ASSERT(kind() == RegExpShared::Kind::RegExp);
-++  if (ticks_ > 0) {
-++    ticks_--;
-++  }
-++}
-++
-++bool RegExpShared::markedForTierUp(JSContext* cx) const {
-++  if (!IsNativeRegExpEnabled(cx)) {
-++    return false;
-++  }
-++  if (kind() != RegExpShared::Kind::RegExp) {
-++    return false;
-++  }
-++  return ticks_ == 0;
-++}
-++
-++/* static */
-++RegExpRunStatus ExecuteAtomImpl(RegExpShared* re, JSLinearString* input,
-++                                size_t start, MatchPairs* matches)
-++{
-++    MOZ_ASSERT(re->pairCount() == 1);
-++    size_t length = input->length();
-++    size_t searchLength = re->patternAtom()->length();
-++
-++    if (re->sticky()) {
-++        // First part checks size_t overflow.
-++        if (searchLength + start < searchLength || searchLength + start > length) {
-++            return RegExpRunStatus_Success_NotFound;
-+         }
-++        if (!HasSubstringAt(input, re->patternAtom(), start)) {
-++            return RegExpRunStatus_Success_NotFound;
-++        }
-++
-++        (*matches)[0].start = start;
-++        (*matches)[0].limit = start + searchLength;
-++        matches->checkAgainst(input->length());
-+         return RegExpRunStatus_Success;
-+     }
-+ 
-+-    do {
-+-        jit::JitCode* code = re->compilation(mode, input->hasLatin1Chars()).jitCode;
-+-        if (!code)
-+-            break;
-+-
-+-        RegExpRunStatus result;
-+-        {
-+-            AutoTraceLog logJIT(logger, TraceLogger_IrregexpExecute);
-+-            AutoCheckCannotGC nogc;
-+-            if (input->hasLatin1Chars()) {
-+-                const Latin1Char* chars = input->latin1Chars(nogc);
-+-                result = irregexp::ExecuteCode(cx, code, chars, start, length, matches, endIndex);
-+-            } else {
-+-                const char16_t* chars = input->twoByteChars(nogc);
-+-                result = irregexp::ExecuteCode(cx, code, chars, start, length, matches, endIndex);
-+-            }
-+-        }
-+-
-+-        if (result == RegExpRunStatus_Error) {
-+-            // An 'Error' result is returned if a stack overflow guard or
-+-            // interrupt guard failed. If CheckOverRecursed doesn't throw, break
-+-            // out and retry the regexp in the bytecode interpreter, which can
-+-            // execute while tolerating future interrupts. Otherwise, if we keep
-+-            // getting interrupted we will never finish executing the regexp.
-+-            if (!jit::CheckOverRecursed(cx))
-+-                return RegExpRunStatus_Error;
-+-            break;
-+-        }
-+-
-+-        if (result == RegExpRunStatus_Success_NotFound)
-+-            return RegExpRunStatus_Success_NotFound;
-+-
-+-        MOZ_ASSERT(result == RegExpRunStatus_Success);
-+-
-+-        if (matches)
-+-            matches->checkAgainst(length);
-+-        return RegExpRunStatus_Success;
-+-    } while (false);
-+-
-+-    // Compile bytecode for the RegExp if necessary.
-+-    if (!compileIfNecessary(cx, re, input, mode, ForceByteCode))
-+-        return RegExpRunStatus_Error;
-+-
-+-    uint8_t* byteCode = re->compilation(mode, input->hasLatin1Chars()).byteCode;
-+-    AutoTraceLog logInterpreter(logger, TraceLogger_IrregexpExecute);
-+-
-+-    AutoStableStringChars inputChars(cx);
-+-    if (!inputChars.init(cx, input))
-+-        return RegExpRunStatus_Error;
-+-
-+-    RegExpRunStatus result;
-+-    if (inputChars.isLatin1()) {
-+-        const Latin1Char* chars = inputChars.latin1Range().begin().get();
-+-        result = irregexp::InterpretCode(cx, byteCode, chars, start, length, matches, endIndex);
-+-    } else {
-+-        const char16_t* chars = inputChars.twoByteRange().begin().get();
-+-        result = irregexp::InterpretCode(cx, byteCode, chars, start, length, matches, endIndex);
-++    int res = StringFindPattern(input, re->patternAtom(), start);
-++    if (res == -1) {
-++        return RegExpRunStatus_Success_NotFound;
-+     }
-+ 
-+-    if (result == RegExpRunStatus_Success && matches)
-+-        matches->checkAgainst(length);
-+-    return result;
-++    (*matches)[0].start = res;
-++    (*matches)[0].limit = res + searchLength;
-++    matches->checkAgainst(input->length());
-++    return RegExpRunStatus_Success;
-++}
-++
-++RegExpRunStatus js::ExecuteRegExpAtomRaw(RegExpShared* re,
-++                                         JSLinearString* input, size_t start,
-++                                         MatchPairs* matchPairs) {
-++  JS::AutoCheckCannotGC nogc;
-++  return ExecuteAtomImpl(re, input, start, matchPairs);
-++}
-++
-++/* static */
-++RegExpRunStatus RegExpShared::executeAtom(MutableHandleRegExpShared re,
-++                                          HandleLinearString input,
-++                                          size_t start, MatchPairs* matches) {
-++  return ExecuteAtomImpl(re, input, start, matches);
-+ }
-+ 
-+ size_t
-+ RegExpShared::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
-+ {
-+     size_t n = 0;
-+ 
-+     for (size_t i = 0; i < ArrayLength(compilationArray); i++) {
-diff --git a/js/src/vm/RegExpShared.h.rej b/js/src/vm/RegExpShared.h.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/vm/RegExpShared.h.rej
-@@ -0,0 +1,396 @@
-+--- RegExpShared.h
-++++ RegExpShared.h
-+@@ -16,58 +16,50 @@
-+ #include "mozilla/MemoryReporting.h"
-+ 
-+ #include "jsalloc.h"
-+ 
-+ #include "builtin/SelfHostingDefines.h"
-+ #include "gc/Barrier.h"
-+ #include "gc/Heap.h"
-+ #include "gc/Marking.h"
-++#include "jit/JitOptions.h"
-++#include "js/RegExpFlags.h"
-+ #include "js/UbiNode.h"
-+ #include "js/Vector.h"
-++#include "irregexp/RegExpTypes.h"
-+ #include "vm/ArrayObject.h"
-+ #include "vm/JSAtom.h"
-++#include "vm/JSContext.h"
-+ 
-+ namespace js {
-+ 
-+ class ArrayObject;
-+ class MatchPairs;
-+ class RegExpCompartment;
-+ class RegExpShared;
-+ class RegExpStatics;
-+ 
-+ using RootedRegExpShared = JS::Rooted<RegExpShared*>;
-+ using HandleRegExpShared = JS::Handle<RegExpShared*>;
-+ using MutableHandleRegExpShared = JS::MutableHandle<RegExpShared*>;
-+ 
-+-enum RegExpFlag : uint8_t
-++enum RegExpRunStatus : int32_t
-+ {
-+-    IgnoreCaseFlag  = 0x01,
-+-    GlobalFlag      = 0x02,
-+-    MultilineFlag   = 0x04,
-+-    StickyFlag      = 0x08,
-+-    UnicodeFlag     = 0x10,
-+-
-+-    NoFlags         = 0x00,
-+-    AllFlags        = 0x1f
-++    RegExpRunStatus_Error = -1,
-++    RegExpRunStatus_Success = 1,
-++    RegExpRunStatus_Success_NotFound = 0,
-+ };
-+-
-+-static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG &&
-+-              GlobalFlag == REGEXP_GLOBAL_FLAG &&
-+-              MultilineFlag == REGEXP_MULTILINE_FLAG &&
-+-              StickyFlag == REGEXP_STICKY_FLAG &&
-+-              UnicodeFlag == REGEXP_UNICODE_FLAG,
-+-              "Flag values should be in sync with self-hosted JS");
-+-
-+-enum RegExpRunStatus
-+-{
-+-    RegExpRunStatus_Error,
-+-    RegExpRunStatus_Success,
-+-    RegExpRunStatus_Success_NotFound
-+-};
-++inline bool IsNativeRegExpEnabled(JSContext* cx) {
-++#ifdef JS_CODEGEN_NONE
-++  return false;
-++#else
-++  return cx->options().nativeRegExp();
-++#endif
-++}
-+ 
-+ /*
-+  * A RegExpShared is the compiled representation of a regexp. A RegExpShared is
-+  * potentially pointed to by multiple RegExpObjects. Additionally, C++ code may
-+  * have pointers to RegExpShareds on the stack. The RegExpShareds are kept in a
-+  * table so that they can be reused when compiling the same regex string.
-+  *
-+  * To save memory, a RegExpShared is not created for a RegExpObject until it is
-+@@ -79,183 +71,243 @@ enum RegExpRunStatus
-+  * than explicitly tracing them, so that the RegExpShared and any jitcode can
-+  * be reclaimed quicker. However, the RegExpShareds are traced through by
-+  * objects when we are preserving jitcode in their zone, to avoid the same
-+  * recompilation inefficiencies as normal Ion and baseline compilation.
-+  */
-+ class RegExpShared : public gc::TenuredCell
-+ {
-+   public:
-+-    enum CompilationMode {
-+-        Normal,
-+-        MatchOnly
-++    enum class Kind
-++    {
-++        Unparsed,
-++        Atom,
-++        RegExp
-+     };
-+ 
-+-    enum ForceByteCodeEnum {
-+-        DontForceByteCode,
-+-        ForceByteCode
-++    enum class CodeKind
-++    {
-++        Bytecode,
-++        Jitcode,
-++        Any
-+     };
-+ 
-+-    using JitCodeTable = UniquePtr<uint8_t[], JS::FreePolicy>;
-++    using ByteCode = js::irregexp::ByteArrayData;
-++    using JitCodeTable = js::irregexp::ByteArray;
-+     using JitCodeTables = Vector<JitCodeTable, 0, SystemAllocPolicy>;
-+ 
-+   private:
-+     friend class RegExpStatics;
-+     friend class RegExpZone;
-+ 
-+     struct RegExpCompilation
-+     {
-+         ReadBarriered<jit::JitCode*> jitCode;
-+-        uint8_t* byteCode;
-++        ByteCode* byteCode;
-+ 
-+         RegExpCompilation() : byteCode(nullptr) {}
-+ 
-+-        bool compiled(ForceByteCodeEnum force = DontForceByteCode) const {
-+-            return byteCode || (force == DontForceByteCode && jitCode);
-++        bool compiled(CodeKind kind = CodeKind::Any) const
-++        {
-++            switch (kind) {
-++                case CodeKind::Bytecode:
-++                    return !!byteCode;
-++                case CodeKind::Jitcode:
-++                    return !!jitCode;
-++                case CodeKind::Any:
-++                    return !!byteCode || !!jitCode;
-++            }
-++            MOZ_CRASH("Unreachable");
-+         }
-+     };
-+ 
-+     /* Source to the RegExp, for lazy compilation. */
-+     GCPtr<JSAtom*>     source;
-+ 
-+-    RegExpFlag         flags;
-+-    bool               canStringMatch;
-+-    size_t             parenCount;
-++    JS::RegExpFlags    flags;
-+ 
-+-    RegExpCompilation  compilationArray[4];
-++    RegExpShared::Kind kind_ = Kind::Unparsed;
-++    GCPtrAtom patternAtom_;
-++    uint32_t maxRegisters_ = 0;
-++    uint32_t ticks_ = 0;
-+ 
-+-    static int CompilationIndex(CompilationMode mode, bool latin1) {
-+-        switch (mode) {
-+-          case Normal:    return latin1 ? 0 : 1;
-+-          case MatchOnly: return latin1 ? 2 : 3;
-+-        }
-+-        MOZ_CRASH();
-+-    }
-++    uint32_t numNamedCaptures_ = {};
-++    uint32_t* namedCaptureIndices_ = {};
-++    GCPtr<PlainObject*> groupsTemplate_ = {};
-++
-++    size_t             pairCount_;
-++
-++    // Make x86 build happy.
-++    size_t             dummy_;
-++
-++    RegExpCompilation  compilationArray[2];
-++
-++    static int CompilationIndex(bool latin1) { return latin1 ? 0 : 1; }
-+ 
-+     // Tables referenced by JIT code.
-+     JitCodeTables tables;
-+ 
-+     /* Internal functions. */
-+-    RegExpShared(JSAtom* source, RegExpFlag flags);
-+-
-+-    static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleLinearString input,
-+-                        CompilationMode mode, ForceByteCodeEnum force);
-+-    static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleAtom pattern,
-+-                        HandleLinearString input, CompilationMode mode, ForceByteCodeEnum force);
-++    RegExpShared(JSAtom* source, JS::RegExpFlags flags);
-+ 
-+-    static bool compileIfNecessary(JSContext* cx, MutableHandleRegExpShared res,
-+-                                   HandleLinearString input, CompilationMode mode,
-+-                                   ForceByteCodeEnum force);
-++    static bool compileIfNecessary(JSContext* cx,
-++                                   MutableHandleRegExpShared res,
-++                                   HandleLinearString input,
-++                                   CodeKind code);
-+ 
-+-    const RegExpCompilation& compilation(CompilationMode mode, bool latin1) const {
-+-        return compilationArray[CompilationIndex(mode, latin1)];
-++    const RegExpCompilation& compilation(bool latin1) const {
-++        return compilationArray[CompilationIndex(latin1)];
-+     }
-+ 
-+-    RegExpCompilation& compilation(CompilationMode mode, bool latin1) {
-+-        return compilationArray[CompilationIndex(mode, latin1)];
-++    RegExpCompilation& compilation(bool latin1) {
-++        return compilationArray[CompilationIndex(latin1)];
-+     }
-+ 
-+   public:
-+     ~RegExpShared() = delete;
-+ 
-+-    // Execute this RegExp on input starting from searchIndex, filling in
-+-    // matches if specified and otherwise only determining if there is a match.
-++    static RegExpRunStatus executeAtom(MutableHandleRegExpShared re,
-++                                       HandleLinearString input,
-++                                       size_t start,
-++                                       MatchPairs* matches);
-++
-++    // Execute this RegExp on input starting from searchIndex, filling in matches.
-+     static RegExpRunStatus execute(JSContext* cx, MutableHandleRegExpShared res,
-+                                    HandleLinearString input, size_t searchIndex,
-+-                                   MatchPairs* matches, size_t* endIndex);
-++                                   MatchPairs* matches);
-+ 
-+     // Register a table with this RegExpShared, and take ownership.
-+     bool addTable(JitCodeTable table) {
-+         return tables.append(Move(table));
-+     }
-+ 
-+     /* Accessors */
-+ 
-+-    size_t getParenCount() const {
-+-        MOZ_ASSERT(isCompiled());
-+-        return parenCount;
-++    size_t pairCount() const {
-++        MOZ_ASSERT(kind() != Kind::Unparsed);
-++        return pairCount_;
-+     }
-+ 
-+-    /* Accounts for the "0" (whole match) pair. */
-+-    size_t pairCount() const            { return getParenCount() + 1; }
-++    RegExpShared::Kind kind() const { return kind_; }
-++
-++    // Use simple string matching for this regexp.
-++    void useAtomMatch(HandleAtom pattern);
-++
-++    // Use the regular expression engine for this regexp.
-++    void useRegExpMatch(size_t parenCount);
-++
-++    static bool initializeNamedCaptures(JSContext* cx,
-++                                        HandleRegExpShared re,
-++                                        HandleNativeObject namedCaptures);
-++    PlainObject* getGroupsTemplate() { return groupsTemplate_; }
-++
-++    void tierUpTick();
-++    bool markedForTierUp(JSContext* cx) const;
-++
-++    void setByteCode(ByteCode* code, bool latin1) { compilation(latin1).byteCode = code; }
-++    ByteCode* getByteCode(bool latin1) const { return compilation(latin1).byteCode; }
-++    void setJitCode(jit::JitCode* code, bool latin1) { compilation(latin1).jitCode = code; }
-++    jit::JitCode* getJitCode(bool latin1) const { return compilation(latin1).jitCode; }
-++    uint32_t getMaxRegisters() const { return maxRegisters_; }
-++    void updateMaxRegisters(uint32_t numRegisters)
-++    {
-++        maxRegisters_ = std::max(maxRegisters_, numRegisters);
-++    }
-++
-++    uint32_t numNamedCaptures() const { return numNamedCaptures_; }
-++    int32_t getNamedCaptureIndex(uint32_t idx) const
-++    {
-++        MOZ_ASSERT(idx < numNamedCaptures());
-++        MOZ_ASSERT(namedCaptureIndices_);
-++        return namedCaptureIndices_[idx];
-++    }
-+ 
-+     JSAtom* getSource() const           { return source; }
-+-    RegExpFlag getFlags() const         { return flags; }
-+-    bool ignoreCase() const             { return flags & IgnoreCaseFlag; }
-+-    bool global() const                 { return flags & GlobalFlag; }
-+-    bool multiline() const              { return flags & MultilineFlag; }
-+-    bool sticky() const                 { return flags & StickyFlag; }
-+-    bool unicode() const                { return flags & UnicodeFlag; }
-++
-++    JSAtom* patternAtom() const         { return patternAtom_; }
-++
-++    JS::RegExpFlags getFlags() const    { return flags; }
-+ 
-+-    bool isCompiled(CompilationMode mode, bool latin1,
-+-                    ForceByteCodeEnum force = DontForceByteCode) const {
-+-        return compilation(mode, latin1).compiled(force);
-++    bool global() const                 { return flags.global(); }
-++    bool ignoreCase() const             { return flags.ignoreCase(); }
-++    bool multiline() const              { return flags.multiline(); }
-++    bool dotAll() const                 { return flags.dotAll(); }
-++    bool unicode() const                { return flags.unicode(); }
-++    bool sticky() const                 { return flags.sticky(); }
-++
-++    bool isCompiled(bool latin1, CodeKind codeKind = CodeKind::Any) const
-++    {
-++        return compilation(latin1).compiled(codeKind);
-+     }
-+-    bool isCompiled() const {
-+-        return isCompiled(Normal, true) || isCompiled(Normal, false)
-+-            || isCompiled(MatchOnly, true) || isCompiled(MatchOnly, false);
-+-    }
-++    bool isCompiled() const { return isCompiled(true) || isCompiled(false); }
-+ 
-+     void traceChildren(JSTracer* trc);
-+     void discardJitCode();
-+     void finalize(FreeOp* fop);
-+ 
-+     static size_t offsetOfSource() {
-+         return offsetof(RegExpShared, source);
-+     }
-+ 
-++    static size_t offsetOfPatternAtom() {
-++        return offsetof(RegExpShared, patternAtom_);
-++    }
-++
-+     static size_t offsetOfFlags() {
-+         return offsetof(RegExpShared, flags);
-+     }
-+ 
-+-    static size_t offsetOfParenCount() {
-+-        return offsetof(RegExpShared, parenCount);
-++    static size_t offsetOfPairCount() {
-++        return offsetof(RegExpShared, pairCount_);
-+     }
-+ 
-+-    static size_t offsetOfLatin1JitCode(CompilationMode mode) {
-+-        return offsetof(RegExpShared, compilationArray)
-+-             + (CompilationIndex(mode, true) * sizeof(RegExpCompilation))
-+-             + offsetof(RegExpCompilation, jitCode);
-++    static size_t offsetOfJitCode(bool latin1)
-++    {
-++        return offsetof(RegExpShared, compilationArray) +
-++               (CompilationIndex(latin1) * sizeof(RegExpCompilation)) +
-++               offsetof(RegExpCompilation, jitCode);
-+     }
-+-    static size_t offsetOfTwoByteJitCode(CompilationMode mode) {
-+-        return offsetof(RegExpShared, compilationArray)
-+-             + (CompilationIndex(mode, false) * sizeof(RegExpCompilation))
-+-             + offsetof(RegExpCompilation, jitCode);
-++
-++    static size_t offsetOfGroupsTemplate() {
-++        return offsetof(RegExpShared, groupsTemplate_);
-+     }
-+ 
-+     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
-+ 
-+ #ifdef DEBUG
-+-    static bool dumpBytecode(JSContext* cx, MutableHandleRegExpShared res, bool match_only,
-++    static bool dumpBytecode(JSContext* cx,
-++                             MutableHandleRegExpShared res,
-+                              HandleLinearString input);
-+ #endif
-+ };
-+ 
-+ class RegExpZone
-+ {
-+-    struct Key {
-+-        JSAtom* atom;
-+-        uint16_t flag;
-++    struct Key
-++    {
-++        JSAtom* atom = nullptr;
-++        JS::RegExpFlags flags = JS::RegExpFlag::NoFlags;
-+ 
-+-        Key() {}
-+-        Key(JSAtom* atom, RegExpFlag flag)
-+-          : atom(atom), flag(flag)
-+-        { }
-++        Key() = default;
-++        Key(JSAtom* atom, JS::RegExpFlags flags)
-++          : atom(atom)
-++          , flags(flags)
-++        {}
-+         MOZ_IMPLICIT Key(const ReadBarriered<RegExpShared*>& shared)
-+           : atom(shared.unbarrieredGet()->getSource()),
-+-            flag(shared.unbarrieredGet()->getFlags())
-++            flags(shared.unbarrieredGet()->getFlags())
-+         { }
-+ 
-+         typedef Key Lookup;
-+         static HashNumber hash(const Lookup& l) {
-+             HashNumber hash = DefaultHasher<JSAtom*>::hash(l.atom);
-+-            return mozilla::AddToHash(hash, l.flag);
-++            return mozilla::AddToHash(hash, l.flags.value());
-+         }
-+         static bool match(Key l, Key r) {
-+-            return l.atom == r.atom && l.flag == r.flag;
-++            return l.atom == r.atom && l.flags == r.flags;
-+         }
-+     };
-+ 
-+     /*
-+      * The set of all RegExpShareds in the zone. On every GC, every RegExpShared
-+      * that was not marked is deleted and removed from the set.
-+      */
-+     using Set = JS::WeakCache<JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, ZoneAllocPolicy>>;
-diff --git a/js/src/vm/StructuredClone.cpp.rej b/js/src/vm/StructuredClone.cpp.rej
-new file mode 100644
---- /dev/null
-+++ b/js/src/vm/StructuredClone.cpp.rej
-@@ -0,0 +1,57 @@
-+--- StructuredClone.cpp
-++++ StructuredClone.cpp
-+@@ -24,49 +24,54 @@
-+  * So during writing, we add objects to the memory when first encountering
-+  * them. When reading a typed array, a placeholder is pushed onto allObjs until
-+  * the ArrayBuffer has been read, then it is updated with the actual typed
-+  * array object.
-+  */
-+ 
-+ #include "js/StructuredClone.h"
-+ 
-++#include "mozilla/Casting.h"
-+ #include "mozilla/CheckedInt.h"
-+ #include "mozilla/EndianUtils.h"
-+ #include "mozilla/FloatingPoint.h"
-+ 
-+ #include <algorithm>
-+ 
-+ #include "jsapi.h"
-+ #include "jsdate.h"
-+ #include "jswrapper.h"
-+ 
-+ #include "builtin/DataViewObject.h"
-+ #include "builtin/MapObject.h"
-+ #include "js/Date.h"
-+ #include "js/GCHashTable.h"
-++#include "js/RegExpFlags.h"
-+ #include "vm/JSContext.h"
-+ #include "vm/RegExpObject.h"
-+ #include "vm/SavedFrame.h"
-+ #include "vm/SharedArrayObject.h"
-+ #include "vm/TypedArrayObject.h"
-+ #include "vm/WrapperObject.h"
-+ #include "wasm/WasmJS.h"
-+ 
-+ #include "vm/JSContext-inl.h"
-+ #include "vm/JSObject-inl.h"
-+ 
-+ using namespace js;
-+ 
-++using mozilla::AssertedCast;
-+ using mozilla::BitwiseCast;
-+ using mozilla::IsNaN;
-+ using mozilla::LittleEndian;
-+ using mozilla::NativeEndian;
-+ using mozilla::NumbersAreIdentical;
-+ using JS::CanonicalizeNaN;
-++using JS::RegExpFlag;
-++using JS::RegExpFlags;
-+ 
-+ // When you make updates here, make sure you consider whether you need to bump the
-+ // value of JS_STRUCTURED_CLONE_VERSION in js/public/StructuredClone.h.  You will
-+ // likely need to increment the version if anything at all changes in the serialization
-+ // format.
-+ //
-+ // Note that SCTAG_END_OF_KEYS is written into the serialized form and should have
-+ // a stable ID, it need not be at the end of the list and should not be used for

+ 0 - 17285
frg/work-js/mozilla-release/patches/TOP-NOBUG-REGEXP-2-buildit-25318.patch

@@ -1,17285 +0,0 @@
-# HG changeset patch
-# User Dmitry Butskoy <buc@buc.me>
-# Date 1687983547 -7200
-# Parent  83d6b423e02b9ddf9674e8fa3f1ec902f5d81459
-No Bug - Switch to new regexp V8 engine. r=frg a=frg
-
-diff --git a/.clang-format-ignore b/.clang-format-ignore
---- a/.clang-format-ignore
-+++ b/.clang-format-ignore
-@@ -129,8 +129,12 @@ third_party/python/rsa/.*
- third_party/python/six/.*
- third_party/python/which/.*
- third_party/rust/.*
- toolkit/components/jsoncpp/.*
- toolkit/components/protobuf/.*
- toolkit/components/url-classifier/chromium/.*
- toolkit/crashreporter/google-breakpad/.*
- tools/fuzzing/libfuzzer.*
-+
-+# Don't want to reformat irregexp (third-party code)
-+js/src/irregexp/imported/.*
-+
-diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild
---- a/config/system-headers.mozbuild
-+++ b/config/system-headers.mozbuild
-@@ -1311,16 +1311,17 @@ if CONFIG['MOZ_SYSTEM_ICU']:
-         'unicode/ucal.h',
-         'unicode/uchar.h',
-         'unicode/uclean.h',
-         'unicode/ucol.h',
-         'unicode/udat.h',
-         'unicode/udatpg.h',
-         'unicode/udisplaycontext.h',
-         'unicode/uenum.h',
-+        'unicode/uniset.h',
-         'unicode/unistr.h',
-         'unicode/unorm.h',
-         'unicode/unum.h',
-         'unicode/upluralrules.h',
-         'unicode/ureldatefmt.h',
-         'unicode/ustring.h',
-         'unicode/utypes.h',
-     ]
-diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp
---- a/dom/base/nsContentUtils.cpp
-+++ b/dom/base/nsContentUtils.cpp
-@@ -15,16 +15,17 @@
- #include "harfbuzz/hb.h"
- #include "imgICache.h"
- #include "imgIContainer.h"
- #include "imgINotificationObserver.h"
- #include "imgLoader.h"
- #include "imgRequestProxy.h"
- #include "jsapi.h"
- #include "jsfriendapi.h"
-+#include "js/RegExp.h"
- #include "js/Value.h"
- #include "Layers.h"
- #include "nsAppRunner.h"
- #include "gfxDrawable.h"
- #include "gfxPrefs.h"
- #include "ImageOps.h"
- #include "mozAutoDocUpdate.h"
- #include "mozilla/ArrayUtils.h"
-@@ -7297,38 +7298,27 @@ nsContentUtils::FindInternalContentViewe
-     }
-     return docFactory.forget();
-   }
- 
-   return nullptr;
- }
- 
- static void
--ReportPatternCompileFailure(nsAString& aPattern, nsIDocument* aDocument,
-+ReportPatternCompileFailure(nsAString& aPattern,
-+                            nsIDocument* aDocument,
-+                            JS::MutableHandle<JS::Value> error,
-                             JSContext* cx)
- {
--    MOZ_ASSERT(JS_IsExceptionPending(cx));
--
--    JS::RootedValue exn(cx);
--    if (!JS_GetPendingException(cx, &exn)) {
--      return;
--    }
--    if (!exn.isObject()) {
--      // If pending exception is not an object, it should be OOM.
--      return;
--    }
--
-     JS::AutoSaveExceptionState savedExc(cx);
--    JS::RootedObject exnObj(cx, &exn.toObject());
-+    JS::RootedObject exnObj(cx, &error.toObject());
-     JS::RootedValue messageVal(cx);
-     if (!JS_GetProperty(cx, exnObj, "message", &messageVal)) {
-       return;
-     }
--    MOZ_ASSERT(messageVal.isString());
--
-     JS::RootedString messageStr(cx, messageVal.toString());
-     MOZ_ASSERT(messageStr);
- 
-     nsAutoString wideMessage;
-     if (!AssignJSString(cx, wideMessage, messageStr)) {
-         return;
-     }
- 
-@@ -7352,35 +7342,46 @@ nsContentUtils::IsPatternMatching(nsAStr
- 
-   AutoJSContext cx;
-   AutoDisableJSInterruptCallback disabler(cx);
- 
-   // We can use the junk scope here, because we're just using it for
-   // regexp evaluation, not actual script execution.
-   JSAutoCompartment ac(cx, xpc::UnprivilegedJunkScope());
- 
-+  // Check if the pattern by itself is valid first, and not that it only becomes
-+  // valid once we add ^(?: and )$.
-+  JS::RootedValue error(cx);
-+  if (!JS::CheckRegExpSyntax(
-+          cx, static_cast<char16_t*>(aPattern.BeginWriting()),
-+          aPattern.Length(), JS::RegExpFlag::Unicode, &error)) {
-+    return true;
-+  }
-+
-+  if (!error.isUndefined()) {
-+    ReportPatternCompileFailure(aPattern, aDocument, &error, cx);
-+    return true;
-+  }
-+
-   // The pattern has to match the entire value.
-   aPattern.InsertLiteral(u"^(?:", 0);
-   aPattern.AppendLiteral(")$");
- 
-   JS::Rooted<JSObject*> re(cx,
--    JS_NewUCRegExpObject(cx,
-+    JS::NewUCRegExpObject(cx,
-                          static_cast<char16_t*>(aPattern.BeginWriting()),
--                         aPattern.Length(), JSREG_UNICODE));
-+                         aPattern.Length(), JS::RegExpFlag::Unicode));
-+
-   if (!re) {
--    // Remove extra patterns added above to report with the original pattern.
--    aPattern.Cut(0, 4);
--    aPattern.Cut(aPattern.Length() - 2, 2);
--    ReportPatternCompileFailure(aPattern, aDocument, cx);
-     return true;
-   }
- 
-   JS::Rooted<JS::Value> rval(cx, JS::NullValue());
-   size_t idx = 0;
--  if (!JS_ExecuteRegExpNoStatics(cx, re,
-+  if (!JS::ExecuteRegExpNoStatics(cx, re,
-                                  static_cast<char16_t*>(aValue.BeginWriting()),
-                                  aValue.Length(), &idx, true, &rval)) {
-     return true;
-   }
- 
-   return !rval.isNull();
- }
- 
-diff --git a/js/ipc/WrapperAnswer.cpp b/js/ipc/WrapperAnswer.cpp
---- a/js/ipc/WrapperAnswer.cpp
-+++ b/js/ipc/WrapperAnswer.cpp
-@@ -7,16 +7,17 @@
- 
- #include "WrapperAnswer.h"
- #include "JavaScriptLogging.h"
- #include "mozilla/dom/ContentChild.h"
- #include "mozilla/dom/BindingUtils.h"
- #include "mozilla/dom/ScriptSettings.h"
- #include "xpcprivate.h"
- #include "js/Class.h"
-+#include "js/RegExp.h"
- #include "jsfriendapi.h"
- 
- using namespace JS;
- using namespace mozilla;
- using namespace mozilla::jsipc;
- 
- // Note - Using AutoJSAPI (rather than AutoEntryScript) for a trap means
- // that we don't expect it to run script. For most of these traps that will only
-@@ -676,25 +677,25 @@ WrapperAnswer::RecvRegExpToShared(const 
-     if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
-         return false;
-     JSContext* cx = jsapi.cx();
- 
-     RootedObject obj(cx, findObjectById(cx, objId));
-     if (!obj)
-         return deadCPOW(jsapi, rs);
- 
--    RootedString sourceJSStr(cx, JS_GetRegExpSource(cx, obj));
-+    RootedString sourceJSStr(cx, JS::GetRegExpSource(cx, obj));
-     if (!sourceJSStr)
-         return fail(jsapi, rs);
-     nsAutoJSString sourceStr;
-     if (!sourceStr.init(cx, sourceJSStr))
-         return fail(jsapi, rs);
-     source->Assign(sourceStr);
- 
--    *flags = JS_GetRegExpFlags(cx, obj);
-+    *flags = JS::GetRegExpFlags(cx, obj).value();
- 
-     return ok(rs);
- }
- 
- bool
- WrapperAnswer::RecvGetPropertyKeys(const ObjectId& objId, const uint32_t& flags,
-                                    ReturnStatus* rs, nsTArray<JSIDVariant>* ids)
- {
-diff --git a/js/ipc/WrapperOwner.cpp b/js/ipc/WrapperOwner.cpp
---- a/js/ipc/WrapperOwner.cpp
-+++ b/js/ipc/WrapperOwner.cpp
-@@ -6,16 +6,18 @@
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #include "WrapperOwner.h"
- #include "JavaScriptLogging.h"
- #include "mozilla/Unused.h"
- #include "mozilla/dom/BindingUtils.h"
- #include "jsfriendapi.h"
- #include "js/CharacterEncoding.h"
-+#include "js/RegExp.h"
-+#include "js/RegExpFlags.h"
- #include "xpcprivate.h"
- #include "CPOWTimer.h"
- #include "WrapperFactory.h"
- 
- #include "nsIDocShellTreeItem.h"
- #include "nsIDOMDocument.h"
- 
- using namespace js;
-@@ -872,17 +874,18 @@ WrapperOwner::regexp_toShared(JSContext*
-         return nullptr;
-     }
-     LOG_STACK();
- 
-     if (!ok(cx, status))
-         return nullptr;
- 
-     RootedObject regexp(cx);
--    regexp = JS_NewUCRegExpObject(cx, source.get(), source.Length(), flags);
-+    regexp = JS::NewUCRegExpObject(
-+      cx, source.get(), source.Length(), RegExpFlags(flags));
-     if (!regexp)
-         return nullptr;
- 
-     return js::RegExpToSharedNonInline(cx, regexp);
- }
- 
- void
- CPOWProxyHandler::finalize(JSFreeOp* fop, JSObject* proxy) const
-diff --git a/js/moz.configure b/js/moz.configure
---- a/js/moz.configure
-+++ b/js/moz.configure
-@@ -428,21 +428,8 @@ js_option('--enable-pipeline-operator', 
- 
- @depends('--enable-pipeline-operator')
- def enable_pipeline_operator(value):
-     if value:
-         return True
- 
- set_config('ENABLE_PIPELINE_OPERATOR', enable_pipeline_operator)
- set_define('ENABLE_PIPELINE_OPERATOR', enable_pipeline_operator)
--
--# Initial support for new regexp engine
--# ==================================================
--
--js_option('--enable-new-regexp', default=False, help='Enable new regexp engine')
--
--@depends('--enable-new-regexp')
--def enable_new_regexp(value):
--    if value:
--        return True
--
--set_config('ENABLE_NEW_REGEXP', enable_new_regexp)
--set_define('ENABLE_NEW_REGEXP', enable_new_regexp)
-diff --git a/js/public/Class.h b/js/public/Class.h
---- a/js/public/Class.h
-+++ b/js/public/Class.h
-@@ -838,17 +838,17 @@ static const uint32_t JSCLASS_FOREGROUND
- // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
- // previously allowed, but is now an ES5 violation and thus unsupported.
- //
- // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
- // the beginning of every global object's slots for use by the
- // application.
- static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
- static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
--    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 38;
-+    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 39;
- 
- #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                              \
-     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
- #define JSCLASS_GLOBAL_FLAGS                                                  \
-     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
- #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
-   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
-    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
-diff --git a/js/public/RegExp.h b/js/public/RegExp.h
-new file mode 100644
---- /dev/null
-+++ b/js/public/RegExp.h
-@@ -0,0 +1,107 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+ *
-+ * This Source Code Form is "Incompatible With Secondary Licenses", as
-+ * defined by the Mozilla Public License, v. 2.0.
-+ */
-+
-+/* Public JS API for Regular Expressions. */
-+
-+#ifndef js_RegExp_h
-+#define js_RegExp_h
-+
-+#include <stddef.h> // size_t
-+
-+#include "jstypes.h" // JS_PUBLIC_API
-+
-+#include "js/RegExpFlags.h"  // JS::RegExpFlags
-+#include "js/RootingAPI.h" // JS::{,Mutable}Handle
-+#include "js/Value.h"      // JS::Value
-+
-+struct JSContext;
-+class JSString;
-+
-+namespace JS {
-+
-+/*
-+ * Create a new RegExp for the given Latin-1-encoded source and flags.
-+ */
-+extern JS_PUBLIC_API(JSObject*) NewRegExpObject(JSContext* cx,
-+                                                const char* bytes,
-+                                                size_t length,
-+                                                RegExpFlags flags);
-+
-+/*
-+ * Create a new RegExp for the given UC source and flags.
-+ */
-+extern JS_PUBLIC_API(JSObject*) NewUCRegExpObject(JSContext* cx,
-+                                                  const char16_t* chars,
-+                                                  size_t length,
-+                                                  RegExpFlags flags);
-+
-+extern JS_PUBLIC_API(bool)
-+  SetRegExpInput(JSContext* cx, Handle<JSObject*> obj, Handle<JSString*> input);
-+
-+extern JS_PUBLIC_API(bool)
-+  ClearRegExpStatics(JSContext* cx, Handle<JSObject*> obj);
-+
-+/* RegExp interface for callers with a global object. */
-+
-+extern JS_PUBLIC_API(bool) ExecuteRegExp(JSContext* cx,
-+                                         Handle<JSObject*> obj,
-+                                         Handle<JSObject*> reobj,
-+                                         char16_t* chars,
-+                                         size_t length,
-+                                         size_t* indexp,
-+                                         bool test,
-+                                         MutableHandle<Value> rval);
-+
-+/* RegExp interface for callers without a global object. */
-+
-+extern JS_PUBLIC_API(bool) ExecuteRegExpNoStatics(JSContext* cx,
-+                                                  Handle<JSObject*> reobj,
-+                                                  char16_t* chars,
-+                                                  size_t length,
-+                                                  size_t* indexp,
-+                                                  bool test,
-+                                                  MutableHandle<Value> rval);
-+
-+/*
-+ * Returns true on success, setting |*isRegExp| to true if |obj| is a RegExp
-+ * object or a wrapper around one, or to false if not. Returns false on failure.
-+ *
-+ * This method returns true with |*isRegExp == false| when passed an ES6 proxy
-+ * whose target is a RegExp, or when passed a revoked proxy.
-+ */
-+extern JS_PUBLIC_API(bool)
-+  ObjectIsRegExp(JSContext* cx, Handle<JSObject*> obj, bool* isRegExp);
-+
-+/*
-+ * Given a RegExp object (or a wrapper around one), return all JS::RegExpFlag::* for it.
-+ */
-+extern JS_PUBLIC_API(RegExpFlags)
-+  GetRegExpFlags(JSContext* cx, Handle<JSObject*> obj);
-+
-+/*
-+ * Return the source text for a RegExp object (or a wrapper around one), or null on failure.
-+ */
-+extern JS_PUBLIC_API(JSString*)
-+  GetRegExpSource(JSContext* cx, Handle<JSObject*> obj);
-+
-+/**
-+ * Check whether the given source is a valid regexp. If the regexp parses
-+ * successfully, returns true and sets |error| to undefined. If the regexp
-+ * has a syntax error, returns true, sets |error| to that error object, and
-+ * clears the exception. Returns false on OOM or over-recursion.
-+ */
-+extern JS_PUBLIC_API(bool) CheckRegExpSyntax(JSContext* cx,
-+                                             const char16_t* chars,
-+                                             size_t length,
-+                                             RegExpFlags flags,
-+                                             MutableHandle<Value> error);
-+
-+} // namespace JS
-+
-+#endif // js_RegExp_h
-diff --git a/js/public/RegExpFlags.h b/js/public/RegExpFlags.h
-new file mode 100644
---- /dev/null
-+++ b/js/public/RegExpFlags.h
-@@ -0,0 +1,171 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+ *
-+ * This Source Code Form is "Incompatible With Secondary Licenses", as
-+ * defined by the Mozilla Public License, v. 2.0.
-+ */
-+
-+/* Regular Expression flags. */
-+
-+#ifndef js_RegExpFlags_h
-+#define js_RegExpFlags_h
-+
-+#include "mozilla/Assertions.h" // for MOZ_ASSERT
-+#include "mozilla/Attributes.h" // for MOZ_IMPLICIT
-+#include <stdint.h>
-+
-+namespace JS {
-+
-+/*
-+ * Regular Expression flag values, suitable for initializing a collection of
-+ * regular expression flags as defined below in |RegExpFlags|.
-+ * Flags are listed in alphabetical order by syntax: /g, /i, /m, /s, /u, /y.
-+ */
-+
-+class RegExpFlag
-+{
-+  // WARNING TO SPIDERMONKEY HACKERS (embedders must assume these values can change):
-+  //
-+  // Flag-bit values appear in XDR and structured clone data formats, so none of
-+  // these values can be changed (including to assign values in numerically
-+  // ascending order) unless you also add a translation layer.
-+public:
-+  /**
-+   * Act globally and find *all* matches (rather than stopping after just the
-+   * first one), i.e. /g.
-+   */
-+  static uint8_t const Global = 0x02;
-+
-+  /**
-+   * Interpret regular expression source text case-insensitively by folding
-+   * uppercase letters to lowercase, i.e. /i.
-+   */
-+  static uint8_t const IgnoreCase = 0x01;
-+
-+  /** Treat ^ and $ as begin and end of line, i.e. /m. */
-+  static uint8_t const Multiline = 0x04;
-+
-+  /** Match '.' to any character including newlines, i.e. /s. */
-+  static uint8_t const DotAll = 0x20;
-+
-+  /** Use Unicode semantics, i.e. /u. */
-+  static uint8_t const Unicode = 0x10;
-+
-+  /** Only match starting from <regular expression>.lastIndex, i.e. /y. */
-+  static uint8_t const Sticky = 0x08;
-+
-+  /** No regular expression flags. */
-+  static uint8_t const NoFlags = 0x00;
-+
-+  /** All regular expression flags. */
-+  static uint8_t const AllFlags = 0x3F; //All supported bits set: 0b11'1111
-+};
-+
-+/*
-+ * A collection of regular expression flags.  Individual flag values may be
-+ * combined into a collection using bitwise operators.
-+ */
-+class RegExpFlags
-+{
-+public:
-+  using Flag = uint8_t;
-+
-+private:
-+  Flag flags_;
-+
-+public:
-+  RegExpFlags() = default;
-+
-+  MOZ_IMPLICIT RegExpFlags(Flag flags)
-+    : flags_(flags)
-+  {
-+    MOZ_ASSERT((flags & RegExpFlag::AllFlags) == flags,
-+               "flags must not contain unrecognized flags");
-+  }
-+
-+  RegExpFlags(const RegExpFlags&) = default;
-+
-+  bool operator==(const RegExpFlags& other) const
-+  {
-+    return flags_ == other.flags_;
-+  }
-+
-+  bool operator!=(const RegExpFlags& other) const { return !(*this == other); }
-+
-+  RegExpFlags& operator&=(const RegExpFlags& rhs)
-+  {
-+    flags_ &= rhs.flags_;
-+    return *this;
-+  }
-+
-+  RegExpFlags& operator|=(const RegExpFlags& rhs)
-+  {
-+    flags_ |= rhs.flags_;
-+    return *this;
-+  }
-+
-+  RegExpFlags operator&(Flag flag) const { return RegExpFlags(flags_ & flag); }
-+
-+  RegExpFlags operator|(Flag flag) const { return RegExpFlags(flags_ | flag); }
-+
-+  RegExpFlags operator^(Flag flag) const { return RegExpFlags(flags_ ^ flag); }
-+
-+  RegExpFlags operator~() const
-+  {
-+    return RegExpFlags(~flags_ & RegExpFlag::AllFlags);
-+  }
-+
-+  bool global() const { return flags_ & RegExpFlag::Global; }
-+  bool ignoreCase() const { return flags_ & RegExpFlag::IgnoreCase; }
-+  bool multiline() const { return flags_ & RegExpFlag::Multiline; }
-+  bool dotAll() const { return flags_ & RegExpFlag::DotAll; }
-+  bool unicode() const { return flags_ & RegExpFlag::Unicode; }
-+  bool sticky() const { return flags_ & RegExpFlag::Sticky; }
-+
-+  explicit operator bool() const { return flags_ != 0; }
-+
-+  Flag value() const { return flags_; }
-+};
-+
-+inline RegExpFlags&
-+operator&=(RegExpFlags& flags, RegExpFlags::Flag flag)
-+{
-+  flags = flags & flag;
-+  return flags;
-+}
-+
-+inline RegExpFlags&
-+operator|=(RegExpFlags& flags, RegExpFlags::Flag flag)
-+{
-+  flags = flags | flag;
-+  return flags;
-+}
-+
-+inline RegExpFlags&
-+operator^=(RegExpFlags& flags, RegExpFlags::Flag flag)
-+{
-+  flags = flags ^ flag;
-+  return flags;
-+}
-+
-+inline RegExpFlags
-+operator&(const RegExpFlags& lhs, const RegExpFlags& rhs)
-+{
-+  RegExpFlags result = lhs;
-+  result &= rhs;
-+  return lhs;
-+}
-+
-+inline RegExpFlags
-+operator|(const RegExpFlags& lhs, const RegExpFlags& rhs)
-+{
-+  RegExpFlags result = lhs;
-+  result |= rhs;
-+  return result;
-+}
-+
-+} // namespace JS
-+
-+#endif // js_RegExpFlags_h
-diff --git a/js/public/Value.h b/js/public/Value.h
---- a/js/public/Value.h
-+++ b/js/public/Value.h
-@@ -707,17 +707,17 @@ class MOZ_NON_PARAM alignas(8) Value
- #endif
-     }
- 
-     uint32_t payloadAsRawUint32() const {
-         MOZ_ASSERT(!isDouble());
-         return data.s.payload.u32;
-     }
- 
--    uint64_t asRawBits() const {
-+    constexpr uint64_t asRawBits() const {
-         return data.asBits;
-     }
- 
-     JSValueType extractNonDoubleType() const {
-         uint32_t type = toTag() & 0xF;
-         MOZ_ASSERT(type > JSVAL_TYPE_DOUBLE);
-         return JSValueType(type);
-     }
-diff --git a/js/src/.clang-format b/js/src/.clang-format
---- a/js/src/.clang-format
-+++ b/js/src/.clang-format
-@@ -1,10 +0,0 @@
--# Clang-format style for SpiderMonkey code which is different than the standard Mozilla style.
--BasedOnStyle: Mozilla
--ColumnLimit: 99
--IndentWidth: 4
--
--# Ignore all comments because they aren't reflowed properly.
--# We require 80-col comments and 99-col code.
--CommentPragmas: "^"
--
--SortIncludes: false
-diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp
---- a/js/src/builtin/RegExp.cpp
-+++ b/js/src/builtin/RegExp.cpp
-@@ -1,111 +1,175 @@
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-  * vim: set ts=8 sts=4 et sw=4 tw=99:
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #include "builtin/RegExp.h"
- 
-+#include "mozilla/Casting.h"
- #include "mozilla/CheckedInt.h"
- #include "mozilla/TypeTraits.h"
- 
- #include "frontend/TokenStream.h"
--#include "irregexp/RegExpParser.h"
-+#include "irregexp/RegExpAPI.h"
- #include "jit/InlinableNatives.h"
-+#include "js/RegExpFlags.h"  // JS::RegExpFlag, JS::RegExpFlags
-+#include "vm/NativeObject-inl.h"
- #include "vm/JSContext.h"
- #include "vm/RegExpStatics.h"
- #include "vm/SelfHosting.h"
- #include "vm/StringBuffer.h"
- #include "vm/Unicode.h"
- 
- #include "vm/JSObject-inl.h"
- #include "vm/NativeObject-inl.h"
- #include "vm/UnboxedObject-inl.h"
- 
- using namespace js;
- using namespace js::unicode;
- 
- using mozilla::ArrayLength;
-+using mozilla::AssertedCast;
- using mozilla::CheckedInt;
- using mozilla::Maybe;
- 
-+using JS::RegExpFlag;
-+using JS::RegExpFlags;
-+
- /*
-- * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-- * steps 3, 16-25.
-+ * ES 2021 draft 21.2.5.2.2: Steps 16-28
-+ * https://tc39.es/ecma262/#sec-regexpbuiltinexec
-  */
- bool
--js::CreateRegExpMatchResult(JSContext* cx, HandleString input, const MatchPairs& matches,
-+js::CreateRegExpMatchResult(JSContext* cx,
-+                            HandleRegExpShared re,
-+                            HandleString input,
-+                            const MatchPairs& matches,
-                             MutableHandleValue rval)
- {
-+    MOZ_ASSERT(re);
-     MOZ_ASSERT(input);
- 
-     /*
-      * Create the (slow) result array for a match.
-      *
-      * Array contents:
-      *  0:              matched string
-      *  1..pairCount-1: paren matches
-      *  input:          input string
-      *  index:          start index for the match
-+     *  groups:         named capture groups for the match
-      */
- 
-     /* Get the templateObject that defines the shape and type of the output object */
-     JSObject* templateObject = cx->compartment()->regExps.getOrCreateMatchResultTemplateObject(cx);
--    if (!templateObject)
-+    if (!templateObject) {
-         return false;
-+    }
- 
-+    // Step 16
-     size_t numPairs = matches.length();
-     MOZ_ASSERT(numPairs > 0);
- 
--    /* Step 17. */
-+    // Steps 18-19
-     RootedArrayObject arr(cx, NewDenseFullyAllocatedArrayWithTemplate(cx, numPairs, templateObject));
--    if (!arr)
-+    if (!arr) {
-         return false;
-+    }
- 
--    /* Steps 22-24.
--     * Store a Value for each pair. */
-+    // Step 24 (reordered)
-+    RootedNativeObject groups(cx);
-+    bool groupsInDictionaryMode = false;
-+    if (re->numNamedCaptures() > 0) {
-+        RootedNativeObject groupsTemplate(cx, re->getGroupsTemplate());
-+        if (groupsTemplate->inDictionaryMode()) {
-+            groups = NewObjectWithGivenProto<PlainObject>(cx, nullptr);
-+            groups->setGroup(groupsTemplate->group());
-+            groupsInDictionaryMode = true;
-+        } else {
-+            JS_TRY_VAR_OR_RETURN_FALSE(
-+              cx, groups, NativeObject::createWithTemplate(cx, gc::DefaultHeap, groupsTemplate));
-+        }
-+    }
-+
-+    // Steps 22-23 and 27 a-e.
-+    // Store a Value for each pair.
-     for (size_t i = 0; i < numPairs; i++) {
-         const MatchPair& pair = matches[i];
- 
-         if (pair.isUndefined()) {
-             MOZ_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
-             arr->setDenseInitializedLength(i + 1);
-             arr->initDenseElement(i, UndefinedValue());
-         } else {
-             JSLinearString* str = NewDependentString(cx, input, pair.start, pair.length());
-             if (!str)
-                 return false;
-             arr->setDenseInitializedLength(i + 1);
-             arr->initDenseElement(i, StringValue(str));
-         }
-     }
- 
-+    // Step 27 f.
-+    // The groups template object stores the names of the named captures in the
-+    // the order in which they are defined. The named capture indices vector
-+    // stores the corresponding capture indices. If we are not in dictionary mode,
-+    // we simply fill in the slots with the correct values. In dictionary mode,
-+    // we have to define the properties explicitly.
-+    if (!groupsInDictionaryMode) {
-+        for (uint32_t i = 0; i < re->numNamedCaptures(); i++) {
-+            uint32_t idx = re->getNamedCaptureIndex(i);
-+            groups->setSlot(i, arr->getDenseElement(idx));
-+        }
-+    } else {
-+        AutoIdVector keys(cx);
-+        RootedPlainObject groupsTemplate(cx, re->getGroupsTemplate());
-+        if (!GetPropertyKeys(cx, groupsTemplate, 0, &keys)) {
-+            return false;
-+        }
-+        MOZ_ASSERT(keys.length() == re->numNamedCaptures());
-+        RootedId key(cx);
-+        RootedValue val(cx);
-+        for (uint32_t i = 0; i < keys.length(); i++) {
-+            key = keys[i];
-+            uint32_t idx = re->getNamedCaptureIndex(i);
-+            val = arr->getDenseElement(idx);
-+            if (!NativeDefineDataProperty(cx, groups, key, val, JSPROP_ENUMERATE)) {
-+                return false;
-+            }
-+        }
-+    }
-+
-     /* Step 20 (reordered).
-      * Set the |index| property. (TemplateObject positions it in slot 0) */
-     arr->setSlot(0, Int32Value(matches[0].start));
- 
-     /* Step 21 (reordered).
-      * Set the |input| property. (TemplateObject positions it in slot 1) */
-     arr->setSlot(1, StringValue(input));
- 
-+    // Steps 25-26 (reordered)
-+    // Set the |groups| property.
-+    arr->setSlot(2, groups ? ObjectValue(*groups) : UndefinedValue());
-+
- #ifdef DEBUG
-     RootedValue test(cx);
-     RootedId id(cx, NameToId(cx->names().index));
-     if (!NativeGetProperty(cx, arr, id, &test))
-         return false;
-     MOZ_ASSERT(test == arr->getSlot(0));
-     id = NameToId(cx->names().input);
-     if (!NativeGetProperty(cx, arr, id, &test))
-         return false;
-     MOZ_ASSERT(test == arr->getSlot(1));
- #endif
- 
--    /* Step 25. */
-+    // Step 28.
-     rval.setObject(*arr);
-     return true;
- }
- 
- static int32_t
- CreateRegExpSearchResult(const MatchPairs& matches)
- {
-     /* Fit the start and limit of match into a int32_t. */
-@@ -116,29 +180,29 @@ CreateRegExpSearchResult(const MatchPair
-     return position | (lastIndex << 15);
- }
- 
- /*
-  * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-  * steps 3, 9-14, except 12.a.i, 12.c.i.1.
-  */
- static RegExpRunStatus
--ExecuteRegExpImpl(JSContext* cx, RegExpStatics* res, MutableHandleRegExpShared re,
--                  HandleLinearString input, size_t searchIndex, MatchPairs* matches,
--                  size_t* endIndex)
-+ExecuteRegExpImpl(JSContext* cx,
-+                  RegExpStatics* res,
-+                  MutableHandleRegExpShared re,
-+                  HandleLinearString input,
-+                  size_t searchIndex,
-+                  MatchPairs* matches)
- {
--    RegExpRunStatus status = RegExpShared::execute(cx, re, input, searchIndex, matches, endIndex);
-+    RegExpRunStatus status = RegExpShared::execute(cx, re, input, searchIndex, matches);
- 
-     /* Out of spec: Update RegExpStatics. */
-     if (status == RegExpRunStatus_Success && res) {
--        if (matches) {
--            if (!res->updateFromMatchPairs(cx, input, *matches))
--                return RegExpRunStatus_Error;
--        } else {
--            res->updateLazily(cx, input, re, searchIndex);
-+        if (!res->updateFromMatchPairs(cx, input, *matches)) {
-+            return RegExpRunStatus_Error;
-         }
-     }
-     return status;
- }
- 
- /* Legacy ExecuteRegExp behavior is baked into the JSAPI. */
- bool
- js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
-@@ -147,17 +211,17 @@ js::ExecuteRegExpLegacy(JSContext* cx, R
- {
-     RootedRegExpShared shared(cx, RegExpObject::getShared(cx, reobj));
-     if (!shared)
-         return false;
- 
-     ScopedMatchPairs matches(&cx->tempLifoAlloc());
- 
-     RegExpRunStatus status = ExecuteRegExpImpl(cx, res, &shared, input, *lastIndex,
--                                               &matches, nullptr);
-+                                               &matches);
-     if (status == RegExpRunStatus_Error)
-         return false;
- 
-     if (status == RegExpRunStatus_Success_NotFound) {
-         /* ExecuteRegExp() previously returned an array or null. */
-         rval.setNull();
-         return true;
-     }
-@@ -165,35 +229,35 @@ js::ExecuteRegExpLegacy(JSContext* cx, R
-     *lastIndex = matches[0].limit;
- 
-     if (test) {
-         /* Forbid an array, as an optimization. */
-         rval.setBoolean(true);
-         return true;
-     }
- 
--    return CreateRegExpMatchResult(cx, input, matches, rval);
-+    return CreateRegExpMatchResult(cx, shared, input, matches, rval);
- }
- 
- static bool
--CheckPatternSyntaxSlow(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
-+CheckPatternSyntaxSlow(JSContext* cx, HandleAtom pattern, RegExpFlags flags)
- {
-     CompileOptions options(cx);
-     frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
--    return irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern,
--                                        flags & UnicodeFlag);
-+    return irregexp::CheckPatternSyntax(cx, dummyTokenStream, pattern, flags);
- }
- 
- static RegExpShared*
--CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
-+CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlags flags)
- {
-     // If we already have a RegExpShared for this pattern/flags, we can
-     // avoid the much slower CheckPatternSyntaxSlow call.
- 
--    if (RegExpShared* shared = cx->zone()->regExps.maybeGet(pattern, flags)) {
-+    RootedRegExpShared shared(cx, cx->zone()->regExps.maybeGet(pattern, flags));
-+    if (shared) {
- #ifdef DEBUG
-         // Assert the pattern is valid.
-         if (!CheckPatternSyntaxSlow(cx, pattern, flags)) {
-             MOZ_ASSERT(cx->isThrowingOutOfMemory() || cx->isThrowingOverRecursed());
-             return nullptr;
-         }
- #endif
-         return shared;
-@@ -233,17 +297,17 @@ RegExpInitializeIgnoringLastIndex(JSCont
-     } else {
-         /* Step 2. */
-         pattern = ToAtom<CanGC>(cx, patternValue);
-         if (!pattern)
-             return false;
-     }
- 
-     /* Step 3. */
--    RegExpFlag flags = RegExpFlag(0);
-+    RegExpFlags flags = RegExpFlag::NoFlags;
-     if (!flagsValue.isUndefined()) {
-         /* Step 4. */
-         RootedString flagStr(cx, ToString<CanGC>(cx, flagsValue));
-         if (!flagStr)
-             return false;
- 
-         /* Step 5. */
-         if (!ParseRegExpFlags(cx, flagStr, &flags))
-@@ -336,22 +400,21 @@ regexp_compile_impl(JSContext* cx, const
-     if (cls == ESClass::RegExp) {
-         // Step 3a.
-         if (args.hasDefined(1)) {
-             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NEWREGEXP_FLAGGED);
-             return false;
-         }
- 
-         // Beware!  |patternObj| might be a proxy into another compartment, so
--        // don't assume |patternObj.is<RegExpObject>()|.  For the same reason,
--        // don't reuse the RegExpShared below.
-+        // don't assume |patternObj.is<RegExpObject>()|.
-         RootedObject patternObj(cx, &patternValue.toObject());
- 
-         RootedAtom sourceAtom(cx);
--        RegExpFlag flags;
-+        RegExpFlags flags = RegExpFlag::NoFlags;
-         {
-             // Step 3b.
-             RegExpShared* shared = RegExpToShared(cx, patternObj);
-             if (!shared)
-                 return false;
- 
-             sourceAtom = shared->getSource();
-             flags = shared->getFlags();
-@@ -435,17 +498,17 @@ js::regexp_construct(JSContext* cx, unsi
-     if (!GetClassOfValue(cx, patternValue, &cls))
-         return false;
-     if (cls == ESClass::RegExp) {
-         // Beware!  |patternObj| might be a proxy into another compartment, so
-         // don't assume |patternObj.is<RegExpObject>()|.
-         RootedObject patternObj(cx, &patternValue.toObject());
- 
-         RootedAtom sourceAtom(cx);
--        RegExpFlag flags;
-+        RegExpFlags flags;
-         RootedRegExpShared shared(cx);
-         {
-             // Step 4.a.
-             shared = RegExpToShared(cx, patternObj);
-             if (!shared)
-                 return false;
-             sourceAtom = shared->getSource();
- 
-@@ -465,28 +528,28 @@ js::regexp_construct(JSContext* cx, unsi
- 
-         Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, GenericObject, proto));
-         if (!regexp)
-             return false;
- 
-         // Step 8.
-         if (args.hasDefined(1)) {
-             // Step 4.c / 21.2.3.2.2 RegExpInitialize step 4.
--            RegExpFlag flagsArg = RegExpFlag(0);
-+            RegExpFlags flagsArg = RegExpFlag::NoFlags;
-             RootedString flagStr(cx, ToString<CanGC>(cx, args[1]));
-             if (!flagStr)
-                 return false;
-             if (!ParseRegExpFlags(cx, flagStr, &flagsArg))
-                 return false;
- 
-             // Don't reuse the RegExpShared if we have different flags.
-             if (flags != flagsArg)
-                 shared = nullptr;
- 
--            if (!(flags & UnicodeFlag) && flagsArg & UnicodeFlag) {
-+            if (!flags.unicode() && flagsArg.unicode()) {
-                 // Have to check syntax again when adding 'u' flag.
- 
-                 // ES 2017 draft rev 9b49a888e9dfe2667008a01b2754c3662059ae56
-                 // 21.2.3.2.2 step 7.
-                 shared = CheckPatternSyntax(cx, sourceAtom, flagsArg);
-                 if (!shared)
-                     return false;
-             }
-@@ -555,25 +618,25 @@ js::regexp_construct_raw_flags(JSContext
-     MOZ_ASSERT(!args.isConstructing());
- 
-     // Step 4.a.
-     RootedAtom sourceAtom(cx, AtomizeString(cx, args[0].toString()));
-     if (!sourceAtom)
-         return false;
- 
-     // Step 4.c.
--    int32_t flags = int32_t(args[1].toNumber());
-+    RegExpFlags flags = AssertedCast<uint8_t>(int32_t(args[1].toNumber()));
- 
-     // Step 7.
-     RegExpObject* regexp = RegExpAlloc(cx, GenericObject);
-     if (!regexp)
-         return false;
- 
-     // Step 8.
--    regexp->initAndZeroLastIndex(sourceAtom, RegExpFlag(flags), cx);
-+    regexp->initAndZeroLastIndex(sourceAtom, flags, cx);
-     args.rval().setObject(*regexp);
-     return true;
- }
- 
- MOZ_ALWAYS_INLINE bool
- IsRegExpPrototype(HandleValue v)
- {
-     if (IsRegExpObject(v) || !v.isObject())
-@@ -695,16 +758,43 @@ regexp_source(JSContext* cx, unsigned ar
-         args.rval().setString(cx->names().emptyRegExp);
-         return true;
-     }
- 
-     // Steps 1-4.
-     return CallNonGenericMethod<IsRegExpObject, regexp_source_impl>(cx, args);
- }
- 
-+// ES 2018 dotAll
-+MOZ_ALWAYS_INLINE bool
-+regexp_dotAll_impl(JSContext* cx, const CallArgs& args)
-+{
-+    MOZ_ASSERT(IsRegExpObject(args.thisv()));
-+
-+    // Steps 4-6.
-+    RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
-+    args.rval().setBoolean(reObj->dotAll());
-+    return true;
-+}
-+
-+bool
-+js::regexp_dotAll(JSContext* cx, unsigned argc, JS::Value* vp)
-+{
-+    CallArgs args = CallArgsFromVp(argc, vp);
-+
-+    // Step 3.a.
-+    if (IsRegExpPrototype(args.thisv())) {
-+        args.rval().setUndefined();
-+        return true;
-+    }
-+
-+    // Steps 1-3.
-+    return CallNonGenericMethod<IsRegExpObject, regexp_dotAll_impl>(cx, args);
-+}
-+
- // ES 2017 draft 21.2.5.12.
- MOZ_ALWAYS_INLINE bool
- regexp_sticky_impl(JSContext* cx, const CallArgs& args)
- {
-     MOZ_ASSERT(IsRegExpObject(args.thisv()));
- 
-     // Steps 4-6.
-     RegExpObject* reObj = &args.thisv().toObject().as<RegExpObject>();
-@@ -757,26 +847,28 @@ js::regexp_unicode(JSContext* cx, unsign
- const JSPropertySpec js::regexp_properties[] = {
-     JS_SELF_HOSTED_GET("flags", "RegExpFlagsGetter", 0),
-     JS_PSG("global", regexp_global, 0),
-     JS_PSG("ignoreCase", regexp_ignoreCase, 0),
-     JS_PSG("multiline", regexp_multiline, 0),
-     JS_PSG("source", regexp_source, 0),
-     JS_PSG("sticky", regexp_sticky, 0),
-     JS_PSG("unicode", regexp_unicode, 0),
-+    JS_PSG("dotAll", regexp_dotAll, 0),
-     JS_PS_END
- };
- 
- const JSFunctionSpec js::regexp_methods[] = {
-     JS_SELF_HOSTED_FN(js_toSource_str, "RegExpToString", 0, 0),
-     JS_SELF_HOSTED_FN(js_toString_str, "RegExpToString", 0, 0),
-     JS_FN("compile",        regexp_compile,     2,0),
-     JS_SELF_HOSTED_FN("exec", "RegExp_prototype_Exec", 1,0),
-     JS_SELF_HOSTED_FN("test", "RegExpTest" ,    1,0),
-     JS_SELF_HOSTED_SYM_FN(match, "RegExpMatch", 1,0),
-+    JS_SELF_HOSTED_SYM_FN(matchAll, "RegExpMatchAll", 1, 0),
-     JS_SELF_HOSTED_SYM_FN(replace, "RegExpReplace", 2,0),
-     JS_SELF_HOSTED_SYM_FN(search, "RegExpSearch", 1,0),
-     JS_SELF_HOSTED_SYM_FN(split, "RegExpSplit", 2,0),
-     JS_FS_END
- };
- 
- #define STATIC_PAREN_GETTER_CODE(parenNum)                                      \
-     if (!res->createParen(cx, parenNum, args.rval()))                           \
-@@ -901,17 +993,17 @@ IsTrailSurrogateWithLeadSurrogate(Handle
- }
- 
- /*
-  * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-  * steps 3, 9-14, except 12.a.i, 12.c.i.1.
-  */
- static RegExpRunStatus
- ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex,
--              MatchPairs* matches, size_t* endIndex)
-+              MatchPairs* matches)
- {
-     /*
-      * WARNING: Despite the presence of spec step comment numbers, this
-      *          algorithm isn't consistent with any ES6 version, draft or
-      *          otherwise.  YOU HAVE BEEN WARNED.
-      */
- 
-     /* Steps 1-2 performed by the caller. */
-@@ -958,17 +1050,17 @@ ExecuteRegExp(JSContext* cx, HandleObjec
-          * However, the spec will change to match our implementation's
-          * behavior. See https://github.com/tc39/ecma262/issues/128.
-          */
-         if (IsTrailSurrogateWithLeadSurrogate(input, lastIndex))
-             lastIndex--;
-     }
- 
-     /* Steps 3, 11-14, except 12.a.i, 12.c.i.1. */
--    RegExpRunStatus status = ExecuteRegExpImpl(cx, res, &re, input, lastIndex, matches, endIndex);
-+    RegExpRunStatus status = ExecuteRegExpImpl(cx, res, &re, input, lastIndex, matches);
-     if (status == RegExpRunStatus_Error)
-         return RegExpRunStatus_Error;
- 
-     /* Steps 12.a.i, 12.c.i.i, 15 are done by Self-hosted function. */
- 
-     return status;
- }
- 
-@@ -979,28 +1071,29 @@ ExecuteRegExp(JSContext* cx, HandleObjec
- static bool
- RegExpMatcherImpl(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex,
-                   MutableHandleValue rval)
- {
-     /* Execute regular expression and gather matches. */
-     ScopedMatchPairs matches(&cx->tempLifoAlloc());
- 
-     /* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */
--    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches, nullptr);
-+    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches);
-     if (status == RegExpRunStatus_Error)
-         return false;
- 
-     /* Steps 12.a, 12.c. */
-     if (status == RegExpRunStatus_Success_NotFound) {
-         rval.setNull();
-         return true;
-     }
- 
-     /* Steps 16-25 */
--    return CreateRegExpMatchResult(cx, string, matches, rval);
-+    RootedRegExpShared shared(cx, regexp->as<RegExpObject>().getShared());
-+    return CreateRegExpMatchResult(cx, shared, string, matches, rval);
- }
- 
- /*
-  * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-  * steps 3, 9-25, except 12.a.i, 12.c.i.1, 15.
-  */
- bool
- js::RegExpMatcher(JSContext* cx, unsigned argc, Value* vp)
-@@ -1029,18 +1122,21 @@ bool
- js::RegExpMatcherRaw(JSContext* cx, HandleObject regexp, HandleString input,
-                      int32_t lastIndex,
-                      MatchPairs* maybeMatches, MutableHandleValue output)
- {
-     MOZ_ASSERT(lastIndex >= 0);
- 
-     // The MatchPairs will always be passed in, but RegExp execution was
-     // successful only if the pairs have actually been filled in.
--    if (maybeMatches && maybeMatches->pairsRaw()[0] >= 0)
--        return CreateRegExpMatchResult(cx, input, *maybeMatches, output);
-+    if (maybeMatches && maybeMatches->pairsRaw()[0] >= 0) {
-+        RootedRegExpShared shared(cx, regexp->as<RegExpObject>().getShared());
-+        return CreateRegExpMatchResult(cx, shared, input, *maybeMatches, output);
-+    }
-+
-     return RegExpMatcherImpl(cx, regexp, input, lastIndex, output);
- }
- 
- /*
-  * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2
-  * steps 3, 9-25, except 12.a.i, 12.c.i.1, 15.
-  * This code is inlined in CodeGenerator.cpp generateRegExpSearcherStub,
-  * changes to this code need to get reflected in there too.
-@@ -1048,17 +1144,17 @@ js::RegExpMatcherRaw(JSContext* cx, Hand
- static bool
- RegExpSearcherImpl(JSContext* cx, HandleObject regexp, HandleString string, int32_t lastIndex,
-                    int32_t* result)
- {
-     /* Execute regular expression and gather matches. */
-     ScopedMatchPairs matches(&cx->tempLifoAlloc());
- 
-     /* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */
--    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches, nullptr);
-+    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches);
-     if (status == RegExpRunStatus_Error)
-         return false;
- 
-     /* Steps 12.a, 12.c. */
-     if (status == RegExpRunStatus_Success_NotFound) {
-         *result = -1;
-         return true;
-     }
-@@ -1130,47 +1226,46 @@ js::RegExpTester(JSContext* cx, unsigned
- 
-     RootedObject regexp(cx, &args[0].toObject());
-     RootedString string(cx, args[1].toString());
- 
-     int32_t lastIndex;
-     MOZ_ALWAYS_TRUE(ToInt32(cx, args[2], &lastIndex));
- 
-     /* Steps 3, 9-14, except 12.a.i, 12.c.i.1. */
--    size_t endIndex = 0;
--    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, nullptr, &endIndex);
-+    ScopedMatchPairs matches(&cx->tempLifoAlloc());
-+    RegExpRunStatus status = ExecuteRegExp(cx, regexp, string, lastIndex, &matches);
- 
-     if (status == RegExpRunStatus_Error)
-         return false;
- 
-     if (status == RegExpRunStatus_Success) {
--        MOZ_ASSERT(endIndex <= INT32_MAX);
--        args.rval().setInt32(int32_t(endIndex));
-+        int32_t endIndex = matches[0].limit;
-+        args.rval().setInt32(endIndex);
-     } else {
-         args.rval().setInt32(-1);
-     }
-     return true;
- }
- 
- /*
-  * Separate interface for use by IonMonkey.
-  * This code cannot re-enter Ion code.
-  */
- bool
- js::RegExpTesterRaw(JSContext* cx, HandleObject regexp, HandleString input,
-                     int32_t lastIndex, int32_t* endIndex)
- {
-     MOZ_ASSERT(lastIndex >= 0);
- 
--    size_t endIndexTmp = 0;
--    RegExpRunStatus status = ExecuteRegExp(cx, regexp, input, lastIndex, nullptr, &endIndexTmp);
-+    ScopedMatchPairs matches(&cx->tempLifoAlloc());
-+    RegExpRunStatus status = ExecuteRegExp(cx, regexp, input, lastIndex, &matches);
- 
-     if (status == RegExpRunStatus_Success) {
--        MOZ_ASSERT(endIndexTmp <= INT32_MAX);
--        *endIndex = int32_t(endIndexTmp);
-+        *endIndex = matches[0].limit;
-         return true;
-     }
-     if (status == RegExpRunStatus_Success_NotFound) {
-         *endIndex = -1;
-         return true;
-     }
- 
-     return false;
-@@ -1203,37 +1298,46 @@ GetParen(JSLinearString* matched, const 
-     if (capture.isUndefined()) {
-         out->initEmpty(matched);
-         return;
-     }
-     JSLinearString& captureLinear = capture.toString()->asLinear();
-     out->init(&captureLinear, 0, captureLinear.length());
- }
- 
--template <typename CharT>
-+template<typename CharT>
- static bool
--InterpretDollar(JSLinearString* matched, JSLinearString* string, size_t position, size_t tailPos,
--                Handle<CapturesVector> captures, JSLinearString* replacement,
--                const CharT* replacementBegin, const CharT* currentDollar,
-+InterpretDollar(JSLinearString* matched,
-+                JSLinearString* string,
-+                size_t position,
-+                size_t tailPos,
-+                Handle<CapturesVector> captures,
-+                Handle<CapturesVector> namedCaptures,
-+                JSLinearString* replacement,
-+                const CharT* replacementBegin,
-+                const CharT* currentDollar,
-                 const CharT* replacementEnd,
--                JSSubString* out, size_t* skip)
-+                JSSubString* out,
-+                size_t* skip,
-+                uint32_t* currentNamedCapture)
- {
-     MOZ_ASSERT(*currentDollar == '$');
- 
-     /* If there is only a dollar, bail now. */
-     if (currentDollar + 1 >= replacementEnd)
-         return false;
- 
--    /* ES 2016 draft Mar 25, 2016 Table 46. */
-+  // ES 2021 Table 52
-+  // https://tc39.es/ecma262/#table-45 (sic)
-     char16_t c = currentDollar[1];
-     if (JS7_ISDEC(c)) {
-         /* $n, $nn */
-         unsigned num = JS7_UNDEC(c);
-         if (num > captures.length()) {
--            // The result is implementation-defined, do not substitute.
-+            // The result is implementation-defined. Do not substitute.
-             return false;
-         }
- 
-         const CharT* currentChar = currentDollar + 2;
-         if (currentChar < replacementEnd) {
-             c = *currentChar;
-             if (JS7_ISDEC(c)) {
-                 unsigned tmpNum = 10 * num + JS7_UNDEC(c);
-@@ -1242,30 +1346,57 @@ InterpretDollar(JSLinearString* matched,
-                 if (tmpNum <= captures.length()) {
-                     currentChar++;
-                     num = tmpNum;
-                 }
-             }
-         }
- 
-         if (num == 0) {
--            // The result is implementation-defined.
--            // Do not substitute.
-+            // The result is implementation-defined. Do not substitute.
-             return false;
-         }
- 
-         *skip = currentChar - currentDollar;
- 
-         MOZ_ASSERT(num <= captures.length());
- 
-         GetParen(matched, captures[num -1], out);
-         return true;
-     }
- 
--    *skip = 2;
-+  // '$<': Named Captures
-+  if (c == '<') {
-+    // Step 1.
-+    if (namedCaptures.length() == 0) {
-+      return false;
-+    }
-+
-+    // Step 2.b
-+    const CharT* nameStart = currentDollar + 2;
-+    const CharT* nameEnd = js_strchr_limit(nameStart, '>', replacementEnd);
-+
-+    // Step 2.c
-+    if (!nameEnd) {
-+      return false;
-+    }
-+
-+    // Step 2.d
-+    // We precompute named capture replacements in InitNamedCaptures.
-+    // They are stored in the order in which we will need them, so here
-+    // we can just take the next one in the list.
-+    size_t nameLength = nameEnd - nameStart;
-+    *skip = nameLength + 3;  // $<...>
-+
-+    // Steps 2.d.iii-iv
-+    GetParen(matched, namedCaptures[*currentNamedCapture], out);
-+    *currentNamedCapture += 1;
-+    return true;
-+  }
-+
-     switch (c) {
-       default:
-         return false;
-       case '$':
-         out->init(replacement, currentDollar - replacementBegin, 1);
-         break;
-       case '&':
-         out->init(matched, 0, matched->length());
-@@ -1279,38 +1410,58 @@ InterpretDollar(JSLinearString* matched,
-         break;
-       case '`':
-         out->init(string, 0, position);
-         break;
-       case '\'':
-         out->init(string, tailPos, string->length() - tailPos);
-         break;
-     }
-+
-+    *skip = 2;
-     return true;
- }
- 
--template <typename CharT>
-+template<typename CharT>
- static bool
--FindReplaceLengthString(JSContext* cx, HandleLinearString matched, HandleLinearString string,
--                        size_t position, size_t tailPos, Handle<CapturesVector> captures,
--                        HandleLinearString replacement, size_t firstDollarIndex, size_t* sizep)
-+FindReplaceLengthString(JSContext* cx,
-+                        HandleLinearString matched,
-+                        HandleLinearString string,
-+                        size_t position,
-+                        size_t tailPos,
-+                        Handle<CapturesVector> captures,
-+                        Handle<CapturesVector> namedCaptures,
-+                        HandleLinearString replacement,
-+                        size_t firstDollarIndex,
-+                        size_t* sizep)
- {
-     CheckedInt<uint32_t> replen = replacement->length();
- 
-     JS::AutoCheckCannotGC nogc;
-     MOZ_ASSERT(firstDollarIndex < replacement->length());
-     const CharT* replacementBegin = replacement->chars<CharT>(nogc);
-     const CharT* currentDollar = replacementBegin + firstDollarIndex;
-     const CharT* replacementEnd = replacementBegin + replacement->length();
-+    uint32_t currentNamedCapture = 0;
-     do {
-         JSSubString sub;
-         size_t skip;
--        if (InterpretDollar(matched, string, position, tailPos, captures, replacement,
--                            replacementBegin, currentDollar, replacementEnd, &sub, &skip))
--        {
-+        if (InterpretDollar(matched,
-+                            string,
-+                            position,
-+                            tailPos,
-+                            captures,
-+                            namedCaptures,
-+                            replacement,
-+                            replacementBegin,
-+                            currentDollar,
-+                            replacementEnd,
-+                            &sub,
-+                            &skip,
-+                            &currentNamedCapture)) {
-             if (sub.length > skip)
-                 replen += sub.length - skip;
-             else
-                 replen -= skip - sub.length;
-             currentDollar += skip;
-         } else {
-             currentDollar++;
-         }
-@@ -1323,95 +1474,259 @@ FindReplaceLengthString(JSContext* cx, H
-         return false;
-     }
- 
-     *sizep = replen.value();
-     return true;
- }
- 
- static bool
--FindReplaceLength(JSContext* cx, HandleLinearString matched, HandleLinearString string,
--                  size_t position, size_t tailPos, Handle<CapturesVector> captures,
--                  HandleLinearString replacement, size_t firstDollarIndex, size_t* sizep)
-+FindReplaceLength(JSContext* cx,
-+                  HandleLinearString matched,
-+                  HandleLinearString string,
-+                  size_t position,
-+                  size_t tailPos,
-+                  Handle<CapturesVector> captures,
-+                  Handle<CapturesVector> namedCaptures,
-+                  HandleLinearString replacement,
-+                  size_t firstDollarIndex,
-+                  size_t* sizep)
- {
--    return replacement->hasLatin1Chars()
--           ? FindReplaceLengthString<Latin1Char>(cx, matched, string, position, tailPos, captures,
--                                                 replacement, firstDollarIndex, sizep)
--           : FindReplaceLengthString<char16_t>(cx, matched, string, position, tailPos, captures,
--                                               replacement, firstDollarIndex, sizep);
-+    return replacement->hasLatin1Chars() ? FindReplaceLengthString<Latin1Char>(cx,
-+                                                                               matched,
-+                                                                               string,
-+                                                                               position,
-+                                                                               tailPos,
-+                                                                               captures,
-+                                                                               namedCaptures,
-+                                                                               replacement,
-+                                                                               firstDollarIndex,
-+                                                                               sizep)
-+                                         : FindReplaceLengthString<char16_t>(cx,
-+                                                                             matched,
-+                                                                             string,
-+                                                                             position,
-+                                                                             tailPos,
-+                                                                             captures,
-+                                                                             namedCaptures,
-+                                                                             replacement,
-+                                                                             firstDollarIndex,
-+                                                                             sizep);
- }
- 
- /*
-  * Precondition: |sb| already has necessary growth space reserved (as
-  * derived from FindReplaceLength), and has been inflated to TwoByte if
-  * necessary.
-  */
--template <typename CharT>
-+template<typename CharT>
- static void
--DoReplace(HandleLinearString matched, HandleLinearString string,
--          size_t position, size_t tailPos, Handle<CapturesVector> captures,
--          HandleLinearString replacement, size_t firstDollarIndex, StringBuffer &sb)
-+DoReplace(HandleLinearString matched,
-+          HandleLinearString string,
-+          size_t position,
-+          size_t tailPos,
-+          Handle<CapturesVector> captures,
-+          Handle<CapturesVector> namedCaptures,
-+          HandleLinearString replacement,
-+          size_t firstDollarIndex,
-+          StringBuffer& sb)
- {
-     JS::AutoCheckCannotGC nogc;
-     const CharT* replacementBegin = replacement->chars<CharT>(nogc);
-     const CharT* currentChar = replacementBegin;
- 
-     MOZ_ASSERT(firstDollarIndex < replacement->length());
-     const CharT* currentDollar = replacementBegin + firstDollarIndex;
-     const CharT* replacementEnd = replacementBegin + replacement->length();
-+    uint32_t currentNamedCapture = 0;
-     do {
-         /* Move one of the constant portions of the replacement value. */
-         size_t len = currentDollar - currentChar;
-         sb.infallibleAppend(currentChar, len);
-         currentChar = currentDollar;
- 
-         JSSubString sub;
-         size_t skip;
--        if (InterpretDollar(matched, string, position, tailPos, captures, replacement,
--                            replacementBegin, currentDollar, replacementEnd, &sub, &skip))
--        {
-+        if (InterpretDollar(matched,
-+                            string,
-+                            position,
-+                            tailPos,
-+                            captures,
-+                            namedCaptures,
-+                            replacement,
-+                            replacementBegin,
-+                            currentDollar,
-+                            replacementEnd,
-+                            &sub,
-+                            &skip,
-+                            &currentNamedCapture)) {
-             sb.infallibleAppendSubstring(sub.base, sub.offset, sub.length);
-             currentChar += skip;
-             currentDollar += skip;
-         } else {
-             currentDollar++;
-         }
- 
-         currentDollar = js_strchr_limit(currentDollar, '$', replacementEnd);
-     } while (currentDollar);
-     sb.infallibleAppend(currentChar, replacement->length() - (currentChar - replacementBegin));
- }
- 
-+/*
-+ * This function finds the list of named captures of the form
-+ * "$<name>" in a replacement string and converts them into jsids, for
-+ * use in InitNamedReplacements.
-+ */
-+template <typename CharT>
-+static bool CollectNames(JSContext* cx, HandleLinearString replacement,
-+                         size_t firstDollarIndex,
-+                         MutableHandle<GCVector<jsid>> names) {
-+  JS::AutoCheckCannotGC nogc;
-+  MOZ_ASSERT(firstDollarIndex < replacement->length());
-+
-+  const CharT* replacementBegin = replacement->chars<CharT>(nogc);
-+  const CharT* currentDollar = replacementBegin + firstDollarIndex;
-+  const CharT* replacementEnd = replacementBegin + replacement->length();
-+
-+  // https://tc39.es/ecma262/#table-45, "$<" section
-+  while (currentDollar && currentDollar + 1 < replacementEnd) {
-+    if (currentDollar[1] == '<') {
-+      // Step 2.b
-+      const CharT* nameStart = currentDollar + 2;
-+      const CharT* nameEnd = js_strchr_limit(nameStart, '>', replacementEnd);
-+
-+      // Step 2.c
-+      if (!nameEnd) {
-+        return true;
-+      }
-+
-+      // Step 2.d.i
-+      size_t nameLength = nameEnd - nameStart;
-+      JSAtom* atom = AtomizeChars(cx, nameStart, nameLength);
-+      if (!atom || !names.append(AtomToId(atom))) {
-+        return false;
-+      }
-+      currentDollar = nameEnd + 1;
-+    } else {
-+      currentDollar += 2;
-+    }
-+    currentDollar = js_strchr_limit(currentDollar, '$', replacementEnd);
-+  }
-+  return true;
-+}
-+
-+/*
-+ * When replacing named captures, the spec requires us to perform
-+ * `Get(match.groups, name)` for each "$<name>". These `Get`s can be
-+ * script-visible; for example, RegExp can be extended with an `exec`
-+ * method that wraps `groups` in a proxy. To make sure that we do the
-+ * right thing, if a regexp has named captures, we find the named
-+ * capture replacements before beginning the actual replacement.
-+ * This guarantees that we will call GetProperty once and only once for
-+ * each "$<name>" in the replacement string, in the correct order.
-+ *
-+ * This function precomputes the results of step 2 of the '$<' case
-+ * here: https://tc39.es/proposal-regexp-named-groups/#table-45, so
-+ * that when we need to access the nth named capture in InterpretDollar,
-+ * we can just use the nth value stored in namedCaptures.
-+ */
-+static bool InitNamedCaptures(JSContext* cx, HandleLinearString replacement,
-+                              HandleObject groups, size_t firstDollarIndex,
-+                              MutableHandle<CapturesVector> namedCaptures) {
-+  Rooted<GCVector<jsid>> names(cx, GCVector<jsid>(cx));
-+  if (replacement->hasLatin1Chars()) {
-+    if (!CollectNames<Latin1Char>(cx, replacement, firstDollarIndex, &names)) {
-+      return false;
-+    }
-+  } else {
-+    if (!CollectNames<char16_t>(cx, replacement, firstDollarIndex, &names)) {
-+      return false;
-+    }
-+  }
-+
-+  // https://tc39.es/ecma262/#table-45, "$<" section
-+  RootedId id(cx);
-+  RootedValue capture(cx);
-+  for (uint32_t i = 0; i < names.length(); i++) {
-+    // Step 2.d.i
-+    id = names[i];
-+
-+    // Step 2.d.ii
-+    if (!GetProperty(cx, groups, groups, id, &capture)) {
-+      return false;
-+    }
-+
-+    // Step 2.d.iii
-+    if (capture.isUndefined()) {
-+      if (!namedCaptures.append(capture)) {
-+        return false;
-+      }
-+    } else {
-+      // Step 2.d.iv
-+      JSString* str = ToString<CanGC>(cx, capture);
-+      if (!str) {
-+        return false;
-+      }
-+      JSLinearString* linear = str->ensureLinear(cx);
-+      if (!linear) {
-+        return false;
-+      }
-+      if (!namedCaptures.append(StringValue(linear))) {
-+        return false;
-+      }
-+    }
-+  }
-+
-+  return true;
-+}
-+
- static bool
--NeedTwoBytes(HandleLinearString string, HandleLinearString replacement,
--             HandleLinearString matched, Handle<CapturesVector> captures)
-+NeedTwoBytes(HandleLinearString string,
-+             HandleLinearString replacement,
-+             HandleLinearString matched,
-+             Handle<CapturesVector> captures,
-+             Handle<CapturesVector> namedCaptures)
- {
-     if (string->hasTwoByteChars())
-         return true;
-     if (replacement->hasTwoByteChars())
-         return true;
-     if (matched->hasTwoByteChars())
-         return true;
- 
--    for (size_t i = 0, len = captures.length(); i < len; i++) {
--        const Value& capture = captures[i];
-+    for (const Value& capture : captures) {
-         if (capture.isUndefined())
-             continue;
-         if (capture.toString()->hasTwoByteChars())
-             return true;
-     }
- 
-+    for (const Value& capture : namedCaptures) {
-+        if (capture.isUndefined()) {
-+            continue;
-+        }
-+        if (capture.toString()->hasTwoByteChars()) {
-+            return true;
-+        }
-+    }
-+
-     return false;
- }
- 
--/* ES 2016 draft Mar 25, 2016 21.1.3.14.1. */
-+/* ES 2021 21.1.3.17.1 */
-+// https://tc39.es/ecma262/#sec-getsubstitution
- bool
--js::RegExpGetSubstitution(JSContext* cx, HandleArrayObject matchResult, HandleLinearString string,
--                          size_t position, HandleLinearString replacement,
--                          size_t firstDollarIndex, MutableHandleValue rval)
-+js::RegExpGetSubstitution(JSContext* cx,
-+                          HandleArrayObject matchResult,
-+                          HandleLinearString string,
-+                          size_t position,
-+                          HandleLinearString replacement,
-+                          size_t firstDollarIndex,
-+                          HandleValue groups,
-+                          MutableHandleValue rval)
- {
-     MOZ_ASSERT(firstDollarIndex < replacement->length());
- 
-     // Step 1 (skipped).
- 
-     // Step 10 (reordered).
-     uint32_t matchResultLength = matchResult->length();
-     MOZ_ASSERT(matchResultLength > 0);
-@@ -1445,51 +1760,70 @@ js::RegExpGetSubstitution(JSContext* cx,
-         }
- 
-         JSLinearString* captureLinear = capture.toString()->ensureLinear(cx);
-         if (!captureLinear)
-             return false;
-         captures.infallibleAppend(StringValue(captureLinear));
-     }
- 
-+    Rooted<CapturesVector> namedCaptures(cx, CapturesVector(cx));
-+    if (groups.isObject()) {
-+        RootedObject groupsObj(cx, &groups.toObject());
-+        if (!InitNamedCaptures(cx, replacement, groupsObj, firstDollarIndex, &namedCaptures)) {
-+            return false;
-+        }
-+    } else {
-+        MOZ_ASSERT(groups.isUndefined());
-+    }
-+
-     // Step 8 (skipped).
- 
-     // Step 9.
-     CheckedInt<uint32_t> checkedTailPos(0);
-     checkedTailPos += position;
-     checkedTailPos += matchLength;
-     if (!checkedTailPos.isValid()) {
-         ReportAllocationOverflow(cx);
-         return false;
-     }
-     uint32_t tailPos = checkedTailPos.value();
- 
-     // Step 11.
-     size_t reserveLength;
--    if (!FindReplaceLength(cx, matched, string, position, tailPos, captures, replacement,
--                           firstDollarIndex, &reserveLength))
--    {
-+    if (!FindReplaceLength(cx,
-+                           matched,
-+                           string,
-+                           position,
-+                           tailPos,
-+                           captures,
-+                           namedCaptures,
-+                           replacement,
-+                           firstDollarIndex,
-+                           &reserveLength)) {
-         return false;
-     }
- 
-     StringBuffer result(cx);
--    if (NeedTwoBytes(string, replacement, matched, captures)) {
--        if (!result.ensureTwoByteChars())
-+    if (NeedTwoBytes(string, replacement, matched, captures, namedCaptures)) {
-+        if (!result.ensureTwoByteChars()) {
-             return false;
-+        }
-     }
- 
--    if (!result.reserve(reserveLength))
-+    if (!result.reserve(reserveLength)) {
-         return false;
-+    }
- 
-     if (replacement->hasLatin1Chars()) {
-         DoReplace<Latin1Char>(matched, string, position, tailPos, captures,
--                              replacement, firstDollarIndex, result);
-+                              namedCaptures, replacement, firstDollarIndex, result);
-     } else {
-         DoReplace<char16_t>(matched, string, position, tailPos, captures,
--                            replacement, firstDollarIndex, result);
-+                            namedCaptures, replacement, firstDollarIndex, result);
-     }
- 
-     // Step 12.
-     JSString* resultString = result.finishString();
-     if (!resultString)
-         return false;
- 
-     rval.setString(resultString);
-@@ -1614,16 +1948,23 @@ js::RegExpPrototypeOptimizableRaw(JSCont
- 
-     JSNative unicodeGetter;
-     if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().unicode), &unicodeGetter))
-         return false;
- 
-     if (unicodeGetter != regexp_unicode)
-         return false;
- 
-+    JSNative dotAllGetter;
-+    if (!GetOwnNativeGetterPure(cx, proto, NameToId(cx->names().dotAll), &dotAllGetter))
-+        return false;
-+
-+    if (dotAllGetter != regexp_dotAll)
-+        return false;
-+
-     // Check if @@match, @@search, and exec are own data properties,
-     // those values should be tested in selfhosted JS.
-     bool has = false;
-     if (!HasOwnDataPropertyPure(cx, proto, SYMBOL_TO_JSID(cx->wellKnownSymbols().match), &has))
-         return false;
-     if (!has)
-         return false;
- 
-diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h
---- a/js/src/builtin/RegExp.h
-+++ b/js/src/builtin/RegExp.h
-@@ -28,17 +28,20 @@ InitRegExpClass(JSContext* cx, HandleObj
-  */
- MOZ_MUST_USE bool
- ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, Handle<RegExpObject*> reobj,
-                     HandleLinearString input, size_t* lastIndex, bool test,
-                     MutableHandleValue rval);
- 
- /* Translation from MatchPairs to a JS array in regexp_exec()'s output format. */
- MOZ_MUST_USE bool
--CreateRegExpMatchResult(JSContext* cx, HandleString input, const MatchPairs& matches,
-+CreateRegExpMatchResult(JSContext* cx,
-+                        HandleRegExpShared re,
-+                        HandleString input,
-+                        const MatchPairs& matches,
-                         MutableHandleValue rval);
- 
- extern MOZ_MUST_USE bool
- RegExpMatcher(JSContext* cx, unsigned argc, Value* vp);
- 
- extern MOZ_MUST_USE bool
- RegExpMatcherRaw(JSContext* cx, HandleObject regexp, HandleString input,
-                  int32_t lastIndex, MatchPairs* maybeMatches, MutableHandleValue output);
-@@ -95,17 +98,17 @@ extern MOZ_MUST_USE bool
- RegExpInstanceOptimizable(JSContext* cx, unsigned argc, Value* vp);
- 
- extern MOZ_MUST_USE bool
- RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* obj, JSObject* proto);
- 
- extern MOZ_MUST_USE bool
- RegExpGetSubstitution(JSContext* cx, HandleArrayObject matchResult, HandleLinearString string,
-                       size_t position, HandleLinearString replacement, size_t firstDollarIndex,
--                      MutableHandleValue rval);
-+                      HandleValue namedCaptures, MutableHandleValue rval);
- 
- extern MOZ_MUST_USE bool
- GetFirstDollarIndex(JSContext* cx, unsigned argc, Value* vp);
- 
- extern MOZ_MUST_USE bool
- GetFirstDollarIndexRaw(JSContext* cx, JSString* str, int32_t* index);
- 
- extern int32_t
-@@ -124,12 +127,14 @@ regexp_global(JSContext* cx, unsigned ar
- extern MOZ_MUST_USE bool
- regexp_ignoreCase(JSContext* cx, unsigned argc, JS::Value* vp);
- extern MOZ_MUST_USE bool
- regexp_multiline(JSContext* cx, unsigned argc, JS::Value* vp);
- extern MOZ_MUST_USE bool
- regexp_sticky(JSContext* cx, unsigned argc, JS::Value* vp);
- extern MOZ_MUST_USE bool
- regexp_unicode(JSContext* cx, unsigned argc, JS::Value* vp);
-+extern MOZ_MUST_USE bool
-+regexp_dotAll(JSContext* cx, unsigned argc, JS::Value* vp);
- 
- } /* namespace js */
- 
- #endif /* builtin_RegExp_h */
-diff --git a/js/src/builtin/RegExp.js b/js/src/builtin/RegExp.js
---- a/js/src/builtin/RegExp.js
-+++ b/js/src/builtin/RegExp.js
-@@ -1,43 +1,48 @@
- /* This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
--// ES6 draft rev34 (2015/02/20) 21.2.5.3 get RegExp.prototype.flags
-+// ECMAScript 2020 draft (2020/03/12) 21.2.5.4 get RegExp.prototype.flags
-+// https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
- function RegExpFlagsGetter() {
-     // Steps 1-2.
-     var R = this;
-     if (!IsObject(R))
-         ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, R === null ? "null" : typeof R);
- 
-     // Step 3.
-     var result = "";
- 
--    // Steps 4-6.
-+    // Steps 4-5.
-     if (R.global)
-         result += "g";
- 
--    // Steps 7-9.
-+    // Steps 6-7.
-     if (R.ignoreCase)
-         result += "i";
- 
--    // Steps 10-12.
-+    // Steps 8-9.
-     if (R.multiline)
-         result += "m";
- 
--    // Steps 13-15.
-+    // Steps 10-11.
-+    if (R.dotAll)
-+        result += "s";
-+
-+    // Steps 12-13.
-     if (R.unicode)
-          result += "u";
- 
--    // Steps 16-18.
-+    // Steps 14-15.
-     if (R.sticky)
-         result += "y";
- 
--    // Step 19.
-+    // Step 16.
-     return result;
- }
- _SetCanonicalName(RegExpFlagsGetter, "get flags");
- 
- // ES 2017 draft 40edb3a95a475c1b251141ac681b8793129d9a6d 21.2.5.14.
- function RegExpToString()
- {
-     // Step 1.
-@@ -220,16 +225,17 @@ function RegExpGlobalMatchOpt(rx, S, ful
- }
- 
- // Checks if following properties and getters are not modified, and accessing
- // them not observed by content script:
- //   * flags
- //   * global
- //   * ignoreCase
- //   * multiline
-+//   * dotAll
- //   * sticky
- //   * unicode
- //   * exec
- //   * lastIndex
- function IsRegExpMethodOptimizable(rx) {
-     if (!IsRegExpObject(rx))
-         return false;
- 
-@@ -384,148 +390,177 @@ function RegExpReplaceSlowPath(rx, S, le
-         // Step 14.d.
-         var matchLength = matched.length;
- 
-         // Steps 14.e-f.
-         var position = std_Math_max(std_Math_min(ToInteger(result.index), lengthS), 0);
- 
-         var n, capN, replacement;
-         if (functionalReplace || firstDollarIndex !== -1) {
--            // Steps 14.g-j.
-+            // Steps 14.g-k.
-             replacement = RegExpGetComplexReplacement(result, matched, S, position,
-                                                       nCaptures, replaceValue,
-                                                       functionalReplace, firstDollarIndex);
-         } else {
-             // Step 14.g, 14.i, 14.i.iv.
-             // We don't need captures array, but ToString is visible to script.
-             for (n = 1; n <= nCaptures; n++) {
-                 // Step 14.i.i-ii.
-                 capN = result[n];
- 
-                 // Step 14.i.ii.
-                 if (capN !== undefined)
-                     ToString(capN);
-             }
-+            // Step 14.j, 14.l., GetSubstitution Step 11.
-+            // We don't need namedCaptures, but ToObject is visible to script.
-+            var namedCaptures = result.groups;
-+            if (namedCaptures !== undefined)
-+                ToObject(namedCaptures);
-+
-             replacement = replaceValue;
-         }
- 
--        // Step 14.l.
-+        // Step 14.m.
-         if (position >= nextSourcePosition) {
--            // Step 14.l.ii.
-+            // Step 14.m.ii.
-             accumulatedResult += Substring(S, nextSourcePosition,
-                                            position - nextSourcePosition) + replacement;
- 
--            // Step 14.l.iii.
-+            // Step 14.m.iii.
-             nextSourcePosition = position + matchLength;
-         }
-     }
- 
-     // Step 15.
-     if (nextSourcePosition >= lengthS)
-         return accumulatedResult;
- 
-     // Step 16.
-     return accumulatedResult + Substring(S, nextSourcePosition, lengthS - nextSourcePosition);
- }
- 
--// ES 2017 draft rev 03bfda119d060aca4099d2b77cf43f6d4f11cfa2 21.2.5.8
--// steps 14.g-k.
-+// ES 2021 draft 21.2.5.10
-+// https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
-+// steps 14.g-l.
- // Calculates functional/substitution replacement from match result.
- // Used in the following functions:
- //   * RegExpReplaceSlowPath
- function RegExpGetComplexReplacement(result, matched, S, position,
-                                      nCaptures, replaceValue,
-                                      functionalReplace, firstDollarIndex)
- {
-     // Step 14.h.
-     var captures = new_List();
-     var capturesLength = 0;
- 
--    // Step 14.j.i (reordered).
-+    // Step 14.k.i (reordered).
-     _DefineDataProperty(captures, capturesLength++, matched);
- 
-     // Step 14.g, 14.i, 14.i.iv.
-     for (var n = 1; n <= nCaptures; n++) {
-         // Step 14.i.i.
-         var capN = result[n];
- 
-         // Step 14.i.ii.
-         if (capN !== undefined)
-             capN = ToString(capN);
- 
-         // Step 14.i.iii.
-         _DefineDataProperty(captures, capturesLength++, capN);
-     }
- 
-     // Step 14.j.
-+    var namedCaptures = result.groups;
-+
-+    // Step 14.k.
-     if (functionalReplace) {
-         // For `nCaptures` <= 4 case, call `replaceValue` directly, otherwise
-         // use `std_Function_apply` with all arguments stored in `captures`.
--        switch (nCaptures) {
--          case 0:
--            return ToString(replaceValue(SPREAD(captures, 1), position, S));
--          case 1:
--            return ToString(replaceValue(SPREAD(captures, 2), position, S));
--          case 2:
--            return ToString(replaceValue(SPREAD(captures, 3), position, S));
--          case 3:
--            return ToString(replaceValue(SPREAD(captures, 4), position, S));
--          case 4:
--            return ToString(replaceValue(SPREAD(captures, 5), position, S));
--          default:
--            // Steps 14.j.ii-v.
--            _DefineDataProperty(captures, capturesLength++, position);
--            _DefineDataProperty(captures, capturesLength++, S);
--            return ToString(callFunction(std_Function_apply, replaceValue, undefined, captures));
-+        if (namedCaptures === undefined) {
-+            switch (nCaptures) {
-+              case 0:
-+                return ToString(replaceValue(SPREAD(captures, 1), position, S));
-+              case 1:
-+                return ToString(replaceValue(SPREAD(captures, 2), position, S));
-+              case 2:
-+                return ToString(replaceValue(SPREAD(captures, 3), position, S));
-+              case 3:
-+                return ToString(replaceValue(SPREAD(captures, 4), position, S));
-+              case 4:
-+                return ToString(replaceValue(SPREAD(captures, 5), position, S));
-+            }
-         }
-+        // Steps 14.k.ii-v.
-+        _DefineDataProperty(captures, capturesLength++, position);
-+        _DefineDataProperty(captures, capturesLength++, S);
-+        if (namedCaptures !== undefined) {
-+            _DefineDataProperty(captures, capturesLength++, namedCaptures);
-+        }
-+        return ToString(callFunction(std_Function_apply, replaceValue, undefined, captures));
-     }
- 
--    // Steps 14.k.i.
--    return RegExpGetSubstitution(captures, S, position, replaceValue, firstDollarIndex);
-+    // Step 14.l.
-+    if (namedCaptures !== undefined) {
-+        namedCaptures = ToObject(namedCaptures);
-+    }
-+    return RegExpGetSubstitution(captures, S, position, replaceValue, firstDollarIndex,
-+                                 namedCaptures);
- }
- 
--// ES 2017 draft rev 03bfda119d060aca4099d2b77cf43f6d4f11cfa2 21.2.5.8
--// steps 14.g-j.
-+// ES 2021 draft 21.2.5.10
-+// https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
-+// steps 14.g-k.
- // Calculates functional replacement from match result.
- // Used in the following functions:
- //   * RegExpGlobalReplaceOptFunc
- //   * RegExpGlobalReplaceOptElemBase
- //   * RegExpLocalReplaceOptFunc
- function RegExpGetFunctionalReplacement(result, S, position, replaceValue) {
-     // For `nCaptures` <= 4 case, call `replaceValue` directly, otherwise
-     // use `std_Function_apply` with all arguments stored in `captures`.
-     assert(result.length >= 1, "RegExpMatcher doesn't return an empty array");
-     var nCaptures = result.length - 1;
- 
--    switch (nCaptures) {
--      case 0:
--        return ToString(replaceValue(SPREAD(result, 1), position, S));
--      case 1:
--        return ToString(replaceValue(SPREAD(result, 2), position, S));
--      case 2:
--        return ToString(replaceValue(SPREAD(result, 3), position, S));
--      case 3:
--        return ToString(replaceValue(SPREAD(result, 4), position, S));
--      case 4:
--        return ToString(replaceValue(SPREAD(result, 5), position, S));
-+    // Step 14.j (reordered)
-+    var namedCaptures = result.groups;
-+
-+    if (namedCaptures === undefined) {
-+        switch (nCaptures) {
-+          case 0:
-+            return ToString(replaceValue(SPREAD(result, 1), position, S));
-+          case 1:
-+            return ToString(replaceValue(SPREAD(result, 2), position, S));
-+          case 2:
-+            return ToString(replaceValue(SPREAD(result, 3), position, S));
-+          case 3:
-+            return ToString(replaceValue(SPREAD(result, 4), position, S));
-+          case 4:
-+            return ToString(replaceValue(SPREAD(result, 5), position, S));
-+        }
-     }
- 
--    // Steps 14.g-i, 14.j.i-ii.
-+    // Steps 14.g-i, 14.k.i-ii.
-     var captures = new_List();
-     for (var n = 0; n <= nCaptures; n++) {
-         assert(typeof result[n] === "string" || result[n] === undefined,
-                "RegExpMatcher returns only strings and undefined");
-         _DefineDataProperty(captures, n, result[n]);
-     }
- 
--    // Step 14.j.iii.
-+    // Step 14.k.iii.
-     _DefineDataProperty(captures, nCaptures + 1, position);
-     _DefineDataProperty(captures, nCaptures + 2, S);
- 
--    // Steps 14.j.iv-v.
-+    // Step 14.k.iv.
-+    if (namedCaptures !== undefined) {
-+        _DefineDataProperty(captures, nCaptures + 3, namedCaptures);
-+    }
-+
-+    // Steps 14.k.v-vi.
-     return ToString(callFunction(std_Function_apply, replaceValue, undefined, captures));
- }
- 
- // ES 2017 draft rev 03bfda119d060aca4099d2b77cf43f6d4f11cfa2 21.2.5.8
- // steps 8.b-16.
- // Optimized path for @@replace with the following conditions:
- //   * global flag is true
- //   * S is a short string (lengthS < 0x7fff)
-@@ -970,17 +1005,17 @@ function RegExpExec(R, S, forTest) {
-         // Steps 6-7 or ES6 21.2.5.2 steps 3, 6 for optimized case.
-         return RegExpBuiltinExec(R, S, forTest);
-     }
- 
-     // Steps 5.a-b.
-     var result = callContentFunction(exec, R, S);
- 
-     // Step 5.c.
--    if (typeof result !== "object")
-+    if (result !== null && !IsObject(result))
-         ThrowTypeError(JSMSG_EXEC_NOT_OBJORNULL);
- 
-     // Step 5.d.
-     return forTest ? result !== null : result;
- }
- 
- // ES2017 draft rev 6390c2f1b34b309895d31d8c0512eac8660a0210
- // 21.2.5.2.2 Runtime Semantics: RegExpBuiltinExec ( R, S )
-@@ -1090,8 +1125,240 @@ function RegExpTest(string) {
- }
- 
- // ES 2016 draft Mar 25, 2016 21.2.4.2.
- function RegExpSpecies() {
-     // Step 1.
-     return this;
- }
- _SetCanonicalName(RegExpSpecies, "get [Symbol.species]");
-+
-+function IsRegExpMatchAllOptimizable(rx, C) {
-+    if (!IsRegExpObject(rx))
-+        return false;
-+
-+    var RegExpCtor = GetBuiltinConstructor("RegExp");
-+    if (C !== RegExpCtor)
-+        return false;
-+
-+    var RegExpProto = RegExpCtor.prototype;
-+    return RegExpPrototypeOptimizable(RegExpProto) &&
-+           RegExpInstanceOptimizable(rx, RegExpProto);
-+}
-+
-+// String.prototype.matchAll proposal.
-+//
-+// RegExp.prototype [ @@matchAll ] ( string )
-+function RegExpMatchAll(string) {
-+    // Step 1.
-+    var rx = this;
-+
-+    // Step 2.
-+    if (!IsObject(rx))
-+        ThrowTypeError(JSMSG_NOT_NONNULL_OBJECT, rx === null ? "null" : typeof rx);
-+
-+    // Step 3.
-+    var str = ToString(string);
-+
-+    // Step 4.
-+    var C = SpeciesConstructor(rx, GetBuiltinConstructor("RegExp"));
-+
-+    var source, flags, matcher, lastIndex;
-+    if (IsRegExpMatchAllOptimizable(rx, C)) {
-+        // Step 5, 9-12.
-+        source = UnsafeGetStringFromReservedSlot(rx, REGEXP_SOURCE_SLOT);
-+        flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT);
-+
-+        // Step 6.
-+        matcher = rx;
-+
-+        // Step 7.
-+        lastIndex = ToLength(rx.lastIndex);
-+
-+        // Step 8 (not applicable for the optimized path).
-+    } else {
-+        // Step 5.
-+        source = "";
-+        flags = ToString(rx.flags);
-+
-+        // Step 6.
-+        matcher = new C(rx, flags);
-+
-+        // Steps 7-8.
-+        matcher.lastIndex = ToLength(rx.lastIndex);
-+
-+        // Steps 9-12.
-+        flags = (callFunction(std_String_includes, flags, "g") ? REGEXP_GLOBAL_FLAG : 0);
-+// XXXX                (callFunction(std_String_includes, flags, "u") ? REGEXP_UNICODE_FLAG : 0);
-+
-+        // Take the non-optimized path.
-+        lastIndex = REGEXP_STRING_ITERATOR_LASTINDEX_SLOW;
-+    }
-+
-+    // Step 13.
-+    return CreateRegExpStringIterator(matcher, str, source, flags, lastIndex);
-+}
-+
-+// String.prototype.matchAll proposal.
-+//
-+// CreateRegExpStringIterator ( R, S, global, fullUnicode )
-+function CreateRegExpStringIterator(regexp, string, source, flags, lastIndex) {
-+    // Step 1.
-+    assert(typeof string === "string", "|string| is a string value");
-+
-+    // Steps 2-3.
-+    assert(typeof flags === "number", "|flags| is a number value");
-+
-+    assert(typeof source === "string", "|source| is a string value");
-+    assert(typeof lastIndex === "number", "|lastIndex| is a number value");
-+
-+    // Steps 4-9.
-+    var iterator = NewRegExpStringIterator();
-+    UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_REGEXP_SLOT, regexp);
-+    UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_STRING_SLOT, string);
-+    UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_SOURCE_SLOT, source);
-+    UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_FLAGS_SLOT, flags | 0);
-+    UnsafeSetReservedSlot(iterator, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT, lastIndex);
-+
-+    // Step 10.
-+    return iterator;
-+}
-+
-+function IsRegExpStringIteratorNextOptimizable() {
-+    var RegExpProto = GetBuiltinPrototype("RegExp");
-+    // If RegExpPrototypeOptimizable succeeds, `RegExpProto.exec` is
-+    // guaranteed to be a data property.
-+    return RegExpPrototypeOptimizable(RegExpProto) &&
-+           RegExpProto.exec === RegExp_prototype_Exec;
-+}
-+
-+// String.prototype.matchAll proposal.
-+//
-+// %RegExpStringIteratorPrototype%.next ( )
-+function RegExpStringIteratorNext() {
-+    // Steps 1-3.
-+    if (!IsObject(this) || !GuardToRegExpStringIterator(this)) {
-+        return callFunction(CallRegExpStringIteratorMethodIfWrapped, this,
-+                            "RegExpStringIteratorNext");
-+    }
-+
-+    var result = { value: undefined, done: false };
-+
-+    // Step 4.
-+    var lastIndex = UnsafeGetReservedSlot(this, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT);
-+    if (lastIndex === REGEXP_STRING_ITERATOR_LASTINDEX_DONE) {
-+        result.done = true;
-+        return result;
-+    }
-+
-+    // Step 5.
-+    var regexp = UnsafeGetObjectFromReservedSlot(this, REGEXP_STRING_ITERATOR_REGEXP_SLOT);
-+
-+    // Step 6.
-+    var string = UnsafeGetStringFromReservedSlot(this, REGEXP_STRING_ITERATOR_STRING_SLOT);
-+
-+    // Steps 7-8.
-+    var flags = UnsafeGetInt32FromReservedSlot(this, REGEXP_STRING_ITERATOR_FLAGS_SLOT);
-+    var global = !!(flags & REGEXP_GLOBAL_FLAG);
-+    var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG);
-+
-+    if (lastIndex >= 0) {
-+        assert(IsRegExpObject(regexp), "|regexp| is a RegExp object");
-+
-+        var source = UnsafeGetStringFromReservedSlot(this, REGEXP_STRING_ITERATOR_SOURCE_SLOT);
-+        if (IsRegExpStringIteratorNextOptimizable() &&
-+            UnsafeGetStringFromReservedSlot(regexp, REGEXP_SOURCE_SLOT) === source &&
-+            UnsafeGetInt32FromReservedSlot(regexp, REGEXP_FLAGS_SLOT) === flags)
-+        {
-+            // Step 9 (Inlined RegExpBuiltinExec).
-+            var globalOrSticky = !!(flags & (REGEXP_GLOBAL_FLAG | REGEXP_STICKY_FLAG));
-+            if (!globalOrSticky)
-+                lastIndex = 0;
-+
-+            var match = (lastIndex <= string.length)
-+                        ? RegExpMatcher(regexp, string, lastIndex)
-+                        : null;
-+
-+            // Step 10.
-+            if (match === null) {
-+                // Step 10.a.
-+                UnsafeSetReservedSlot(this, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
-+                                      REGEXP_STRING_ITERATOR_LASTINDEX_DONE);
-+
-+                // Step 10.b.
-+                result.done = true;
-+                return result;
-+            }
-+
-+            // Step 11.a.
-+            if (global) {
-+                // Step 11.a.i.
-+                var matchLength = match[0].length;
-+                lastIndex = match.index + matchLength;
-+
-+                // Step 11.a.ii.
-+                if (matchLength === 0) {
-+                    // Steps 11.a.ii.1-3.
-+                    lastIndex = fullUnicode ? AdvanceStringIndex(string, lastIndex) : lastIndex + 1;
-+                }
-+
-+                UnsafeSetReservedSlot(this, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT, lastIndex);
-+            } else {
-+                // Step 11.b.i.
-+                UnsafeSetReservedSlot(this, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
-+                                      REGEXP_STRING_ITERATOR_LASTINDEX_DONE);
-+            }
-+
-+            // Steps 11.a.iii and 11.b.ii.
-+            result.value = match;
-+            return result;
-+        }
-+
-+        // Reify the RegExp object.
-+        regexp = regexp_construct_raw_flags(source, flags);
-+        regexp.lastIndex = lastIndex;
-+        UnsafeSetReservedSlot(this, REGEXP_STRING_ITERATOR_REGEXP_SLOT, regexp);
-+
-+        // Mark the iterator as no longer optimizable.
-+        UnsafeSetReservedSlot(this, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
-+                              REGEXP_STRING_ITERATOR_LASTINDEX_SLOW);
-+    }
-+
-+    // Step 9.
-+    var match = RegExpExec(regexp, string, false);
-+
-+    // Step 10.
-+    if (match === null) {
-+        // Step 10.a.
-+        UnsafeSetReservedSlot(this, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
-+                              REGEXP_STRING_ITERATOR_LASTINDEX_DONE);
-+
-+        // Step 10.b.
-+        result.done = true;
-+        return result;
-+    }
-+
-+    // Step 11.a.
-+    if (global) {
-+        // Step 11.a.i.
-+        var matchStr = ToString(match[0]);
-+
-+        // Step 11.a.ii.
-+        if (matchStr.length === 0) {
-+            // Step 11.a.ii.1.
-+            var thisIndex = ToLength(regexp.lastIndex);
-+
-+            // Step 11.a.ii.2.
-+            var nextIndex = fullUnicode ? AdvanceStringIndex(string, thisIndex) : thisIndex + 1;
-+
-+            // Step 11.a.ii.3.
-+            regexp.lastIndex = nextIndex;
-+        }
-+    } else {
-+        // Step 11.b.i.
-+        UnsafeSetReservedSlot(this, REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
-+                              REGEXP_STRING_ITERATOR_LASTINDEX_DONE);
-+    }
-+
-+    // Steps 11.a.iii and 11.b.ii.
-+    result.value = match;
-+    return result;
-+}
-diff --git a/js/src/builtin/RegExpGlobalReplaceOpt.h.js b/js/src/builtin/RegExpGlobalReplaceOpt.h.js
---- a/js/src/builtin/RegExpGlobalReplaceOpt.h.js
-+++ b/js/src/builtin/RegExpGlobalReplaceOpt.h.js
-@@ -64,22 +64,29 @@ function FUNC_NAME(rx, S, lengthS, repla
- 
-         // Step 14.d.
-         var matchLength = matched.length | 0;
- 
-         // Steps 14.e-f.
-         var position = result.index | 0;
-         lastIndex = position + matchLength;
- 
--        // Steps g-k.
-+        // Steps g-l.
-         var replacement;
- #if defined(FUNCTIONAL)
-         replacement = RegExpGetFunctionalReplacement(result, S, position, replaceValue);
- #elif defined(SUBSTITUTION)
--        replacement = RegExpGetSubstitution(result, S, position, replaceValue, firstDollarIndex);
-+        // Step l.i
-+        var namedCaptures = result.groups;
-+        if (namedCaptures !== undefined) {
-+            namedCaptures = ToObject(namedCaptures);
-+        }
-+        // Step l.ii
-+        replacement = RegExpGetSubstitution(result, S, position, replaceValue,
-+                                            firstDollarIndex, namedCaptures);
- #elif defined(ELEMBASE)
-         if (IsObject(elemBase)) {
-             var prop = GetStringDataProperty(elemBase, matched);
-             if (prop !== undefined) {
-                 assert(typeof prop === "string",
-                        "GetStringDataProperty should return either string or undefined");
-                 replacement = prop;
-             } else {
-@@ -88,21 +95,21 @@ function FUNC_NAME(rx, S, lengthS, repla
-         }
- 
-         if (!IsObject(elemBase))
-             replacement = RegExpGetFunctionalReplacement(result, S, position, replaceValue);
- #else
-         replacement = replaceValue;
- #endif
- 
--        // Step 14.l.ii.
-+        // Step 14.m.ii.
-         accumulatedResult += Substring(S, nextSourcePosition,
-                                        position - nextSourcePosition) + replacement;
- 
--        // Step 14.l.iii.
-+        // Step 14.m.iii.
-         nextSourcePosition = lastIndex;
- 
-         // Step 11.c.iii.2.
-         if (matchLength === 0) {
-             lastIndex = fullUnicode ? AdvanceStringIndex(S, lastIndex) : lastIndex + 1;
-             if (lastIndex > lengthS)
-                 break;
-             lastIndex |= 0;
-diff --git a/js/src/builtin/RegExpLocalReplaceOpt.h.js b/js/src/builtin/RegExpLocalReplaceOpt.h.js
---- a/js/src/builtin/RegExpLocalReplaceOpt.h.js
-+++ b/js/src/builtin/RegExpLocalReplaceOpt.h.js
-@@ -86,17 +86,17 @@ function FUNC_NAME(rx, S, lengthS, repla
-     var matched = result[0];
- 
-     // Step 14.d.
-     var matchLength = matched.length;
- 
-     // Step 14.e-f.
-     var position = result.index;
- 
--    // Step 14.l.iii (reordered)
-+    // Step 14.m.iii (reordered)
-     // To set rx.lastIndex before RegExpGetFunctionalReplacement.
-     var nextSourcePosition = position + matchLength;
- #else
-     // Steps 14.a-d (skipped).
- 
-     // Step 14.e-f.
-     var position = result & 0x7fff;
- 
-@@ -104,26 +104,33 @@ function FUNC_NAME(rx, S, lengthS, repla
-     var nextSourcePosition = (result >> 15) & 0x7fff;
- #endif
- 
-     // 21.2.5.2.2 RegExpBuiltinExec, step 15.
-     if (globalOrSticky)
-        rx.lastIndex = nextSourcePosition;
- 
-     var replacement;
--    // Steps g-j.
-+    // Steps g-l.
- #if defined(FUNCTIONAL)
-     replacement = RegExpGetFunctionalReplacement(result, S, position, replaceValue);
- #elif defined(SUBSTITUTION)
--    replacement = RegExpGetSubstitution(result, S, position, replaceValue, firstDollarIndex);
-+    // Step l.i
-+    var namedCaptures = result.groups;
-+    if (namedCaptures !== undefined) {
-+        namedCaptures = ToObject(namedCaptures);
-+    }
-+    // Step l.ii
-+    replacement = RegExpGetSubstitution(result, S, position, replaceValue, firstDollarIndex,
-+                                        namedCaptures);
- #else
-     replacement = replaceValue;
- #endif
- 
--    // Step 14.l.ii.
-+    // Step 14.m.ii.
-     var accumulatedResult = Substring(S, 0, position) + replacement;
- 
-     // Step 15.
-     if (nextSourcePosition >= lengthS)
-         return accumulatedResult;
- 
-     // Step 16.
-     return accumulatedResult + Substring(S, nextSourcePosition, lengthS - nextSourcePosition);
-diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h
---- a/js/src/builtin/SelfHostingDefines.h
-+++ b/js/src/builtin/SelfHostingDefines.h
-@@ -87,16 +87,26 @@
- #define REGEXP_SOURCE_SLOT 1
- #define REGEXP_FLAGS_SLOT 2
- 
- #define REGEXP_IGNORECASE_FLAG  0x01
- #define REGEXP_GLOBAL_FLAG      0x02
- #define REGEXP_MULTILINE_FLAG   0x04
- #define REGEXP_STICKY_FLAG      0x08
- #define REGEXP_UNICODE_FLAG     0x10
-+#define REGEXP_DOTALL_FLAG      0x20
-+
-+#define REGEXP_STRING_ITERATOR_REGEXP_SLOT 0
-+#define REGEXP_STRING_ITERATOR_STRING_SLOT 1
-+#define REGEXP_STRING_ITERATOR_SOURCE_SLOT 2
-+#define REGEXP_STRING_ITERATOR_FLAGS_SLOT 3
-+#define REGEXP_STRING_ITERATOR_LASTINDEX_SLOT 4
-+
-+#define REGEXP_STRING_ITERATOR_LASTINDEX_DONE -1
-+#define REGEXP_STRING_ITERATOR_LASTINDEX_SLOW -2
- 
- #define MODULE_OBJECT_ENVIRONMENT_SLOT        1
- #define MODULE_OBJECT_STATUS_SLOT             3
- #define MODULE_OBJECT_EVALUATION_ERROR_SLOT   4
- #define MODULE_OBJECT_DFS_INDEX_SLOT          13
- #define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 14
- 
- #define MODULE_STATUS_UNINSTANTIATED  0
-diff --git a/js/src/builtin/String.js b/js/src/builtin/String.js
---- a/js/src/builtin/String.js
-+++ b/js/src/builtin/String.js
-@@ -57,16 +57,59 @@ function String_match(regexp) {
- 
- function String_generic_match(thisValue, regexp) {
-     WarnDeprecatedStringMethod(STRING_GENERICS_MATCH, "match");
-     if (thisValue === undefined)
-         ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "String.match");
-     return callFunction(String_match, thisValue, regexp);
- }
- 
-+// String.prototype.matchAll proposal.
-+//
-+// String.prototype.matchAll ( regexp )
-+function String_matchAll(regexp) {
-+    // Step 1.
-+    RequireObjectCoercible(this);
-+
-+    // Step 2.
-+    if (regexp !== undefined && regexp !== null) {
-+        // Steps 2.a-b.
-+        if (IsRegExp(regexp)) {
-+            // Step 2.b.i.
-+            var flags = regexp.flags;
-+
-+            // Step 2.b.ii.
-+            if (flags === undefined || flags === null) {
-+                ThrowTypeError(JSMSG_FLAGS_UNDEFINED_OR_NULL);
-+            }
-+
-+            // Step 2.b.iii.
-+            if (!callFunction(std_String_includes, ToString(flags), "g")) {
-+                ThrowTypeError(JSMSG_REQUIRES_GLOBAL_REGEXP, "matchAll");
-+            }
-+        }
-+
-+        // Step 2.c.
-+        var matcher = GetMethod(regexp, std_matchAll);
-+
-+        // Step 2.d.
-+        if (matcher !== undefined)
-+            return callContentFunction(matcher, regexp, this);
-+    }
-+
-+    // Step 3.
-+    var string = ToString(this);
-+
-+    // Step 4.
-+    var rx = RegExpCreate(regexp, "g");
-+
-+    // Step 5.
-+    return callContentFunction(GetMethod(rx, std_matchAll), rx, string);
-+}
-+
- /**
-  * A helper function implementing the logic for both String.prototype.padStart
-  * and String.prototype.padEnd as described in ES7 Draft March 29, 2016
-  */
- function String_pad(maxLength, fillString, padEnd = false) {
- 
-     // Steps 1-2.
-     RequireObjectCoercible(this);
-diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
---- a/js/src/builtin/TestingFunctions.cpp
-+++ b/js/src/builtin/TestingFunctions.cpp
-@@ -23,24 +23,22 @@
- #include "jsiter.h"
- #include "jsprf.h"
- #include "jswrapper.h"
- 
- #include "builtin/Promise.h"
- #include "builtin/SelfHostingDefines.h"
- #ifdef DEBUG
- #include "frontend/TokenStream.h"
--#include "irregexp/RegExpAST.h"
--#include "irregexp/RegExpEngine.h"
--#include "irregexp/RegExpParser.h"
- #endif
- #include "jit/BaselineJIT.h"
- #include "jit/InlinableNatives.h"
- #include "js/Debug.h"
- #include "js/HashTable.h"
-+#include "js/RegExpFlags.h"
- #include "js/StructuredClone.h"
- #include "js/UbiNode.h"
- #include "js/UbiNodeBreadthFirst.h"
- #include "js/UbiNodeShortestPaths.h"
- #include "js/UniquePtr.h"
- #include "js/Vector.h"
- #include "vm/AsyncFunction.h"
- #include "vm/AsyncIteration.h"
-@@ -68,16 +66,19 @@
- #include "vm/JSObject-inl.h"
- #include "vm/NativeObject-inl.h"
- 
- using namespace js;
- 
- using mozilla::ArrayLength;
- using mozilla::Move;
- 
-+using JS::RegExpFlag;
-+using JS::RegExpFlags;
-+
- // If fuzzingSafe is set, remove functionality that could cause problems with
- // fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE.
- mozilla::Atomic<bool> fuzzingSafe(false);
- 
- // If disableOOMFunctions is set, disable functionality that causes artificial
- // OOM conditions.
- static mozilla::Atomic<bool> disableOOMFunctions(false);
- 
-@@ -4383,382 +4384,16 @@ GetModuleEnvironmentValue(JSContext* cx,
-     if (args.rval().isMagic(JS_UNINITIALIZED_LEXICAL)) {
-         ReportRuntimeLexicalError(cx, JSMSG_UNINITIALIZED_LEXICAL, id);
-         return false;
-     }
- 
-     return true;
- }
- 
--#ifdef DEBUG
--static const char*
--AssertionTypeToString(irregexp::RegExpAssertion::AssertionType type)
--{
--    switch (type) {
--      case irregexp::RegExpAssertion::START_OF_LINE:
--        return "START_OF_LINE";
--      case irregexp::RegExpAssertion::START_OF_INPUT:
--        return "START_OF_INPUT";
--      case irregexp::RegExpAssertion::END_OF_LINE:
--        return "END_OF_LINE";
--      case irregexp::RegExpAssertion::END_OF_INPUT:
--        return "END_OF_INPUT";
--      case irregexp::RegExpAssertion::BOUNDARY:
--        return "BOUNDARY";
--      case irregexp::RegExpAssertion::NON_BOUNDARY:
--        return "NON_BOUNDARY";
--      case irregexp::RegExpAssertion::NOT_AFTER_LEAD_SURROGATE:
--        return "NOT_AFTER_LEAD_SURROGATE";
--      case irregexp::RegExpAssertion::NOT_IN_SURROGATE_PAIR:
--        return "NOT_IN_SURROGATE_PAIR";
--    }
--    MOZ_CRASH("unexpected AssertionType");
--}
--
--static JSObject*
--ConvertRegExpTreeToObject(JSContext* cx, irregexp::RegExpTree* tree)
--{
--    RootedObject obj(cx, JS_NewPlainObject(cx));
--    if (!obj)
--        return nullptr;
--
--    auto IntProp = [](JSContext* cx, HandleObject obj,
--                      const char* name, int32_t value) {
--        RootedValue val(cx, Int32Value(value));
--        return JS_SetProperty(cx, obj, name, val);
--    };
--
--    auto BooleanProp = [](JSContext* cx, HandleObject obj,
--                          const char* name, bool value) {
--        RootedValue val(cx, BooleanValue(value));
--        return JS_SetProperty(cx, obj, name, val);
--    };
--
--    auto StringProp = [](JSContext* cx, HandleObject obj,
--                         const char* name, const char* value) {
--        RootedString valueStr(cx, JS_NewStringCopyZ(cx, value));
--        if (!valueStr)
--            return false;
--
--        RootedValue val(cx, StringValue(valueStr));
--        return JS_SetProperty(cx, obj, name, val);
--    };
--
--    auto ObjectProp = [](JSContext* cx, HandleObject obj,
--                         const char* name, HandleObject value) {
--        RootedValue val(cx, ObjectValue(*value));
--        return JS_SetProperty(cx, obj, name, val);
--    };
--
--    auto CharVectorProp = [](JSContext* cx, HandleObject obj,
--                             const char* name, const irregexp::CharacterVector& data) {
--        RootedString valueStr(cx, JS_NewUCStringCopyN(cx, data.begin(), data.length()));
--        if (!valueStr)
--            return false;
--
--        RootedValue val(cx, StringValue(valueStr));
--        return JS_SetProperty(cx, obj, name, val);
--    };
--
--    auto TreeProp = [&ObjectProp](JSContext* cx, HandleObject obj,
--                                  const char* name, irregexp::RegExpTree* tree) {
--        RootedObject treeObj(cx, ConvertRegExpTreeToObject(cx, tree));
--        if (!treeObj)
--            return false;
--        return ObjectProp(cx, obj, name, treeObj);
--    };
--
--    auto TreeVectorProp = [&ObjectProp](JSContext* cx, HandleObject obj,
--                                        const char* name,
--                                        const irregexp::RegExpTreeVector& nodes) {
--        size_t len = nodes.length();
--        RootedObject array(cx, JS_NewArrayObject(cx, len));
--        if (!array)
--            return false;
--
--        for (size_t i = 0; i < len; i++) {
--            RootedObject child(cx, ConvertRegExpTreeToObject(cx, nodes[i]));
--            if (!child)
--                return false;
--
--            RootedValue childVal(cx, ObjectValue(*child));
--            if (!JS_SetElement(cx, array, i, childVal))
--                return false;
--        }
--        return ObjectProp(cx, obj, name, array);
--    };
--
--    auto CharRangesProp = [&ObjectProp](JSContext* cx, HandleObject obj,
--                                        const char* name,
--                                        const irregexp::CharacterRangeVector& ranges) {
--        size_t len = ranges.length();
--        RootedObject array(cx, JS_NewArrayObject(cx, len));
--        if (!array)
--            return false;
--
--        for (size_t i = 0; i < len; i++) {
--            const irregexp::CharacterRange& range = ranges[i];
--            RootedObject rangeObj(cx, JS_NewPlainObject(cx));
--            if (!rangeObj)
--                return false;
--
--            auto CharProp = [](JSContext* cx, HandleObject obj,
--                               const char* name, char16_t c) {
--                RootedString valueStr(cx, JS_NewUCStringCopyN(cx, &c, 1));
--                if (!valueStr)
--                    return false;
--                RootedValue val(cx, StringValue(valueStr));
--                return JS_SetProperty(cx, obj, name, val);
--            };
--
--            if (!CharProp(cx, rangeObj, "from", range.from()))
--                return false;
--            if (!CharProp(cx, rangeObj, "to", range.to()))
--                return false;
--
--            RootedValue rangeVal(cx, ObjectValue(*rangeObj));
--            if (!JS_SetElement(cx, array, i, rangeVal))
--                return false;
--        }
--        return ObjectProp(cx, obj, name, array);
--    };
--
--    auto ElemProp = [&ObjectProp](JSContext* cx, HandleObject obj,
--                                  const char* name, const irregexp::TextElementVector& elements) {
--        size_t len = elements.length();
--        RootedObject array(cx, JS_NewArrayObject(cx, len));
--        if (!array)
--            return false;
--
--        for (size_t i = 0; i < len; i++) {
--            const irregexp::TextElement& element = elements[i];
--            RootedObject elemTree(cx, ConvertRegExpTreeToObject(cx, element.tree()));
--            if (!elemTree)
--                return false;
--
--            RootedValue elemTreeVal(cx, ObjectValue(*elemTree));
--            if (!JS_SetElement(cx, array, i, elemTreeVal))
--                return false;
--        }
--        return ObjectProp(cx, obj, name, array);
--    };
--
--    if (tree->IsDisjunction()) {
--        if (!StringProp(cx, obj, "type", "Disjunction"))
--            return nullptr;
--        irregexp::RegExpDisjunction* t = tree->AsDisjunction();
--        if (!TreeVectorProp(cx, obj, "alternatives", t->alternatives()))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsAlternative()) {
--        if (!StringProp(cx, obj, "type", "Alternative"))
--            return nullptr;
--        irregexp::RegExpAlternative* t = tree->AsAlternative();
--        if (!TreeVectorProp(cx, obj, "nodes", t->nodes()))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsAssertion()) {
--        if (!StringProp(cx, obj, "type", "Assertion"))
--            return nullptr;
--        irregexp::RegExpAssertion* t = tree->AsAssertion();
--        if (!StringProp(cx, obj, "assertion_type", AssertionTypeToString(t->assertion_type())))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsCharacterClass()) {
--        if (!StringProp(cx, obj, "type", "CharacterClass"))
--            return nullptr;
--        irregexp::RegExpCharacterClass* t = tree->AsCharacterClass();
--        if (!BooleanProp(cx, obj, "is_negated", t->is_negated()))
--            return nullptr;
--        LifoAlloc* alloc = &cx->tempLifoAlloc();
--        if (!CharRangesProp(cx, obj, "ranges", t->ranges(alloc)))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsAtom()) {
--        if (!StringProp(cx, obj, "type", "Atom"))
--            return nullptr;
--        irregexp::RegExpAtom* t = tree->AsAtom();
--        if (!CharVectorProp(cx, obj, "data", t->data()))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsText()) {
--        if (!StringProp(cx, obj, "type", "Text"))
--            return nullptr;
--        irregexp::RegExpText* t = tree->AsText();
--        if (!ElemProp(cx, obj, "elements", t->elements()))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsQuantifier()) {
--        if (!StringProp(cx, obj, "type", "Quantifier"))
--            return nullptr;
--        irregexp::RegExpQuantifier* t = tree->AsQuantifier();
--        if (!IntProp(cx, obj, "min", t->min()))
--            return nullptr;
--        if (!IntProp(cx, obj, "max", t->max()))
--            return nullptr;
--        if (!StringProp(cx, obj, "quantifier_type",
--                        t->is_possessive() ? "POSSESSIVE"
--                        : t->is_non_greedy() ? "NON_GREEDY"
--                        : "GREEDY"))
--            return nullptr;
--        if (!TreeProp(cx, obj, "body", t->body()))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsCapture()) {
--        if (!StringProp(cx, obj, "type", "Capture"))
--            return nullptr;
--        irregexp::RegExpCapture* t = tree->AsCapture();
--        if (!IntProp(cx, obj, "index", t->index()))
--            return nullptr;
--        if (!TreeProp(cx, obj, "body", t->body()))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsLookahead()) {
--        if (!StringProp(cx, obj, "type", "Lookahead"))
--            return nullptr;
--        irregexp::RegExpLookahead* t = tree->AsLookahead();
--        if (!BooleanProp(cx, obj, "is_positive", t->is_positive()))
--            return nullptr;
--        if (!TreeProp(cx, obj, "body", t->body()))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsBackReference()) {
--        if (!StringProp(cx, obj, "type", "BackReference"))
--            return nullptr;
--        irregexp::RegExpBackReference* t = tree->AsBackReference();
--        if (!IntProp(cx, obj, "index", t->index()))
--            return nullptr;
--        return obj;
--    }
--    if (tree->IsEmpty()) {
--        if (!StringProp(cx, obj, "type", "Empty"))
--            return nullptr;
--        return obj;
--    }
--
--    MOZ_CRASH("unexpected RegExpTree type");
--}
--
--static bool
--ParseRegExp(JSContext* cx, unsigned argc, Value* vp)
--{
--    CallArgs args = CallArgsFromVp(argc, vp);
--    RootedObject callee(cx, &args.callee());
--
--    if (args.length() == 0) {
--        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
--        return false;
--    }
--
--    if (!args[0].isString()) {
--        ReportUsageErrorASCII(cx, callee, "First argument must be a String");
--        return false;
--    }
--
--    RegExpFlag flags = RegExpFlag(0);
--    if (!args.get(1).isUndefined()) {
--        if (!args.get(1).isString()) {
--            ReportUsageErrorASCII(cx, callee, "Second argument, if present, must be a String");
--            return false;
--        }
--        RootedString flagStr(cx, args[1].toString());
--        if (!ParseRegExpFlags(cx, flagStr, &flags))
--            return false;
--    }
--
--    bool match_only = false;
--    if (!args.get(2).isUndefined()) {
--        if (!args.get(2).isBoolean()) {
--            ReportUsageErrorASCII(cx, callee, "Third argument, if present, must be a Boolean");
--            return false;
--        }
--        match_only = args[2].toBoolean();
--    }
--
--    RootedAtom pattern(cx, AtomizeString(cx, args[0].toString()));
--    if (!pattern)
--        return false;
--
--    CompileOptions options(cx);
--    frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
--
--    irregexp::RegExpCompileData data;
--    if (!irregexp::ParsePattern(dummyTokenStream, cx->tempLifoAlloc(), pattern,
--                                flags & MultilineFlag, match_only,
--                                flags & UnicodeFlag, flags & IgnoreCaseFlag,
--                                flags & GlobalFlag, flags & StickyFlag,
--                                &data))
--    {
--        return false;
--    }
--
--    RootedObject obj(cx, ConvertRegExpTreeToObject(cx, data.tree));
--    if (!obj)
--        return false;
--
--    args.rval().setObject(*obj);
--    return true;
--}
--
--static bool
--DisRegExp(JSContext* cx, unsigned argc, Value* vp)
--{
--    CallArgs args = CallArgsFromVp(argc, vp);
--    RootedObject callee(cx, &args.callee());
--
--    if (args.length() == 0) {
--        ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
--        return false;
--    }
--
--    if (!args[0].isObject() || !args[0].toObject().is<RegExpObject>()) {
--        ReportUsageErrorASCII(cx, callee, "First argument must be a RegExp");
--        return false;
--    }
--
--    Rooted<RegExpObject*> reobj(cx, &args[0].toObject().as<RegExpObject>());
--
--    bool match_only = false;
--    if (!args.get(1).isUndefined()) {
--        if (!args.get(1).isBoolean()) {
--            ReportUsageErrorASCII(cx, callee, "Second argument, if present, must be a Boolean");
--            return false;
--        }
--        match_only = args[1].toBoolean();
--    }
--
--    RootedLinearString input(cx, cx->runtime()->emptyString);
--    if (!args.get(2).isUndefined()) {
--        if (!args.get(2).isString()) {
--            ReportUsageErrorASCII(cx, callee, "Third argument, if present, must be a String");
--            return false;
--        }
--        RootedString inputStr(cx, args[2].toString());
--        input = inputStr->ensureLinear(cx);
--        if (!input)
--            return false;
--    }
--
--    if (!RegExpObject::dumpBytecode(cx, reobj, match_only, input))
--        return false;
--
--    args.rval().setUndefined();
--    return true;
--}
--#endif // DEBUG
--
- static bool
- GetTimeZone(JSContext* cx, unsigned argc, Value* vp)
- {
-     CallArgs args = CallArgsFromVp(argc, vp);
-     RootedObject callee(cx, &args.callee());
- 
-     if (args.length() != 0) {
-         ReportUsageErrorASCII(cx, callee, "Wrong number of arguments");
-@@ -5791,26 +5426,16 @@ gc::ZealModeHelpText),
- "    baselineCompile();  for (var i=0; i<1; i++) {} ...\n"
- "  The interpreter will enter the new jitcode at the loop header unless\n"
- "  baselineCompile returned a string or threw an error.\n"),
- 
-     JS_FS_HELP_END
- };
- 
- static const JSFunctionSpecWithHelp FuzzingUnsafeTestingFunctions[] = {
--#ifdef DEBUG
--    JS_FN_HELP("parseRegExp", ParseRegExp, 3, 0,
--"parseRegExp(pattern[, flags[, match_only])",
--"  Parses a RegExp pattern and returns a tree, potentially throwing."),
--
--    JS_FN_HELP("disRegExp", DisRegExp, 3, 0,
--"disRegExp(regexp[, match_only[, input]])",
--"  Dumps RegExp bytecode."),
--#endif
--
-     JS_FN_HELP("getErrorNotes", GetErrorNotes, 1, 0,
- "getErrorNotes(error)",
- "  Returns an array of error notes."),
- 
-     JS_FN_HELP("setTimeZone", SetTimeZone, 1, 0,
- "setTimeZone(tzname)",
- "  Set the 'TZ' environment variable to the given time zone and applies the new time zone.\n"
- "  An empty string or undefined resets the time zone to its default value.\n"
-diff --git a/js/src/devtools/rootAnalysis/annotations.js b/js/src/devtools/rootAnalysis/annotations.js
---- a/js/src/devtools/rootAnalysis/annotations.js
-+++ b/js/src/devtools/rootAnalysis/annotations.js
-@@ -243,16 +243,19 @@ var ignoreFunctions = {
- 
-     // The big hammers.
-     "PR_GetCurrentThread" : true,
-     "calloc" : true,
- 
-     "uint8 nsContentUtils::IsExpandedPrincipal(nsIPrincipal*)" : true,
- 
-     "void mozilla::AutoProfilerLabel::~AutoProfilerLabel(int32)" : true,
-+
-+    // Calls MergeSort
-+    "uint8 v8::internal::RegExpDisjunction::SortConsecutiveAtoms(v8::internal::RegExpCompiler*)": true,
- };
- 
- function extraGCFunctions() {
-     return ["ffi_call"];
- }
- 
- function extraGCFunctions() {
-     return ["ffi_call"].filter(f => f in readableNames);
-@@ -269,28 +272,35 @@ function isHeapSnapshotMockClass(name)
-            name.match(/\bMockDeserializedNode\b/);
- }
- 
- function isGTest(name)
- {
-     return name.match(/\btesting::/);
- }
- 
-+function isICU(name)
-+{
-+    return name.match(/\bicu_\d+::/) ||
-+           name.match(/u(prv_malloc|prv_realloc|prv_free|case_toFullLower)_\d+/)
-+}
-+
- function ignoreGCFunction(mangled)
- {
-     assert(mangled in readableNames, mangled + " not in readableNames");
-     var fun = readableNames[mangled][0];
- 
-     if (fun in ignoreFunctions)
-         return true;
- 
-     // The protobuf library, and [de]serialization code generated by the
-     // protobuf compiler, uses a _ton_ of function pointers but they are all
--    // internal. Easiest to just ignore that mess here.
--    if (isProtobuf(fun))
-+    // internal. The same is true for ICU. Easiest to just ignore that mess
-+    // here.
-+    if (isProtobuf(fun) || isICU(fun))
-         return true;
- 
-     // Ignore anything that goes through heap snapshot GTests or mocked classes
-     // used in heap snapshot GTests. GTest and GMock expose a lot of virtual
-     // methods and function pointers that could potentially GC after an
-     // assertion has already failed (depending on user-provided code), but don't
-     // exhibit that behavior currently. For non-test code, we have dynamic and
-     // static checks that ensure we don't GC. However, for test code we opt out
-diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
---- a/js/src/frontend/Parser.cpp
-+++ b/js/src/frontend/Parser.cpp
-@@ -32,17 +32,18 @@
- #include "jsopcode.h"
- #include "jstypes.h"
- 
- #include "builtin/ModuleObject.h"
- #include "builtin/SelfHostingDefines.h"
- #include "frontend/BytecodeCompiler.h"
- #include "frontend/FoldConstants.h"
- #include "frontend/TokenStream.h"
--#include "irregexp/RegExpParser.h"
-+#include "irregexp/RegExpAPI.h"
-+#include "js/RegExpFlags.h"
- #include "vm/JSAtom.h"
- #include "vm/JSContext.h"
- #include "vm/JSFunction.h"
- #include "vm/JSScript.h"
- #include "vm/RegExpObject.h"
- #include "wasm/AsmJS.h"
- 
- #include "frontend/ParseContext-inl.h"
-@@ -59,16 +60,17 @@ using mozilla::Forward;
- using mozilla::Maybe;
- using mozilla::Move;
- using mozilla::Nothing;
- using mozilla::PodZero;
- using mozilla::PointerRangeSize;
- using mozilla::Some;
- 
- using JS::AutoGCRooter;
-+using JS::RegExpFlags;
- 
- namespace js {
- namespace frontend {
- 
- using DeclaredNamePtr = ParseContext::Scope::DeclaredNamePtr;
- using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr;
- using BindingIter = ParseContext::Scope::BindingIter;
- using UsedNamePtr = UsedNameTracker::UsedNameMap::Ptr;
-@@ -9293,17 +9295,17 @@ Parser<FullParseHandler, CharT>::newRegE
-     MOZ_ASSERT(!options().selfHostingMode);
- 
-     static_assert(mozilla::IsSame<CharT, char16_t>::value,
-                   "code below will need changing for UTF-8 handling");
- 
-     // Create the regexp and check its syntax.
-     const CharT* chars = tokenStream.getTokenbuf().begin();
-     size_t length = tokenStream.getTokenbuf().length();
--    RegExpFlag flags = anyChars.currentToken().regExpFlags();
-+    RegExpFlags flags = anyChars.currentToken().regExpFlags();
- 
-     Rooted<RegExpObject*> reobj(context);
-     reobj = RegExpObject::create(context, chars, length, flags, anyChars, alloc, TenuredObject);
-     if (!reobj)
-         return null();
- 
-     return handler.newRegExp(reobj, pos(), *this);
- }
-@@ -9315,22 +9317,22 @@ Parser<SyntaxParseHandler, CharT>::newRe
-     MOZ_ASSERT(!options().selfHostingMode);
- 
-     static_assert(mozilla::IsSame<CharT, char16_t>::value,
-                   "code below will need changing for UTF-8 handling");
- 
-     // Only check the regexp's syntax, but don't create a regexp object.
-     const CharT* chars = tokenStream.getTokenbuf().begin();
-     size_t length = tokenStream.getTokenbuf().length();
--    RegExpFlag flags = anyChars.currentToken().regExpFlags();
-+    RegExpFlags flags = anyChars.currentToken().regExpFlags();
- 
-     mozilla::Range<const CharT> source(chars, length);
--    if (!js::irregexp::ParsePatternSyntax(anyChars, alloc, source, flags & UnicodeFlag))
--        return null();
--
-+    if (!irregexp::CheckPatternSyntax(context, anyChars, source, flags)) {
-+      return null();
-+    }
-     return handler.newRegExp(SyntaxParseHandler::NodeGeneric, pos(), *this);
- }
- 
- template <class ParseHandler, typename CharT>
- typename ParseHandler::Node
- GeneralParser<ParseHandler, CharT>::newRegExp()
- {
-     return asFinalParser()->newRegExp();
-diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp
---- a/js/src/frontend/TokenStream.cpp
-+++ b/js/src/frontend/TokenStream.cpp
-@@ -20,31 +20,35 @@
- 
- #include "jsexn.h"
- #include "jsnum.h"
- 
- #include "frontend/BytecodeCompiler.h"
- #include "frontend/Parser.h"
- #include "frontend/ReservedWords.h"
- #include "js/CharacterEncoding.h"
-+#include "js/RegExpFlags.h"  // JS::RegExpFlags
- #include "js/UniquePtr.h"
- #include "vm/HelperThreads.h"
- #include "vm/JSAtom.h"
- #include "vm/JSCompartment.h"
- #include "vm/JSContext.h"
- #include "vm/StringBuffer.h"
- #include "vm/Unicode.h"
- 
- using mozilla::ArrayLength;
- using mozilla::MakeScopeExit;
- using mozilla::Maybe;
- using mozilla::PodAssign;
- using mozilla::PodCopy;
- using mozilla::PodZero;
- 
-+using JS::RegExpFlag;
-+using JS::RegExpFlags;
-+
- struct ReservedWordInfo
- {
-     const char* chars;         // C string with reserved word text
-     js::frontend::TokenKind tokentype;
- };
- 
- static const ReservedWordInfo reservedWords[] = {
- #define RESERVED_WORD_INFO(word, name, type) \
-@@ -2025,31 +2029,33 @@ TokenStreamSpecific<CharT, AnyCharsAcces
-                     ungetChar(c);
-                     reportError(JSMSG_UNTERMINATED_REGEXP);
-                     goto error;
-                 }
-                 if (!tokenbuf.append(c))
-                     goto error;
-             } while (true);
- 
--            RegExpFlag reflags = NoFlags;
-+            RegExpFlags reflags = RegExpFlag::NoFlags;
-             unsigned length = tokenbuf.length() + 1;
-             while (true) {
-                 if (!peekChar(&c))
-                     goto error;
--                if (c == 'g' && !(reflags & GlobalFlag))
--                    reflags = RegExpFlag(reflags | GlobalFlag);
--                else if (c == 'i' && !(reflags & IgnoreCaseFlag))
--                    reflags = RegExpFlag(reflags | IgnoreCaseFlag);
--                else if (c == 'm' && !(reflags & MultilineFlag))
--                    reflags = RegExpFlag(reflags | MultilineFlag);
--                else if (c == 'y' && !(reflags & StickyFlag))
--                    reflags = RegExpFlag(reflags | StickyFlag);
--                else if (c == 'u' && !(reflags & UnicodeFlag))
--                    reflags = RegExpFlag(reflags | UnicodeFlag);
-+                if (c == 'g' && !(reflags & RegExpFlag::Global))
-+                    reflags = RegExpFlags(reflags | RegExpFlag::Global);
-+                else if (c == 'i' && !(reflags & RegExpFlag::IgnoreCase))
-+                    reflags = RegExpFlags(reflags | RegExpFlag::IgnoreCase);
-+                else if (c == 'm' && !(reflags & RegExpFlag::Multiline))
-+                    reflags = RegExpFlags(reflags | RegExpFlag::Multiline);
-+                else if (c == 's' && !(reflags & RegExpFlag::DotAll))
-+                    reflags = RegExpFlags(reflags | RegExpFlag::DotAll);
-+                else if (c == 'u' && !(reflags & RegExpFlag::Unicode))
-+                    reflags = RegExpFlags(reflags | RegExpFlag::Unicode);
-+                else if (c == 'y' && !(reflags & RegExpFlag::Sticky))
-+                    reflags = RegExpFlags(reflags | RegExpFlag::Sticky);
-                 else
-                     break;
-                 if (!getChar(&c))
-                     goto error;
-                 length++;
-             }
- 
-             if (!peekChar(&c))
-diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h
---- a/js/src/frontend/TokenStream.h
-+++ b/js/src/frontend/TokenStream.h
-@@ -171,21 +171,21 @@
- #include <stdarg.h>
- #include <stddef.h>
- #include <stdio.h>
- 
- #include "jspubtd.h"
- 
- #include "frontend/ErrorReporter.h"
- #include "frontend/TokenKind.h"
-+#include "js/RegExpFlags.h"
- #include "js/UniquePtr.h"
- #include "js/Vector.h"
- #include "vm/ErrorReporting.h"
- #include "vm/JSContext.h"
--#include "vm/RegExpShared.h"
- #include "vm/String.h"
- #include "vm/Unicode.h"
- 
- struct KeywordInfo;
- 
- namespace js {
- namespace frontend {
- 
-@@ -333,17 +333,17 @@ struct Token
-       private:
-         friend struct Token;
-         PropertyName*   name;          // non-numeric atom
-         JSAtom*         atom;          // potentially-numeric atom
-         struct {
-             double      value;          // floating point number
-             DecimalPoint decimalPoint;  // literal contains '.'
-         } number;
--        RegExpFlag      reflags;        // regexp flags; use tokenbuf to access
-+        JS::RegExpFlags  reflags;       // regexp flags; use tokenbuf to access
-                                         //   regexp chars
-     } u;
- #ifdef DEBUG
-     Modifier modifier;                  // Modifier used to get this token
-     ModifierException modifierException; // Exception for this modifier
- #endif
- 
-     // Mutators
-@@ -355,19 +355,18 @@ struct Token
- 
-     void setAtom(JSAtom* atom) {
-         MOZ_ASSERT(type == TokenKind::String ||
-                    type == TokenKind::TemplateHead ||
-                    type == TokenKind::NoSubsTemplate);
-         u.atom = atom;
-     }
- 
--    void setRegExpFlags(RegExpFlag flags) {
-+    void setRegExpFlags(JS::RegExpFlags flags) {
-         MOZ_ASSERT(type == TokenKind::RegExp);
--        MOZ_ASSERT((flags & AllFlags) == flags);
-         u.reflags = flags;
-     }
- 
-     void setNumber(double n, DecimalPoint decimalPoint) {
-         MOZ_ASSERT(type == TokenKind::Number);
-         u.number.value = n;
-         u.number.decimalPoint = decimalPoint;
-     }
-@@ -381,19 +380,18 @@ struct Token
- 
-     JSAtom* atom() const {
-         MOZ_ASSERT(type == TokenKind::String ||
-                    type == TokenKind::TemplateHead ||
-                    type == TokenKind::NoSubsTemplate);
-         return u.atom;
-     }
- 
--    RegExpFlag regExpFlags() const {
-+    JS::RegExpFlags regExpFlags() const {
-         MOZ_ASSERT(type == TokenKind::RegExp);
--        MOZ_ASSERT((u.reflags & AllFlags) == u.reflags);
-         return u.reflags;
-     }
- 
-     double number() const {
-         MOZ_ASSERT(type == TokenKind::Number);
-         return u.number.value;
-     }
- 
-@@ -1568,30 +1566,36 @@ class TokenStreamAnyCharsAccess
-   public:
-     template<class TokenStreamSpecific>
-     static inline TokenStreamAnyChars& anyChars(TokenStreamSpecific* tss);
- 
-     template<class TokenStreamSpecific>
-     static inline const TokenStreamAnyChars& anyChars(const TokenStreamSpecific* tss);
- };
- 
--class MOZ_STACK_CLASS TokenStream final
-+class MOZ_STACK_CLASS TokenStream
-   : public TokenStreamAnyChars,
-     public TokenStreamSpecific<char16_t, TokenStreamAnyCharsAccess>
- {
-     using CharT = char16_t;
- 
-   public:
-     TokenStream(JSContext* cx, const ReadOnlyCompileOptions& options,
-                 const CharT* base, size_t length, StrictModeGetter* smg)
-     : TokenStreamAnyChars(cx, options, smg),
-       TokenStreamSpecific<CharT, TokenStreamAnyCharsAccess>(cx, options, base, length)
-     {}
- };
- 
-+class MOZ_STACK_CLASS DummyTokenStream final : public TokenStream {
-+  public:
-+    DummyTokenStream(JSContext* cx, const JS::ReadOnlyCompileOptions& options)
-+        : TokenStream(cx, options, nullptr, 0, nullptr) {}
-+};
-+
- template<class TokenStreamSpecific>
- /* static */ inline TokenStreamAnyChars&
- TokenStreamAnyCharsAccess::anyChars(TokenStreamSpecific* tss)
- {
-     auto* ts = static_cast<TokenStream*>(tss);
-     return *static_cast<TokenStreamAnyChars*>(ts);
- }
- 
-diff --git a/js/src/irregexp/IRREGEXP_VERSION b/js/src/irregexp/IRREGEXP_VERSION
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/IRREGEXP_VERSION
-@@ -0,0 +1,2 @@
-+Imported using import-irregexp.py from:
-+https://github.com/v8/v8/tree/8732b2ee52b567ad4e15ca91d141fd6e27499e99/src/regexp
-diff --git a/js/src/irregexp/RegExpAPI.cpp b/js/src/irregexp/RegExpAPI.cpp
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/RegExpAPI.cpp
-@@ -0,0 +1,703 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+// Copyright 2020 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include "irregexp/RegExpAPI.h"
-+
-+#include "mozilla/ArrayUtils.h"
-+#include "mozilla/Casting.h"
-+
-+#include "irregexp/imported/regexp-ast.h"
-+#include "irregexp/imported/regexp-bytecode-generator.h"
-+#include "irregexp/imported/regexp-compiler.h"
-+#include "irregexp/imported/regexp-interpreter.h"
-+#include "irregexp/imported/regexp-macro-assembler-arch.h"
-+#include "irregexp/imported/regexp-parser.h"
-+#include "irregexp/imported/regexp-stack.h"
-+#include "irregexp/imported/regexp.h"
-+#include "irregexp/RegExpShim.h"
-+#include "jit/JitCommon.h"
-+
-+#include "util/Text.h"
-+#include "vm/ErrorReporting.h"
-+#include "vm/MatchPairs.h"
-+#include "vm/RegExpShared.h"
-+#include "vm/StringBuffer.h"
-+
-+namespace js {
-+namespace irregexp {
-+
-+using namespace mozilla;
-+
-+using frontend::DummyTokenStream;
-+using frontend::TokenStreamAnyChars;
-+
-+using v8::internal::DisallowGarbageCollection;
-+using v8::internal::FlatStringReader;
-+using v8::internal::HandleScope;
-+using v8::internal::InputOutputData;
-+using v8::internal::IrregexpInterpreter;
-+using v8::internal::NativeRegExpMacroAssembler;
-+using v8::internal::RegExpBytecodeGenerator;
-+using v8::internal::RegExpCompileData;
-+using v8::internal::RegExpCompiler;
-+using v8::internal::RegExpError;
-+using v8::internal::RegExpMacroAssembler;
-+using v8::internal::RegExpNode;
-+using v8::internal::RegExpParser;
-+using v8::internal::SMRegExpMacroAssembler;
-+using v8::internal::Zone;
-+
-+using V8HandleString = v8::internal::Handle<v8::internal::String>;
-+using V8HandleRegExp = v8::internal::Handle<v8::internal::JSRegExp>;
-+
-+using namespace v8::internal::regexp_compiler_constants;
-+
-+static uint32_t ErrorNumber(RegExpError err) {
-+  switch (err) {
-+    case RegExpError::kNone:
-+      return JSMSG_NOT_AN_ERROR;
-+    case RegExpError::kStackOverflow:
-+      return JSMSG_OVER_RECURSED;
-+    case RegExpError::kAnalysisStackOverflow:
-+      return JSMSG_OVER_RECURSED;
-+    case RegExpError::kTooLarge:
-+      return JSMSG_TOO_MANY_PARENS;
-+    case RegExpError::kUnterminatedGroup:
-+      return JSMSG_MISSING_PAREN;
-+    case RegExpError::kUnmatchedParen:
-+      return JSMSG_UNMATCHED_RIGHT_PAREN;
-+    case RegExpError::kEscapeAtEndOfPattern:
-+      return JSMSG_ESCAPE_AT_END_OF_REGEXP;
-+    case RegExpError::kInvalidPropertyName:
-+      return JSMSG_INVALID_PROPERTY_NAME;
-+    case RegExpError::kInvalidEscape:
-+      return JSMSG_INVALID_IDENTITY_ESCAPE;
-+    case RegExpError::kInvalidDecimalEscape:
-+      return JSMSG_INVALID_DECIMAL_ESCAPE;
-+    case RegExpError::kInvalidUnicodeEscape:
-+      return JSMSG_INVALID_UNICODE_ESCAPE;
-+    case RegExpError::kNothingToRepeat:
-+      return JSMSG_NOTHING_TO_REPEAT;
-+    case RegExpError::kLoneQuantifierBrackets:
-+      // Note: V8 reports the same error for both ']' and '}'.
-+      return JSMSG_RAW_BRACKET_IN_REGEXP;
-+    case RegExpError::kRangeOutOfOrder:
-+      return JSMSG_NUMBERS_OUT_OF_ORDER;
-+    case RegExpError::kIncompleteQuantifier:
-+      return JSMSG_INCOMPLETE_QUANTIFIER;
-+    case RegExpError::kInvalidQuantifier:
-+      return JSMSG_INVALID_QUANTIFIER;
-+    case RegExpError::kInvalidGroup:
-+      return JSMSG_INVALID_GROUP;
-+    case RegExpError::kMultipleFlagDashes:
-+    case RegExpError::kRepeatedFlag:
-+    case RegExpError::kInvalidFlagGroup:
-+      // V8 contains experimental support for turning regexp flags on
-+      // and off in the middle of a regular expression. Unless it
-+      // becomes standardized, SM does not support this feature.
-+      MOZ_CRASH("Mode modifiers not supported");
-+    case RegExpError::kNotLinear:
-+      // V8 has an experimental non-backtracking engine. We do not
-+      // support it yet.
-+      MOZ_CRASH("Non-backtracking execution not supported");
-+    case RegExpError::kTooManyCaptures:
-+      return JSMSG_TOO_MANY_PARENS;
-+    case RegExpError::kInvalidCaptureGroupName:
-+      return JSMSG_INVALID_CAPTURE_NAME;
-+    case RegExpError::kDuplicateCaptureGroupName:
-+      return JSMSG_DUPLICATE_CAPTURE_NAME;
-+    case RegExpError::kInvalidNamedReference:
-+      return JSMSG_INVALID_NAMED_REF;
-+    case RegExpError::kInvalidNamedCaptureReference:
-+      return JSMSG_INVALID_NAMED_CAPTURE_REF;
-+    case RegExpError::kInvalidClassEscape:
-+      return JSMSG_RANGE_WITH_CLASS_ESCAPE;
-+    case RegExpError::kInvalidClassPropertyName:
-+      return JSMSG_INVALID_CLASS_PROPERTY_NAME;
-+    case RegExpError::kInvalidCharacterClass:
-+      return JSMSG_RANGE_WITH_CLASS_ESCAPE;
-+    case RegExpError::kUnterminatedCharacterClass:
-+      return JSMSG_UNTERM_CLASS;
-+    case RegExpError::kOutOfOrderCharacterClass:
-+      return JSMSG_BAD_CLASS_RANGE;
-+    case RegExpError::NumErrors:
-+      MOZ_CRASH("Unreachable");
-+  }
-+  MOZ_CRASH("Unreachable");
-+}
-+
-+Isolate* CreateIsolate(JSContext* cx) {
-+  auto isolate = MakeUnique<Isolate>(cx);
-+  if (!isolate || !isolate->init()) {
-+    return nullptr;
-+  }
-+  return isolate.release();
-+}
-+
-+void DestroyIsolate(Isolate* isolate) {
-+  MOZ_ASSERT(isolate->liveHandles() == 0);
-+  MOZ_ASSERT(isolate->livePseudoHandles() == 0);
-+  js_delete(isolate);
-+}
-+
-+size_t IsolateSizeOfIncludingThis(Isolate* isolate,
-+                                  mozilla::MallocSizeOf mallocSizeOf) {
-+  return isolate->sizeOfIncludingThis(mallocSizeOf);
-+}
-+
-+static size_t ComputeColumn(const Latin1Char* begin, const Latin1Char* end) {
-+  return mozilla::PointerRangeSize(begin, end);
-+}
-+
-+static size_t ComputeColumn(const char16_t* begin, const char16_t* end) {
-+  return unicode::CountCodePoints(begin, end);
-+}
-+
-+// This function is varargs purely so it can call ReportCompileErrorLatin1.
-+// We never call it with additional arguments.
-+template <typename CharT>
-+static void ReportSyntaxError(TokenStreamAnyChars& ts, RegExpCompileData& result,
-+                              CharT* start, size_t length, ...) {
-+  gc::AutoSuppressGC suppressGC(ts.context());
-+  uint32_t errorNumber = ErrorNumber(result.error);
-+
-+  if (errorNumber == JSMSG_OVER_RECURSED) {
-+    ReportOverRecursed(ts.context());
-+    return;
-+  }
-+
-+  uint32_t offset = std::max(result.error_pos, 0);
-+  MOZ_ASSERT(offset <= length);
-+
-+  ErrorMetadata err;
-+
-+  // Ordinarily this indicates whether line-of-context information can be
-+  // added, but we entirely ignore that here because we create a
-+  // a line of context based on the expression source.
-+  uint32_t location = ts.currentToken().pos.begin;
-+  if (ts.fillExcludingContext(&err, location)) {
-+    // Line breaks are not significant in pattern text in the same way as
-+    // in source text, so act as though pattern text is a single line, then
-+    // compute a column based on "code point" count (treating a lone
-+    // surrogate as a "code point" in UTF-16).  Gak.
-+    err.lineNumber = 1;
-+    err.columnNumber =
-+        AssertedCast<uint32_t>(ComputeColumn(start, start + offset));
-+  }
-+
-+  // For most error reporting, the line of context derives from the token
-+  // stream.  So when location information doesn't come from the token
-+  // stream, we can't give a line of context.  But here the "line of context"
-+  // can be (and is) derived from the pattern text, so we can provide it no
-+  // matter if the location is derived from the caller.
-+
-+  const CharT* windowStart =
-+      (offset > ErrorMetadata::lineOfContextRadius)
-+          ? start + (offset - ErrorMetadata::lineOfContextRadius)
-+          : start;
-+
-+  const CharT* windowEnd =
-+      (length - offset > ErrorMetadata::lineOfContextRadius)
-+          ? start + offset + ErrorMetadata::lineOfContextRadius
-+          : start + length;
-+
-+  size_t windowLength = PointerRangeSize(windowStart, windowEnd);
-+  MOZ_ASSERT(windowLength <= ErrorMetadata::lineOfContextRadius * 2);
-+
-+  // Create the windowed string, not including the potential line
-+  // terminator.
-+  StringBuffer windowBuf(ts.context());
-+  if (!windowBuf.append(windowStart, windowEnd)) {
-+    return;
-+  }
-+
-+  // The line of context must be null-terminated, and StringBuffer doesn't
-+  // make that happen unless we force it to.
-+  if (!windowBuf.append('\0')) {
-+    return;
-+  }
-+
-+  err.lineOfContext.reset(windowBuf.stealChars());
-+  if (!err.lineOfContext) {
-+    return;
-+  }
-+
-+  err.lineLength = windowLength;
-+  err.tokenOffset = offset - (windowStart - start);
-+
-+  va_list args;
-+  va_start(args, length);
-+  ReportCompileError(ts.context(), std::move(err), nullptr, /* notes/report */
-+                     JSREPORT_ERROR,                        /*flags*/
-+                     errorNumber, args);
-+  va_end(args);
-+}
-+
-+static void ReportSyntaxError(TokenStreamAnyChars& ts, RegExpCompileData& result,
-+                              HandleAtom pattern) {
-+  JS::AutoCheckCannotGC nogc_;
-+  if (pattern->hasLatin1Chars()) {
-+    ReportSyntaxError(ts, result, pattern->latin1Chars(nogc_),
-+                      pattern->length());
-+  } else {
-+    ReportSyntaxError(ts, result, pattern->twoByteChars(nogc_),
-+                      pattern->length());
-+  }
-+}
-+
-+static bool CheckPatternSyntaxImpl(JSContext* cx, FlatStringReader* pattern,
-+                                   JS::RegExpFlags flags,
-+                                   RegExpCompileData* result) {
-+  LifoAllocScope allocScope(&cx->tempLifoAlloc());
-+  Zone zone(allocScope.alloc());
-+
-+  HandleScope handleScope(cx->isolate);
-+  DisallowGarbageCollection no_gc;
-+  return RegExpParser::VerifyRegExpSyntax(cx->isolate, &zone, pattern, flags,
-+                                          result, no_gc);
-+}
-+
-+bool CheckPatternSyntax(JSContext* cx, TokenStreamAnyChars& ts,
-+                        const mozilla::Range<const char16_t> chars,
-+                        JS::RegExpFlags flags) {
-+  FlatStringReader reader(chars);
-+  RegExpCompileData result;
-+  if (!CheckPatternSyntaxImpl(cx, &reader, flags, &result)) {
-+    ReportSyntaxError(ts, result, chars.begin().get(), chars.length());
-+    return false;
-+  }
-+  return true;
-+}
-+
-+bool CheckPatternSyntax(JSContext* cx, TokenStreamAnyChars& ts, HandleAtom pattern,
-+                        JS::RegExpFlags flags) {
-+  FlatStringReader reader(cx, pattern);
-+  RegExpCompileData result;
-+  if (!CheckPatternSyntaxImpl(cx, &reader, flags, &result)) {
-+    ReportSyntaxError(ts, result, pattern);
-+    return false;
-+  }
-+  return true;
-+}
-+
-+// A regexp is a good candidate for Boyer-Moore if it has at least 3
-+// times as many characters as it has unique characters. Note that
-+// table lookups in irregexp are done modulo tableSize (128).
-+template <typename CharT>
-+static bool HasFewDifferentCharacters(const CharT* chars, size_t length) {
-+  const uint32_t tableSize =
-+      v8::internal::NativeRegExpMacroAssembler::kTableSize;
-+  bool character_found[tableSize];
-+  uint32_t different = 0;
-+  memset(&character_found[0], 0, sizeof(character_found));
-+  for (uint32_t i = 0; i < length; i++) {
-+    uint32_t ch = chars[i] % tableSize;
-+    if (!character_found[ch]) {
-+      character_found[ch] = true;
-+      different++;
-+      // We declare a regexp low-alphabet if it has at least 3 times as many
-+      // characters as it has different characters.
-+      if (different * 3 > length) {
-+        return false;
-+      }
-+    }
-+  }
-+  return true;
-+}
-+
-+// Identifies the sort of pattern where Boyer-Moore is faster than string search
-+static bool UseBoyerMoore(HandleAtom pattern, JS::AutoCheckCannotGC& nogc) {
-+  size_t length =
-+      std::min(size_t(kMaxLookaheadForBoyerMoore), pattern->length());
-+  if (length <= kPatternTooShortForBoyerMoore) {
-+    return false;
-+  }
-+
-+  if (pattern->hasLatin1Chars()) {
-+    return HasFewDifferentCharacters(pattern->latin1Chars(nogc), length);
-+  }
-+  MOZ_ASSERT(pattern->hasTwoByteChars());
-+  return HasFewDifferentCharacters(pattern->twoByteChars(nogc), length);
-+}
-+
-+// Sample character frequency information for use in Boyer-Moore.
-+static void SampleCharacters(FlatStringReader* sample_subject,
-+                             RegExpCompiler& compiler) {
-+  static const int kSampleSize = 128;
-+  int chars_sampled = 0;
-+
-+  int length = sample_subject->length();
-+
-+  int half_way = (length - kSampleSize) / 2;
-+  for (int i = std::max(0, half_way); i < length && chars_sampled < kSampleSize;
-+       i++, chars_sampled++) {
-+    compiler.frequency_collator()->CountCharacter(sample_subject->Get(i));
-+  }
-+}
-+
-+// Recursively walking the AST for a deeply nested regexp (like
-+// `/(a(a(a(a(a(a(a(...(a)...))))))))/`) may overflow the stack while
-+// compiling. To avoid this, we use V8's implementation of the Visitor
-+// pattern to walk the AST first with an overly large stack frame.
-+class RegExpDepthCheck final : public v8::internal::RegExpVisitor {
-+ public:
-+  explicit RegExpDepthCheck(JSContext* cx) : cx_(cx) {}
-+
-+  bool check(v8::internal::RegExpTree* root) {
-+    return !!root->Accept(this, nullptr);
-+  }
-+
-+  // Leaf nodes with no children
-+#define LEAF_DEPTH(Kind)                                                \
-+  void* Visit##Kind(v8::internal::RegExp##Kind* node, void*) override { \
-+    uint8_t padding[FRAME_PADDING];                                     \
-+    dummy_ = padding; /* Prevent padding from being optimized away.*/   \
-+    return (void*)CheckRecursionLimitDontReport(cx_);                   \
-+  }
-+
-+  LEAF_DEPTH(Assertion)
-+  LEAF_DEPTH(Atom)
-+  LEAF_DEPTH(BackReference)
-+  LEAF_DEPTH(CharacterClass)
-+  LEAF_DEPTH(Empty)
-+  LEAF_DEPTH(Text)
-+#undef LEAF_DEPTH
-+
-+  // Wrapper nodes with one child
-+#define WRAPPER_DEPTH(Kind)                                             \
-+  void* Visit##Kind(v8::internal::RegExp##Kind* node, void*) override { \
-+    uint8_t padding[FRAME_PADDING];                                     \
-+    dummy_ = padding; /* Prevent padding from being optimized away.*/   \
-+    if (!CheckRecursionLimitDontReport(cx_)) {                          \
-+      return nullptr;                                                   \
-+    }                                                                   \
-+    return node->body()->Accept(this, nullptr);                         \
-+  }
-+
-+  WRAPPER_DEPTH(Capture)
-+  WRAPPER_DEPTH(Group)
-+  WRAPPER_DEPTH(Lookaround)
-+  WRAPPER_DEPTH(Quantifier)
-+#undef WRAPPER_DEPTH
-+
-+  void* VisitAlternative(v8::internal::RegExpAlternative* node,
-+                         void*) override {
-+    uint8_t padding[FRAME_PADDING];
-+    dummy_ = padding; /* Prevent padding from being optimized away.*/
-+    if (!CheckRecursionLimitDontReport(cx_)) {
-+      return nullptr;
-+    }
-+    for (auto* child : *node->nodes()) {
-+      if (!child->Accept(this, nullptr)) {
-+        return nullptr;
-+      }
-+    }
-+    return (void*)true;
-+  }
-+  void* VisitDisjunction(v8::internal::RegExpDisjunction* node,
-+                         void*) override {
-+    uint8_t padding[FRAME_PADDING];
-+    dummy_ = padding; /* Prevent padding from being optimized away.*/
-+    if (!CheckRecursionLimitDontReport(cx_)) {
-+      return nullptr;
-+    }
-+    for (auto* child : *node->alternatives()) {
-+      if (!child->Accept(this, nullptr)) {
-+        return nullptr;
-+      }
-+    }
-+    return (void*)true;
-+  }
-+
-+ private:
-+  JSContext* cx_;
-+  void* dummy_ = nullptr;
-+
-+  // This size is picked to be comfortably larger than any
-+  // RegExp*::ToNode stack frame.
-+  static const size_t FRAME_PADDING = 256;
-+};
-+
-+enum class AssembleResult {
-+  Success,
-+  TooLarge,
-+  OutOfMemory,
-+};
-+
-+static MOZ_MUST_USE AssembleResult Assemble(JSContext* cx,
-+                                            RegExpCompiler* compiler,
-+                                            RegExpCompileData* data,
-+                                            MutableHandleRegExpShared re,
-+                                            HandleAtom pattern, Zone* zone,
-+                                            bool useNativeCode, bool isLatin1) {
-+  // Because we create a StackMacroAssembler, this function is not allowed
-+  // to GC. If needed, we allocate and throw errors in the caller.
-+  Maybe<jit::JitContext> jctx;
-+  Maybe<js::jit::StackMacroAssembler> stack_masm;
-+  UniquePtr<RegExpMacroAssembler> masm;
-+  if (useNativeCode) {
-+    NativeRegExpMacroAssembler::Mode mode =
-+        isLatin1 ? NativeRegExpMacroAssembler::LATIN1
-+                 : NativeRegExpMacroAssembler::UC16;
-+    // If we are compiling native code, we need a macroassembler,
-+    // which needs a jit context.
-+    jctx.emplace(cx, nullptr);
-+    stack_masm.emplace();
-+    uint32_t num_capture_registers = re->pairCount() * 2;
-+    masm = MakeUnique<SMRegExpMacroAssembler>(cx, stack_masm.ref(), zone, mode,
-+                                              num_capture_registers);
-+  } else {
-+    masm = MakeUnique<RegExpBytecodeGenerator>(cx->isolate, zone);
-+  }
-+  if (!masm) {
-+    return AssembleResult::OutOfMemory;
-+  }
-+
-+  bool isLargePattern =
-+      pattern->length() > v8::internal::RegExp::kRegExpTooLargeToOptimize;
-+  masm->set_slow_safe(isLargePattern);
-+  if (compiler->optimize()) {
-+    compiler->set_optimize(!isLargePattern);
-+  }
-+
-+  // When matching a regexp with known maximum length that is anchored
-+  // at the end, we may be able to skip the beginning of long input
-+  // strings. This decision is made here because it depends on
-+  // information in the AST that isn't replicated in the Node
-+  // structure used inside the compiler.
-+  bool is_start_anchored = data->tree->IsAnchoredAtStart();
-+  bool is_end_anchored = data->tree->IsAnchoredAtEnd();
-+  int max_length = data->tree->max_match();
-+  static const int kMaxBacksearchLimit = 1024;
-+  if (is_end_anchored && !is_start_anchored && !re->sticky() &&
-+      max_length < kMaxBacksearchLimit) {
-+    masm->SetCurrentPositionFromEnd(max_length);
-+  }
-+
-+  if (re->global()) {
-+    RegExpMacroAssembler::GlobalMode mode = RegExpMacroAssembler::GLOBAL;
-+    if (data->tree->min_match() > 0) {
-+      mode = RegExpMacroAssembler::GLOBAL_NO_ZERO_LENGTH_CHECK;
-+    } else if (re->unicode()) {
-+      mode = RegExpMacroAssembler::GLOBAL_UNICODE;
-+    }
-+    masm->set_global_mode(mode);
-+  }
-+
-+  // Compile the regexp.
-+  V8HandleString wrappedPattern(v8::internal::String(pattern), cx->isolate);
-+  RegExpCompiler::CompilationResult result = compiler->Assemble(
-+      cx->isolate, masm.get(), data->node, data->capture_count, wrappedPattern);
-+  if (!result.Succeeded()) {
-+    MOZ_ASSERT(result.error == RegExpError::kTooLarge);
-+    return AssembleResult::TooLarge;
-+  }
-+  if (result.code->value().isUndefined()) {
-+    // SMRegExpMacroAssembler::GetCode returns undefined on OOM.
-+    MOZ_ASSERT(useNativeCode);
-+    return AssembleResult::OutOfMemory;
-+  }
-+
-+  re->updateMaxRegisters(result.num_registers);
-+  if (useNativeCode) {
-+    // Transfer ownership of the tables from the macroassembler to the
-+    // RegExpShared.
-+    SMRegExpMacroAssembler::TableVector& tables =
-+        static_cast<SMRegExpMacroAssembler*>(masm.get())->tables();
-+    for (uint32_t i = 0; i < tables.length(); i++) {
-+      if (!re->addTable(std::move(tables[i]))) {
-+        return AssembleResult::OutOfMemory;
-+      }
-+    }
-+    re->setJitCode(v8::internal::Code::cast(*result.code).inner(), isLatin1);
-+  } else {
-+    // Transfer ownership of the bytecode from the HandleScope to the
-+    // RegExpShared.
-+    ByteArray bytecode =
-+        v8::internal::ByteArray::cast(*result.code).takeOwnership(cx->isolate);
-+    uint32_t length = bytecode->length;
-+    re->setByteCode(bytecode.release(), isLatin1);
-+    // js::AddCellMemory(re, length, MemoryUse::RegExpSharedBytecode);
-+  }
-+
-+  return AssembleResult::Success;
-+}
-+
-+bool CompilePattern(JSContext* cx, MutableHandleRegExpShared re,
-+                    HandleLinearString input, RegExpShared::CodeKind codeKind) {
-+  RootedAtom pattern(cx, re->getSource());
-+  JS::RegExpFlags flags = re->getFlags();
-+  LifoAllocScope allocScope(&cx->tempLifoAlloc());
-+  HandleScope handleScope(cx->isolate);
-+  Zone zone(allocScope.alloc());
-+
-+  RegExpCompileData data;
-+  {
-+    FlatStringReader patternBytes(cx, pattern);
-+    if (!RegExpParser::ParseRegExp(cx->isolate, &zone, &patternBytes, flags,
-+                                   &data)) {
-+      MOZ_ASSERT(data.error == RegExpError::kStackOverflow);
-+      JS::CompileOptions options(cx);
-+      DummyTokenStream dummyTokenStream(cx, options);
-+      ReportSyntaxError(dummyTokenStream, data, pattern);
-+      return false;
-+    }
-+  }
-+
-+  // Avoid stack overflow while recursively walking the AST.
-+  RegExpDepthCheck depthCheck(cx);
-+  if (!depthCheck.check(data.tree)) {
-+    JS_ReportErrorASCII(cx, "regexp too big");
-+    return false;
-+  }
-+
-+  if (re->kind() == RegExpShared::Kind::Unparsed) {
-+    // This is the first time we have compiled this regexp.
-+    // First, check to see if we should use simple string search
-+    // with an atom.
-+    if (!flags.ignoreCase() && !flags.sticky()) {
-+      RootedAtom searchAtom(cx);
-+      if (data.simple) {
-+        // The parse-tree is a single atom that is equal to the pattern.
-+        searchAtom = re->getSource();
-+      } else if (data.tree->IsAtom() && data.capture_count == 0) {
-+        // The parse-tree is a single atom that is not equal to the pattern.
-+        v8::internal::RegExpAtom* atom = data.tree->AsAtom();
-+        const char16_t* twoByteChars = atom->data().begin();
-+        searchAtom = AtomizeChars(cx, twoByteChars, atom->length());
-+        if (!searchAtom) {
-+          return false;
-+        }
-+      }
-+      JS::AutoCheckCannotGC nogc(cx);
-+      if (searchAtom && !UseBoyerMoore(searchAtom, nogc)) {
-+        re->useAtomMatch(searchAtom);
-+        return true;
-+      }
-+    }
-+    if (!data.capture_name_map.is_null()) {
-+      RootedNativeObject namedCaptures(cx, data.capture_name_map->inner());
-+      if (!RegExpShared::initializeNamedCaptures(cx, re, namedCaptures)) {
-+        return false;
-+      }
-+    }
-+    // All fallible initialization has succeeded, so we can change state.
-+    // Add one to capture_count to account for the whole-match capture.
-+    uint32_t pairCount = data.capture_count + 1;
-+    re->useRegExpMatch(pairCount);
-+  }
-+
-+  MOZ_ASSERT(re->kind() == RegExpShared::Kind::RegExp);
-+
-+  RegExpCompiler compiler(cx->isolate, &zone, data.capture_count,
-+                          input->hasLatin1Chars());
-+
-+  bool isLatin1 = input->hasLatin1Chars();
-+
-+  FlatStringReader sample_subject(cx, input);
-+  SampleCharacters(&sample_subject, compiler);
-+  data.node = compiler.PreprocessRegExp(&data, flags, isLatin1);
-+  data.error = AnalyzeRegExp(cx->isolate, isLatin1, data.node);
-+  if (data.error != RegExpError::kNone) {
-+    MOZ_ASSERT(data.error == RegExpError::kAnalysisStackOverflow);
-+    ReportOverRecursed(cx);
-+    return false;
-+  }
-+
-+  bool useNativeCode = codeKind == RegExpShared::CodeKind::Jitcode;
-+  MOZ_ASSERT_IF(useNativeCode, IsNativeRegExpEnabled(cx));
-+
-+  switch (Assemble(cx, &compiler, &data, re, pattern, &zone, useNativeCode,
-+                   isLatin1)) {
-+    case AssembleResult::TooLarge:
-+      JS_ReportErrorASCII(cx, "regexp too big");
-+      return false;
-+    case AssembleResult::OutOfMemory:
-+      ReportOutOfMemory(cx);
-+      return false;
-+    case AssembleResult::Success:
-+      break;
-+  }
-+  return true;
-+}
-+
-+template <typename CharT>
-+RegExpRunStatus ExecuteRaw(jit::JitCode* code, const CharT* chars,
-+                           size_t length, size_t startIndex,
-+                           MatchPairs* matches) {
-+  InputOutputData data(chars, chars + length, startIndex, matches);
-+
-+  static_assert(RegExpRunStatus_Error ==
-+                v8::internal::RegExp::kInternalRegExpException, "e1");
-+  static_assert(RegExpRunStatus_Success ==
-+                v8::internal::RegExp::kInternalRegExpSuccess, "e2");
-+  static_assert(RegExpRunStatus_Success_NotFound ==
-+                v8::internal::RegExp::kInternalRegExpFailure, "e3");
-+
-+  typedef int (*RegExpCodeSignature)(InputOutputData*);
-+  auto function = reinterpret_cast<RegExpCodeSignature>(code->raw());
-+  {
-+    JS::AutoSuppressGCAnalysis nogc;
-+    return (RegExpRunStatus)CALL_GENERATED_1(function, &data);
-+  }
-+}
-+
-+RegExpRunStatus Interpret(JSContext* cx, MutableHandleRegExpShared re,
-+                          HandleLinearString input, size_t startIndex,
-+                          MatchPairs* matches) {
-+  MOZ_ASSERT(re->getByteCode(input->hasLatin1Chars()));
-+
-+  HandleScope handleScope(cx->isolate);
-+  V8HandleRegExp wrappedRegExp(v8::internal::JSRegExp(re), cx->isolate);
-+  V8HandleString wrappedInput(v8::internal::String(input), cx->isolate);
-+
-+  static_assert(RegExpRunStatus_Error ==
-+                v8::internal::RegExp::kInternalRegExpException, "e4");
-+  static_assert(RegExpRunStatus_Success ==
-+                v8::internal::RegExp::kInternalRegExpSuccess, "e5");
-+  static_assert(RegExpRunStatus_Success_NotFound ==
-+                v8::internal::RegExp::kInternalRegExpFailure, "e6");
-+
-+  RegExpRunStatus status =
-+      (RegExpRunStatus)IrregexpInterpreter::MatchForCallFromRuntime(
-+          cx->isolate, wrappedRegExp, wrappedInput, matches->pairsRaw(),
-+          matches->pairCount() * 2, startIndex);
-+
-+  MOZ_ASSERT(status == RegExpRunStatus_Error ||
-+             status == RegExpRunStatus_Success ||
-+             status == RegExpRunStatus_Success_NotFound);
-+
-+  return status;
-+}
-+
-+RegExpRunStatus Execute(JSContext* cx, MutableHandleRegExpShared re,
-+                        HandleLinearString input, size_t startIndex,
-+                        MatchPairs* matches) {
-+  bool latin1 = input->hasLatin1Chars();
-+  jit::JitCode* jitCode = re->getJitCode(latin1);
-+  bool isCompiled = !!jitCode;
-+
-+  // Reset the Irregexp backtrack stack if it grows during execution.
-+  irregexp::RegExpStackScope stackScope(cx->isolate);
-+
-+  if (isCompiled) {
-+    JS::AutoCheckCannotGC nogc;
-+    if (latin1) {
-+      return ExecuteRaw(jitCode, input->latin1Chars(nogc), input->length(),
-+                        startIndex, matches);
-+    }
-+    return ExecuteRaw(jitCode, input->twoByteChars(nogc), input->length(),
-+                      startIndex, matches);
-+  }
-+
-+  return Interpret(cx, re, input, startIndex, matches);
-+}
-+
-+}  // namespace irregexp
-+}  // namespace js
-diff --git a/js/src/irregexp/RegExpAPI.h b/js/src/irregexp/RegExpAPI.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/RegExpAPI.h
-@@ -0,0 +1,46 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+ *
-+ * This Source Code Form is "Incompatible With Secondary Licenses", as
-+ * defined by the Mozilla Public License, v. 2.0.
-+ */
-+
-+/* This is the interface that the regexp engine exposes to SpiderMonkey. */
-+
-+#ifndef regexp_RegExpAPI_h
-+#define regexp_RegExpAPI_h
-+
-+#include "mozilla/MemoryReporting.h"
-+
-+#include "frontend/TokenStream.h"
-+#include "jsgc.h"
-+#include "vm/JSContext.h"
-+#include "vm/RegExpObject.h"
-+
-+namespace js {
-+namespace irregexp {
-+
-+Isolate* CreateIsolate(JSContext* cx);
-+void DestroyIsolate(Isolate* isolate);
-+
-+size_t IsolateSizeOfIncludingThis(Isolate* isolate,
-+                                  mozilla::MallocSizeOf mallocSizeOf);
-+
-+bool CheckPatternSyntax(JSContext* cx, frontend::TokenStreamAnyChars& ts,
-+                        const mozilla::Range<const char16_t> chars,
-+                        JS::RegExpFlags flags);
-+bool CheckPatternSyntax(JSContext* cx, frontend::TokenStreamAnyChars& ts,
-+                        HandleAtom pattern, JS::RegExpFlags flags);
-+bool CompilePattern(JSContext* cx, MutableHandleRegExpShared re,
-+                    HandleLinearString input, RegExpShared::CodeKind codeKind);
-+
-+RegExpRunStatus Execute(JSContext* cx, MutableHandleRegExpShared re,
-+                        HandleLinearString input, size_t start,
-+                        MatchPairs* matches);
-+
-+}  // namespace irregexp
-+}  // namespace js
-+
-+#endif /* regexp_RegExpAPI_h */
-diff --git a/js/src/irregexp/RegExpNativeMacroAssembler.cpp b/js/src/irregexp/RegExpNativeMacroAssembler.cpp
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/RegExpNativeMacroAssembler.cpp
-@@ -0,0 +1,1250 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+// Copyright 2020 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include "irregexp/imported/regexp-macro-assembler-arch.h"
-+#include "irregexp/imported/regexp-stack.h"
-+#include "irregexp/imported/special-case.h"
-+#include "jit/Linker.h"
-+#include "gc/Zone.h"
-+#include "vm/MatchPairs.h"
-+
-+#include "jit/MacroAssembler-inl.h"
-+
-+using namespace js;
-+using namespace js::irregexp;
-+using namespace js::jit;
-+
-+namespace v8 {
-+namespace internal {
-+
-+using js::MatchPairs;
-+using js::jit::AbsoluteAddress;
-+using js::jit::Address;
-+using js::jit::AllocatableGeneralRegisterSet;
-+using js::jit::Assembler;
-+using js::jit::BaseIndex;
-+using js::jit::CodeLocationLabel;
-+using js::jit::GeneralRegisterBackwardIterator;
-+using js::jit::GeneralRegisterForwardIterator;
-+using js::jit::GeneralRegisterSet;
-+using js::jit::Imm32;
-+using js::jit::ImmPtr;
-+using js::jit::ImmWord;
-+using js::jit::JitCode;
-+using js::jit::Linker;
-+using js::jit::LiveGeneralRegisterSet;
-+using js::jit::Register;
-+using js::jit::Registers;
-+using js::jit::StackMacroAssembler;
-+
-+SMRegExpMacroAssembler::SMRegExpMacroAssembler(JSContext* cx,
-+                                               StackMacroAssembler& masm,
-+                                               Zone* zone, Mode mode,
-+                                               uint32_t num_capture_registers)
-+    : NativeRegExpMacroAssembler(cx->isolate, zone),
-+      cx_(cx),
-+      masm_(masm),
-+      mode_(mode),
-+      num_registers_(num_capture_registers),
-+      num_capture_registers_(num_capture_registers) {
-+  // Each capture has a start and an end register
-+  MOZ_ASSERT(num_capture_registers_ % 2 == 0);
-+
-+  AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
-+
-+  temp0_ = regs.takeAny();
-+  temp1_ = regs.takeAny();
-+  temp2_ = regs.takeAny();
-+  input_end_pointer_ = regs.takeAny();
-+  current_character_ = regs.takeAny();
-+  current_position_ = regs.takeAny();
-+  backtrack_stack_pointer_ = regs.takeAny();
-+  savedRegisters_ = js::jit::SavedNonVolatileRegisters(regs);
-+
-+  masm_.jump(&entry_label_);  // We'll generate the entry code later
-+  masm_.bind(&start_label_);  // and continue from here.
-+}
-+
-+int SMRegExpMacroAssembler::stack_limit_slack() {
-+  return RegExpStack::kStackLimitSlack;
-+}
-+
-+void SMRegExpMacroAssembler::AdvanceCurrentPosition(int by) {
-+  if (by != 0) {
-+    masm_.addPtr(Imm32(by * char_size()), current_position_);
-+  }
-+}
-+
-+void SMRegExpMacroAssembler::AdvanceRegister(int reg, int by) {
-+  MOZ_ASSERT(reg >= 0 && reg < num_registers_);
-+  if (by != 0) {
-+    masm_.addPtr(Imm32(by), register_location(reg));
-+  }
-+}
-+
-+void SMRegExpMacroAssembler::Backtrack() {
-+  // Check for an interrupt. We have to restart from the beginning if we
-+  // are interrupted, so we only check for urgent interrupts.
-+  js::jit::Label noInterrupt;
-+  masm_.branch32(Assembler::Equal,
-+                 AbsoluteAddress(cx_->addressOfInterruptRegExpJit()), Imm32(0),
-+                 &noInterrupt);
-+  masm_.movePtr(ImmWord(js::RegExpRunStatus_Error), temp0_);
-+  masm_.jump(&exit_label_);
-+  masm_.bind(&noInterrupt);
-+
-+  // Pop code location from backtrack stack and jump to location.
-+  Pop(temp0_);
-+  masm_.jump(temp0_);
-+}
-+
-+void SMRegExpMacroAssembler::Bind(Label* label) {
-+  masm_.bind(label->inner());
-+  if (label->patchOffset_.bound()) {
-+    AddLabelPatch(label->patchOffset_, label->pos());
-+  }
-+}
-+
-+// Check if current_position + cp_offset is the input start
-+void SMRegExpMacroAssembler::CheckAtStartImpl(int cp_offset, Label* on_cond,
-+                                              Assembler::Condition cond) {
-+  Address addr(current_position_, cp_offset * char_size());
-+  masm_.computeEffectiveAddress(addr, temp0_);
-+
-+  masm_.branchPtr(cond, inputStart(), temp0_, LabelOrBacktrack(on_cond));
-+}
-+
-+void SMRegExpMacroAssembler::CheckAtStart(int cp_offset, Label* on_at_start) {
-+  CheckAtStartImpl(cp_offset, on_at_start, Assembler::Equal);
-+}
-+
-+void SMRegExpMacroAssembler::CheckNotAtStart(int cp_offset,
-+                                             Label* on_not_at_start) {
-+  CheckAtStartImpl(cp_offset, on_not_at_start, Assembler::NotEqual);
-+}
-+
-+void SMRegExpMacroAssembler::CheckCharacterImpl(Imm32 c, Label* on_cond,
-+                                                Assembler::Condition cond) {
-+  masm_.branch32(cond, current_character_, c, LabelOrBacktrack(on_cond));
-+}
-+
-+void SMRegExpMacroAssembler::CheckCharacter(uint32_t c, Label* on_equal) {
-+  CheckCharacterImpl(Imm32(c), on_equal, Assembler::Equal);
-+}
-+
-+void SMRegExpMacroAssembler::CheckNotCharacter(uint32_t c,
-+                                               Label* on_not_equal) {
-+  CheckCharacterImpl(Imm32(c), on_not_equal, Assembler::NotEqual);
-+}
-+
-+void SMRegExpMacroAssembler::CheckCharacterGT(uc16 c, Label* on_greater) {
-+  CheckCharacterImpl(Imm32(c), on_greater, Assembler::GreaterThan);
-+}
-+
-+void SMRegExpMacroAssembler::CheckCharacterLT(uc16 c, Label* on_less) {
-+  CheckCharacterImpl(Imm32(c), on_less, Assembler::LessThan);
-+}
-+
-+// Bitwise-and the current character with mask and then check for a
-+// match with c.
-+void SMRegExpMacroAssembler::CheckCharacterAfterAndImpl(uint32_t c,
-+                                                        uint32_t mask,
-+                                                        Label* on_cond,
-+                                                        bool is_not) {
-+  if (c == 0) {
-+    Assembler::Condition cond = is_not ? Assembler::NonZero : Assembler::Zero;
-+    masm_.branchTest32(cond, current_character_, Imm32(mask),
-+                       LabelOrBacktrack(on_cond));
-+  } else {
-+    Assembler::Condition cond = is_not ? Assembler::NotEqual : Assembler::Equal;
-+    masm_.move32(Imm32(mask), temp0_);
-+    masm_.and32(current_character_, temp0_);
-+    masm_.branch32(cond, temp0_, Imm32(c), LabelOrBacktrack(on_cond));
-+  }
-+}
-+
-+void SMRegExpMacroAssembler::CheckCharacterAfterAnd(uint32_t c, uint32_t mask,
-+                                                    Label* on_equal) {
-+  CheckCharacterAfterAndImpl(c, mask, on_equal, /*is_not =*/false);
-+}
-+
-+void SMRegExpMacroAssembler::CheckNotCharacterAfterAnd(uint32_t c,
-+                                                       uint32_t mask,
-+                                                       Label* on_not_equal) {
-+  CheckCharacterAfterAndImpl(c, mask, on_not_equal, /*is_not =*/true);
-+}
-+
-+// Subtract minus from the current character, then bitwise-and the
-+// result with mask, then check for a match with c.
-+void SMRegExpMacroAssembler::CheckNotCharacterAfterMinusAnd(
-+    uc16 c, uc16 minus, uc16 mask, Label* on_not_equal) {
-+  masm_.computeEffectiveAddress(Address(current_character_, -minus), temp0_);
-+  if (c == 0) {
-+    masm_.branchTest32(Assembler::NonZero, temp0_, Imm32(mask),
-+                       LabelOrBacktrack(on_not_equal));
-+  } else {
-+    masm_.and32(Imm32(mask), temp0_);
-+    masm_.branch32(Assembler::NotEqual, temp0_, Imm32(c),
-+                   LabelOrBacktrack(on_not_equal));
-+  }
-+}
-+
-+// If the current position matches the position stored on top of the backtrack
-+// stack, pops the backtrack stack and branches to the given label.
-+void SMRegExpMacroAssembler::CheckGreedyLoop(Label* on_equal) {
-+  js::jit::Label fallthrough;
-+  masm_.branchPtr(Assembler::NotEqual, Address(backtrack_stack_pointer_, 0),
-+                  current_position_, &fallthrough);
-+  masm_.addPtr(Imm32(sizeof(void*)), backtrack_stack_pointer_);  // Pop.
-+  JumpOrBacktrack(on_equal);
-+  masm_.bind(&fallthrough);
-+}
-+
-+void SMRegExpMacroAssembler::CheckCharacterInRangeImpl(
-+    uc16 from, uc16 to, Label* on_cond, Assembler::Condition cond) {
-+  // x is in [from,to] if unsigned(x - from) <= to - from
-+  masm_.computeEffectiveAddress(Address(current_character_, -from), temp0_);
-+  masm_.branch32(cond, temp0_, Imm32(to - from), LabelOrBacktrack(on_cond));
-+}
-+
-+void SMRegExpMacroAssembler::CheckCharacterInRange(uc16 from, uc16 to,
-+                                                   Label* on_in_range) {
-+  CheckCharacterInRangeImpl(from, to, on_in_range, Assembler::BelowOrEqual);
-+}
-+
-+void SMRegExpMacroAssembler::CheckCharacterNotInRange(uc16 from, uc16 to,
-+                                                      Label* on_not_in_range) {
-+  CheckCharacterInRangeImpl(from, to, on_not_in_range, Assembler::Above);
-+}
-+
-+void SMRegExpMacroAssembler::CheckBitInTable(Handle<ByteArray> table,
-+                                             Label* on_bit_set) {
-+  // Claim ownership of the ByteArray from the current HandleScope.
-+  // ByteArrays are allocated on the C++ heap and are (eventually)
-+  // owned by the RegExpShared.
-+  PseudoHandle<ByteArrayData> rawTable = table->takeOwnership(isolate());
-+
-+  masm_.movePtr(ImmPtr(rawTable->data()), temp0_);
-+
-+  masm_.move32(Imm32(kTableMask), temp1_);
-+  masm_.and32(current_character_, temp1_);
-+
-+  masm_.load8ZeroExtend(BaseIndex(temp0_, temp1_, js::jit::TimesOne), temp0_);
-+  masm_.branchTest32(Assembler::NonZero, temp0_, temp0_,
-+                     LabelOrBacktrack(on_bit_set));
-+
-+  // Transfer ownership of |rawTable| to the |tables_| vector.
-+  AddTable(std::move(rawTable));
-+}
-+
-+void SMRegExpMacroAssembler::CheckNotBackReferenceImpl(int start_reg,
-+                                                       bool read_backward,
-+                                                       bool unicode,
-+                                                       Label* on_no_match,
-+                                                       bool ignore_case) {
-+  js::jit::Label fallthrough;
-+
-+  // Captures are stored as a sequential pair of registers.
-+  // Find the length of the back-referenced capture and load the
-+  // capture's start index into current_character_.
-+  masm_.loadPtr(register_location(start_reg),  // index of start
-+                current_character_);
-+  masm_.loadPtr(register_location(start_reg + 1), temp0_);  // index of end
-+  masm_.subPtr(current_character_, temp0_);                 // length of capture
-+
-+  // Capture registers are either both set or both cleared.
-+  // If the capture length is zero, then the capture is either empty or cleared.
-+  // Fall through in both cases.
-+  masm_.branchPtr(Assembler::Equal, temp0_, ImmWord(0), &fallthrough);
-+
-+  // Check that there are sufficient characters left in the input.
-+  if (read_backward) {
-+    // If start + len > current, there isn't enough room for a
-+    // lookbehind backreference.
-+    masm_.loadPtr(inputStart(), temp1_);
-+    masm_.addPtr(temp0_, temp1_);
-+    masm_.branchPtr(Assembler::GreaterThan, temp1_, current_position_,
-+                    LabelOrBacktrack(on_no_match));
-+  } else {
-+    // current_position_ is the negative offset from the end.
-+    // If current + len > 0, there isn't enough room for a backreference.
-+    masm_.movePtr(current_position_, temp1_);
-+    masm_.addPtr(temp0_, temp1_);
-+    masm_.branchPtr(Assembler::GreaterThan, temp1_, ImmWord(0),
-+                    LabelOrBacktrack(on_no_match));
-+  }
-+
-+  if (mode_ == UC16 && ignore_case) {
-+    // We call a helper function for case-insensitive non-latin1 strings.
-+
-+    // Save volatile regs. temp1_, temp2_, and current_character_
-+    // don't need to be saved.  current_position_ needs to be saved
-+    // even if it's non-volatile, because we modify it to use as an argument.
-+    LiveGeneralRegisterSet volatileRegs(GeneralRegisterSet::Volatile());
-+    volatileRegs.addUnchecked(current_position_);
-+    volatileRegs.takeUnchecked(temp1_);
-+    volatileRegs.takeUnchecked(temp2_);
-+    volatileRegs.takeUnchecked(current_character_);
-+    masm_.PushRegsInMask(volatileRegs);
-+
-+    // Parameters are
-+    //   Address captured - Address of captured substring's start.
-+    //   Address current - Address of current character position.
-+    //   size_t byte_length - length of capture (in bytes)
-+
-+    // Compute |captured|
-+    masm_.addPtr(input_end_pointer_, current_character_);
-+
-+    // Compute |current|
-+    masm_.addPtr(input_end_pointer_, current_position_);
-+    if (read_backward) {
-+      // Offset by length when matching backwards.
-+      masm_.subPtr(temp0_, current_position_);
-+    }
-+
-+    masm_.setupUnalignedABICall(temp1_);
-+    masm_.passABIArg(current_character_);
-+    masm_.passABIArg(current_position_);
-+    masm_.passABIArg(temp0_);
-+
-+    if (unicode) {
-+      uint32_t (*fun)(const char16_t*, const char16_t*, size_t) =
-+          CaseInsensitiveCompareUnicode;
-+      masm_.callWithABI(JS_FUNC_TO_DATA_PTR(void*, fun));
-+    } else {
-+      uint32_t (*fun)(const char16_t*, const char16_t*, size_t) =
-+          CaseInsensitiveCompareNonUnicode;
-+      masm_.callWithABI(JS_FUNC_TO_DATA_PTR(void*, fun));
-+    }
-+    masm_.storeCallInt32Result(temp1_);
-+    masm_.PopRegsInMask(volatileRegs);
-+    masm_.branchTest32(Assembler::Zero, temp1_, temp1_,
-+                       LabelOrBacktrack(on_no_match));
-+
-+    // On success, advance position by length of capture
-+    if (read_backward) {
-+      masm_.subPtr(temp0_, current_position_);
-+    } else {
-+      masm_.addPtr(temp0_, current_position_);
-+    }
-+
-+    masm_.bind(&fallthrough);
-+    return;
-+  }
-+
-+  // We will be modifying current_position_. Save it in case the match fails.
-+  masm_.push(current_position_);
-+
-+  // Compute start of capture string
-+  masm_.addPtr(input_end_pointer_, current_character_);
-+
-+  // Compute start of match string
-+  masm_.addPtr(input_end_pointer_, current_position_);
-+  if (read_backward) {
-+    // Offset by length when matching backwards.
-+    masm_.subPtr(temp0_, current_position_);
-+  }
-+
-+  // Compute end of match string
-+  masm_.addPtr(current_position_, temp0_);
-+
-+  js::jit::Label success;
-+  js::jit::Label fail;
-+  js::jit::Label loop;
-+  masm_.bind(&loop);
-+
-+  // Load next character from each string.
-+  if (mode_ == LATIN1) {
-+    masm_.load8ZeroExtend(Address(current_character_, 0), temp1_);
-+    masm_.load8ZeroExtend(Address(current_position_, 0), temp2_);
-+  } else {
-+    masm_.load16ZeroExtend(Address(current_character_, 0), temp1_);
-+    masm_.load16ZeroExtend(Address(current_position_, 0), temp2_);
-+  }
-+
-+  if (ignore_case) {
-+    MOZ_ASSERT(mode_ == LATIN1);
-+    // Try exact match.
-+    js::jit::Label loop_increment;
-+    masm_.branch32(Assembler::Equal, temp1_, temp2_, &loop_increment);
-+
-+    // Mismatch. Try case-insensitive match.
-+    // Force the capture character to lower case (by setting bit 0x20)
-+    // then check to see if it is a letter.
-+    js::jit::Label convert_match;
-+    masm_.or32(Imm32(0x20), temp1_);
-+
-+    // Check if it is in [a,z].
-+    masm_.computeEffectiveAddress(Address(temp1_, -'a'), temp2_);
-+    masm_.branch32(Assembler::BelowOrEqual, temp2_, Imm32('z' - 'a'),
-+                   &convert_match);
-+    // Check for values in range [224,254].
-+    // Exclude 247 (U+00F7 DIVISION SIGN).
-+    masm_.sub32(Imm32(224 - 'a'), temp2_);
-+    masm_.branch32(Assembler::Above, temp2_, Imm32(254 - 224), &fail);
-+    masm_.branch32(Assembler::Equal, temp2_, Imm32(247 - 224), &fail);
-+
-+    // Capture character is lower case. Convert match character
-+    // to lower case and compare.
-+    masm_.bind(&convert_match);
-+    masm_.load8ZeroExtend(Address(current_position_, 0), temp2_);
-+    masm_.or32(Imm32(0x20), temp2_);
-+    masm_.branch32(Assembler::NotEqual, temp1_, temp2_, &fail);
-+
-+    masm_.bind(&loop_increment);
-+  } else {
-+    // Fail if characters do not match.
-+    masm_.branch32(Assembler::NotEqual, temp1_, temp2_, &fail);
-+  }
-+
-+  // Increment pointers into match and capture strings.
-+  masm_.addPtr(Imm32(char_size()), current_character_);
-+  masm_.addPtr(Imm32(char_size()), current_position_);
-+
-+  // Loop if we have not reached the end of the match string.
-+  masm_.branchPtr(Assembler::Below, current_position_, temp0_, &loop);
-+  masm_.jump(&success);
-+
-+  // If we fail, restore current_position_ and branch.
-+  masm_.bind(&fail);
-+  masm_.pop(current_position_);
-+  JumpOrBacktrack(on_no_match);
-+
-+  masm_.bind(&success);
-+
-+  // Drop saved value of current_position_
-+  masm_.addToStackPtr(Imm32(sizeof(uintptr_t)));
-+
-+  // current_position_ is a pointer. Convert it back to an offset.
-+  masm_.subPtr(input_end_pointer_, current_position_);
-+  if (read_backward) {
-+    // Subtract match length if we matched backward
-+    masm_.addPtr(register_location(start_reg), current_position_);
-+    masm_.subPtr(register_location(start_reg + 1), current_position_);
-+  }
-+
-+  masm_.bind(&fallthrough);
-+}
-+
-+// Branch if a back-reference does not match a previous capture.
-+void SMRegExpMacroAssembler::CheckNotBackReference(int start_reg,
-+                                                   bool read_backward,
-+                                                   Label* on_no_match) {
-+  CheckNotBackReferenceImpl(start_reg, read_backward, /*unicode = */ false,
-+                            on_no_match, /*ignore_case = */ false);
-+}
-+
-+void SMRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(
-+    int start_reg, bool read_backward, bool unicode, Label* on_no_match) {
-+  CheckNotBackReferenceImpl(start_reg, read_backward, unicode, on_no_match,
-+                            /*ignore_case = */ true);
-+}
-+
-+// Checks whether the given offset from the current position is
-+// inside the input string.
-+void SMRegExpMacroAssembler::CheckPosition(int cp_offset,
-+                                           Label* on_outside_input) {
-+  // Note: current_position_ is a (negative) byte offset relative to
-+  // the end of the input string.
-+  if (cp_offset >= 0) {
-+    //      end + current + offset >= end
-+    // <=>        current + offset >= 0
-+    // <=>        current          >= -offset
-+    masm_.branchPtr(Assembler::GreaterThanOrEqual, current_position_,
-+                    ImmWord(-cp_offset * char_size()),
-+                    LabelOrBacktrack(on_outside_input));
-+  } else {
-+    // Compute offset position
-+    masm_.computeEffectiveAddress(
-+        Address(current_position_, cp_offset * char_size()), temp0_);
-+
-+    // Compare to start of input.
-+    masm_.branchPtr(Assembler::GreaterThan, inputStart(), temp0_,
-+                    LabelOrBacktrack(on_outside_input));
-+  }
-+}
-+
-+// This function attempts to generate special case code for character classes.
-+// Returns true if a special case is generated.
-+// Otherwise returns false and generates no code.
-+bool SMRegExpMacroAssembler::CheckSpecialCharacterClass(uc16 type,
-+                                                        Label* on_no_match) {
-+  js::jit::Label* no_match = LabelOrBacktrack(on_no_match);
-+
-+  // Note: throughout this function, range checks (c in [min, max])
-+  // are implemented by an unsigned (c - min) <= (max - min) check.
-+  switch (type) {
-+    case 's': {
-+      // Match space-characters
-+      if (mode_ != LATIN1) {
-+        return false;
-+      }
-+      js::jit::Label success;
-+      // One byte space characters are ' ', '\t'..'\r', and '\u00a0' (NBSP).
-+
-+      // Check ' '
-+      masm_.branch32(Assembler::Equal, current_character_, Imm32(' '),
-+                     &success);
-+
-+      // Check '\t'..'\r'
-+      masm_.computeEffectiveAddress(Address(current_character_, -'\t'), temp0_);
-+      masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32('\r' - '\t'),
-+                     &success);
-+
-+      // Check \u00a0.
-+      masm_.branch32(Assembler::NotEqual, temp0_, Imm32(0x00a0 - '\t'),
-+                     no_match);
-+
-+      masm_.bind(&success);
-+      return true;
-+    }
-+    case 'S':
-+      // The emitted code for generic character classes is good enough.
-+      return false;
-+    case 'd':
-+      // Match latin1 digits ('0'-'9')
-+      masm_.computeEffectiveAddress(Address(current_character_, -'0'), temp0_);
-+      masm_.branch32(Assembler::Above, temp0_, Imm32('9' - '0'), no_match);
-+      return true;
-+    case 'D':
-+      // Match anything except latin1 digits ('0'-'9')
-+      masm_.computeEffectiveAddress(Address(current_character_, -'0'), temp0_);
-+      masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32('9' - '0'),
-+                     no_match);
-+      return true;
-+    case '.':
-+      // Match non-newlines. This excludes '\n' (0x0a), '\r' (0x0d),
-+      // U+2028 LINE SEPARATOR, and U+2029 PARAGRAPH SEPARATOR.
-+      // See https://tc39.es/ecma262/#prod-LineTerminator
-+
-+      // To test for 0x0a and 0x0d efficiently, we XOR the input with 1.
-+      // This converts 0x0a to 0x0b, and 0x0d to 0x0c, allowing us to
-+      // test for the contiguous range 0x0b..0x0c.
-+      masm_.move32(current_character_, temp0_);
-+      masm_.xor32(Imm32(0x01), temp0_);
-+      masm_.sub32(Imm32(0x0b), temp0_);
-+      masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32(0x0c - 0x0b),
-+                     no_match);
-+
-+      if (mode_ == UC16) {
-+        // Compare original value to 0x2028 and 0x2029, using the already
-+        // computed (current_char ^ 0x01 - 0x0b). I.e., check for
-+        // 0x201d (0x2028 - 0x0b) or 0x201e.
-+        masm_.sub32(Imm32(0x2028 - 0x0b), temp0_);
-+        masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32(0x2029 - 0x2028),
-+                       no_match);
-+      }
-+      return true;
-+    case 'w':
-+      // \w matches the set of 63 characters defined in Runtime Semantics:
-+      // WordCharacters. We use a static lookup table, which is defined in
-+      // regexp-macro-assembler.cc.
-+      // Note: if both Unicode and IgnoreCase are true, \w matches a
-+      // larger set of characters. That case is handled elsewhere.
-+      if (mode_ != LATIN1) {
-+        masm_.branch32(Assembler::Above, current_character_, Imm32('z'),
-+                       no_match);
-+      }
-+      static_assert(
-+          arraysize(word_character_map) > unibrow::Latin1::kMaxChar,
-+          "regex: arraysize(word_character_map) > unibrow::Latin1::kMaxChar");
-+      masm_.movePtr(ImmPtr(word_character_map), temp0_);
-+      masm_.load8ZeroExtend(
-+          BaseIndex(temp0_, current_character_, js::jit::TimesOne), temp0_);
-+      masm_.branchTest32(Assembler::Zero, temp0_, temp0_, no_match);
-+      return true;
-+    case 'W': {
-+      // See 'w' above.
-+      js::jit::Label done;
-+      if (mode_ != LATIN1) {
-+        masm_.branch32(Assembler::Above, current_character_, Imm32('z'), &done);
-+      }
-+      static_assert(
-+          arraysize(word_character_map) > unibrow::Latin1::kMaxChar,
-+          "regex: arraysize(word_character_map) > unibrow::Latin1::kMaxChar");
-+      masm_.movePtr(ImmPtr(word_character_map), temp0_);
-+      masm_.load8ZeroExtend(
-+          BaseIndex(temp0_, current_character_, js::jit::TimesOne), temp0_);
-+      masm_.branchTest32(Assembler::NonZero, temp0_, temp0_, no_match);
-+      if (mode_ != LATIN1) {
-+        masm_.bind(&done);
-+      }
-+      return true;
-+    }
-+      ////////////////////////////////////////////////////////////////////////
-+      // Non-standard classes (with no syntactic shorthand) used internally //
-+      ////////////////////////////////////////////////////////////////////////
-+    case '*':
-+      // Match any character
-+      return true;
-+    case 'n':
-+      // Match newlines. The opposite of '.'. See '.' above.
-+      masm_.move32(current_character_, temp0_);
-+      masm_.xor32(Imm32(0x01), temp0_);
-+      masm_.sub32(Imm32(0x0b), temp0_);
-+      if (mode_ == LATIN1) {
-+        masm_.branch32(Assembler::Above, temp0_, Imm32(0x0c - 0x0b), no_match);
-+      } else {
-+        MOZ_ASSERT(mode_ == UC16);
-+        js::jit::Label done;
-+        masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32(0x0c - 0x0b),
-+                       &done);
-+
-+        // Compare original value to 0x2028 and 0x2029, using the already
-+        // computed (current_char ^ 0x01 - 0x0b). I.e., check for
-+        // 0x201d (0x2028 - 0x0b) or 0x201e.
-+        masm_.sub32(Imm32(0x2028 - 0x0b), temp0_);
-+        masm_.branch32(Assembler::Above, temp0_, Imm32(0x2029 - 0x2028),
-+                       no_match);
-+        masm_.bind(&done);
-+      }
-+      return true;
-+
-+      // No custom implementation
-+    default:
-+      return false;
-+  }
-+}
-+
-+void SMRegExpMacroAssembler::Fail() {
-+  masm_.movePtr(ImmWord(js::RegExpRunStatus_Success_NotFound), temp0_);
-+  masm_.jump(&exit_label_);
-+}
-+
-+void SMRegExpMacroAssembler::GoTo(Label* to) {
-+  masm_.jump(LabelOrBacktrack(to));
-+}
-+
-+void SMRegExpMacroAssembler::IfRegisterGE(int reg, int comparand,
-+                                          Label* if_ge) {
-+  masm_.branchPtr(Assembler::GreaterThanOrEqual, register_location(reg),
-+                  ImmWord(comparand), LabelOrBacktrack(if_ge));
-+}
-+
-+void SMRegExpMacroAssembler::IfRegisterLT(int reg, int comparand,
-+                                          Label* if_lt) {
-+  masm_.branchPtr(Assembler::LessThan, register_location(reg),
-+                  ImmWord(comparand), LabelOrBacktrack(if_lt));
-+}
-+
-+void SMRegExpMacroAssembler::IfRegisterEqPos(int reg, Label* if_eq) {
-+  masm_.branchPtr(Assembler::Equal, register_location(reg), current_position_,
-+                  LabelOrBacktrack(if_eq));
-+}
-+
-+// This is a word-for-word identical copy of the V8 code, which is
-+// duplicated in at least nine different places in V8 (one per
-+// supported architecture) with no differences outside of comments and
-+// formatting. It should be hoisted into the superclass. Once that is
-+// done upstream, this version can be deleted.
-+void SMRegExpMacroAssembler::LoadCurrentCharacterImpl(int cp_offset,
-+                                                      Label* on_end_of_input,
-+                                                      bool check_bounds,
-+                                                      int characters,
-+                                                      int eats_at_least) {
-+  // It's possible to preload a small number of characters when each success
-+  // path requires a large number of characters, but not the reverse.
-+  MOZ_ASSERT(eats_at_least >= characters);
-+  MOZ_ASSERT(cp_offset < (1 << 30));  // Be sane! (And ensure negation works)
-+
-+  if (check_bounds) {
-+    if (cp_offset >= 0) {
-+      CheckPosition(cp_offset + eats_at_least - 1, on_end_of_input);
-+    } else {
-+      CheckPosition(cp_offset, on_end_of_input);
-+    }
-+  }
-+  LoadCurrentCharacterUnchecked(cp_offset, characters);
-+}
-+
-+// Load the character (or characters) at the specified offset from the
-+// current position. Zero-extend to 32 bits.
-+void SMRegExpMacroAssembler::LoadCurrentCharacterUnchecked(int cp_offset,
-+                                                           int characters) {
-+  BaseIndex address(input_end_pointer_, current_position_, js::jit::TimesOne,
-+                    cp_offset * char_size());
-+  if (mode_ == LATIN1) {
-+    if (characters == 4) {
-+      masm_.load32(address, current_character_);
-+    } else if (characters == 2) {
-+      masm_.load16ZeroExtend(address, current_character_);
-+    } else {
-+      MOZ_ASSERT(characters == 1);
-+      masm_.load8ZeroExtend(address, current_character_);
-+    }
-+  } else {
-+    MOZ_ASSERT(mode_ == UC16);
-+    if (characters == 2) {
-+      masm_.load32(address, current_character_);
-+    } else {
-+      MOZ_ASSERT(characters == 1);
-+      masm_.load16ZeroExtend(address, current_character_);
-+    }
-+  }
-+}
-+
-+void SMRegExpMacroAssembler::PopCurrentPosition() { Pop(current_position_); }
-+
-+void SMRegExpMacroAssembler::PopRegister(int register_index) {
-+  Pop(temp0_);
-+  masm_.storePtr(temp0_, register_location(register_index));
-+}
-+
-+void SMRegExpMacroAssembler::PushBacktrack(Label* label) {
-+  MOZ_ASSERT(!label->is_bound());
-+  MOZ_ASSERT(!label->patchOffset_.bound());
-+  label->patchOffset_ = masm_.movWithPatch(ImmPtr(nullptr), temp0_);
-+  MOZ_ASSERT(label->patchOffset_.bound());
-+
-+  Push(temp0_);
-+
-+  CheckBacktrackStackLimit();
-+}
-+
-+void SMRegExpMacroAssembler::PushCurrentPosition() { Push(current_position_); }
-+
-+void SMRegExpMacroAssembler::PushRegister(int register_index,
-+                                          StackCheckFlag check_stack_limit) {
-+  masm_.loadPtr(register_location(register_index), temp0_);
-+  Push(temp0_);
-+  if (check_stack_limit) {
-+    CheckBacktrackStackLimit();
-+  }
-+}
-+
-+void SMRegExpMacroAssembler::ReadCurrentPositionFromRegister(int reg) {
-+  masm_.loadPtr(register_location(reg), current_position_);
-+}
-+
-+void SMRegExpMacroAssembler::WriteCurrentPositionToRegister(int reg,
-+                                                            int cp_offset) {
-+  if (cp_offset == 0) {
-+    masm_.storePtr(current_position_, register_location(reg));
-+  } else {
-+    Address addr(current_position_, cp_offset * char_size());
-+    masm_.computeEffectiveAddress(addr, temp0_);
-+    masm_.storePtr(temp0_, register_location(reg));
-+  }
-+}
-+
-+// Note: The backtrack stack pointer is stored in a register as an
-+// offset from the stack top, not as a bare pointer, so that it is not
-+// corrupted if the backtrack stack grows (and therefore moves).
-+void SMRegExpMacroAssembler::ReadStackPointerFromRegister(int reg) {
-+  masm_.loadPtr(register_location(reg), backtrack_stack_pointer_);
-+  masm_.addPtr(backtrackStackBase(), backtrack_stack_pointer_);
-+}
-+void SMRegExpMacroAssembler::WriteStackPointerToRegister(int reg) {
-+  masm_.movePtr(backtrack_stack_pointer_, temp0_);
-+  masm_.subPtr(backtrackStackBase(), temp0_);
-+  masm_.storePtr(temp0_, register_location(reg));
-+}
-+
-+// When matching a regexp that is anchored at the end, this operation
-+// is used to try skipping the beginning of long strings. If the
-+// maximum length of a match is less than the length of the string, we
-+// can skip the initial len - max_len bytes.
-+void SMRegExpMacroAssembler::SetCurrentPositionFromEnd(int by) {
-+  js::jit::Label after_position;
-+  masm_.branchPtr(Assembler::GreaterThanOrEqual, current_position_,
-+                  ImmWord(-by * char_size()), &after_position);
-+  masm_.movePtr(ImmWord(-by * char_size()), current_position_);
-+
-+  // On RegExp code entry (where this operation is used), the character before
-+  // the current position is expected to be already loaded.
-+  // We have advanced the position, so it's safe to read backwards.
-+  LoadCurrentCharacterUnchecked(-1, 1);
-+  masm_.bind(&after_position);
-+}
-+
-+void SMRegExpMacroAssembler::SetRegister(int register_index, int to) {
-+  MOZ_ASSERT(register_index >= num_capture_registers_);
-+  masm_.storePtr(ImmWord(to), register_location(register_index));
-+}
-+
-+// Returns true if a regexp match can be restarted (aka the regexp is global).
-+// The return value is not used anywhere, but we implement it to be safe.
-+bool SMRegExpMacroAssembler::Succeed() {
-+  masm_.jump(&success_label_);
-+  return global();
-+}
-+
-+// Capture registers are initialized to input[-1]
-+void SMRegExpMacroAssembler::ClearRegisters(int reg_from, int reg_to) {
-+  MOZ_ASSERT(reg_from <= reg_to);
-+  masm_.loadPtr(inputStart(), temp0_);
-+  masm_.subPtr(Imm32(char_size()), temp0_);
-+  for (int reg = reg_from; reg <= reg_to; reg++) {
-+    masm_.storePtr(temp0_, register_location(reg));
-+  }
-+}
-+
-+void SMRegExpMacroAssembler::Push(Register source) {
-+  MOZ_ASSERT(source != backtrack_stack_pointer_);
-+
-+  masm_.subPtr(Imm32(sizeof(void*)), backtrack_stack_pointer_);
-+  masm_.storePtr(source, Address(backtrack_stack_pointer_, 0));
-+}
-+
-+void SMRegExpMacroAssembler::Pop(Register target) {
-+  MOZ_ASSERT(target != backtrack_stack_pointer_);
-+
-+  masm_.loadPtr(Address(backtrack_stack_pointer_, 0), target);
-+  masm_.addPtr(Imm32(sizeof(void*)), backtrack_stack_pointer_);
-+}
-+
-+void SMRegExpMacroAssembler::JumpOrBacktrack(Label* to) {
-+  if (to) {
-+    masm_.jump(to->inner());
-+  } else {
-+    Backtrack();
-+  }
-+}
-+
-+// Generate a quick inline test for backtrack stack overflow.
-+// If the test fails, call an OOL handler to try growing the stack.
-+void SMRegExpMacroAssembler::CheckBacktrackStackLimit() {
-+  js::jit::Label no_stack_overflow;
-+  masm_.branchPtr(
-+      Assembler::BelowOrEqual,
-+      AbsoluteAddress(isolate()->regexp_stack()->limit_address_address()),
-+      backtrack_stack_pointer_, &no_stack_overflow);
-+
-+  masm_.call(&stack_overflow_label_);
-+
-+  // Exit with an exception if the call failed
-+  masm_.branchTest32(Assembler::Zero, temp0_, temp0_,
-+                     &exit_with_exception_label_);
-+
-+  masm_.bind(&no_stack_overflow);
-+}
-+
-+// This is used to sneak an OOM through the V8 layer.
-+static Handle<HeapObject> DummyCode() {
-+  return Handle<HeapObject>::fromHandleValue(JS::UndefinedHandleValue);
-+}
-+
-+// Finalize code. This is called last, so that we know how many
-+// registers we need.
-+Handle<HeapObject> SMRegExpMacroAssembler::GetCode(Handle<String> source) {
-+  if (!cx_->compartment()->ensureJitCompartmentExists(cx_)) {
-+    return DummyCode();
-+  }
-+
-+  masm_.bind(&entry_label_);
-+
-+  createStackFrame();
-+  initFrameAndRegs();
-+
-+  masm_.jump(&start_label_);
-+
-+  successHandler();
-+  exitHandler();
-+  backtrackHandler();
-+  stackOverflowHandler();
-+
-+  Linker linker(masm_);
-+  JitCode* code = linker.newCode<NoGC>(cx_, REGEXP_CODE);
-+  if (!code) {
-+    ReportOutOfMemory(cx_);
-+    return DummyCode();
-+  }
-+
-+  for (LabelPatch& lp : labelPatches_) {
-+    Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, lp.patchOffset_),
-+                                       ImmPtr(code->raw() + lp.labelOffset_),
-+                                       ImmPtr(nullptr));
-+  }
-+
-+  return Handle<HeapObject>(JS::PrivateGCThingValue(code), isolate());
-+}
-+
-+/*
-+ * The stack will have the following structure:
-+ *  sp-> - FrameData
-+ *         - inputStart
-+ *         - backtrack stack base
-+ *         - matches
-+ *         - numMatches
-+ *       - Registers
-+ *         - Capture positions
-+ *         - Scratch registers
-+ *       --- frame alignment ---
-+ *       - Saved register area
-+ *       - Return address
-+ */
-+void SMRegExpMacroAssembler::createStackFrame() {
-+#ifdef JS_CODEGEN_ARM64
-+  // ARM64 communicates stack address via SP, but uses a pseudo-sp (PSP) for
-+  // addressing.  The register we use for PSP may however also be used by
-+  // calling code, and it is nonvolatile, so save it.  Do this as a special
-+  // case first because the generic save/restore code needs the PSP to be
-+  // initialized already.
-+  MOZ_ASSERT(js::jit::PseudoStackPointer64.Is(masm_.GetStackPointer64()));
-+  masm_.Str(js::jit::PseudoStackPointer64,
-+            vixl::MemOperand(js::jit::sp, -16, vixl::PreIndex));
-+
-+  // Initialize the PSP from the SP.
-+  masm_.initPseudoStackPtr();
-+#endif
-+
-+  // Push non-volatile registers which might be modified by jitcode.
-+  size_t pushedNonVolatileRegisters = 0;
-+  for (GeneralRegisterForwardIterator iter(savedRegisters_); iter.more();
-+       ++iter) {
-+    masm_.Push(*iter);
-+    pushedNonVolatileRegisters++;
-+  }
-+
-+  // The pointer to InputOutputData is passed as the first argument.
-+  // On x86 we have to load it off the stack into temp0_.
-+  // On other platforms it is already in a register.
-+#ifdef JS_CODEGEN_X86
-+  Address ioDataAddr(masm_.getStackPointer(),
-+                     (pushedNonVolatileRegisters + 1) * sizeof(void*));
-+  masm_.loadPtr(ioDataAddr, temp0_);
-+#else
-+  if (js::jit::IntArgReg0 != temp0_) {
-+    masm_.movePtr(js::jit::IntArgReg0, temp0_);
-+  }
-+#endif
-+
-+  // Start a new stack frame.
-+  size_t frameBytes = sizeof(FrameData) + num_registers_ * sizeof(void*);
-+  frameSize_ = js::jit::StackDecrementForCall(js::jit::ABIStackAlignment,
-+                                              masm_.framePushed(), frameBytes);
-+  masm_.reserveStack(frameSize_);
-+  masm_.checkStackAlignment();
-+
-+  // Check if we have space on the stack. Use the *NoInterrupt stack limit to
-+  // avoid failing repeatedly when the regex code is called from Ion JIT code.
-+  // (See bug 1208819)
-+  js::jit::Label stack_ok;
-+  AbsoluteAddress limit_addr(cx_->addressOfJitStackLimitNoInterrupt());
-+  masm_.branchStackPtrRhs(Assembler::Below, limit_addr, &stack_ok);
-+
-+  // There is not enough space on the stack. Exit with an exception.
-+  masm_.movePtr(ImmWord(js::RegExpRunStatus_Error), temp0_);
-+  masm_.jump(&exit_label_);
-+
-+  masm_.bind(&stack_ok);
-+}
-+
-+void SMRegExpMacroAssembler::initFrameAndRegs() {
-+  // At this point, an uninitialized stack frame has been created,
-+  // and the address of the InputOutputData is in temp0_.
-+  Register ioDataReg = temp0_;
-+
-+  Register matchesReg = temp1_;
-+  masm_.loadPtr(Address(ioDataReg, offsetof(InputOutputData, matches)),
-+                matchesReg);
-+
-+  // Initialize output registers
-+  masm_.loadPtr(Address(matchesReg, MatchPairs::offsetOfPairs()), temp2_);
-+  masm_.storePtr(temp2_, matches());
-+  masm_.load32(Address(matchesReg, MatchPairs::offsetOfPairCount()), temp2_);
-+  masm_.store32(temp2_, numMatches());
-+
-+#ifdef DEBUG
-+  // Bounds-check numMatches.
-+  js::jit::Label enoughRegisters;
-+  masm_.branchPtr(Assembler::GreaterThanOrEqual, temp2_,
-+                  ImmWord(num_capture_registers_ / 2), &enoughRegisters);
-+  masm_.assumeUnreachable("Not enough output pairs for RegExp");
-+  masm_.bind(&enoughRegisters);
-+#endif
-+
-+  // Load input start pointer.
-+  masm_.loadPtr(Address(ioDataReg, offsetof(InputOutputData, inputStart)),
-+                current_position_);
-+
-+  // Load input end pointer
-+  masm_.loadPtr(Address(ioDataReg, offsetof(InputOutputData, inputEnd)),
-+                input_end_pointer_);
-+
-+  // Set up input position to be negative offset from string end.
-+  masm_.subPtr(input_end_pointer_, current_position_);
-+
-+  // Store inputStart
-+  masm_.storePtr(current_position_, inputStart());
-+
-+  // Load start index
-+  Register startIndexReg = temp1_;
-+  masm_.loadPtr(Address(ioDataReg, offsetof(InputOutputData, startIndex)),
-+                startIndexReg);
-+  masm_.computeEffectiveAddress(
-+      BaseIndex(current_position_, startIndexReg, factor()), current_position_);
-+
-+  // Initialize current_character_.
-+  // Load newline if index is at start, or previous character otherwise.
-+  js::jit::Label start_regexp;
-+  js::jit::Label load_previous_character;
-+  masm_.branchPtr(Assembler::NotEqual, startIndexReg, ImmWord(0),
-+                  &load_previous_character);
-+  masm_.movePtr(ImmWord('\n'), current_character_);
-+  masm_.jump(&start_regexp);
-+
-+  masm_.bind(&load_previous_character);
-+  LoadCurrentCharacterUnchecked(-1, 1);
-+  masm_.bind(&start_regexp);
-+
-+  // Initialize captured registers with inputStart - 1
-+  MOZ_ASSERT(num_capture_registers_ > 0);
-+  Register inputStartMinusOneReg = temp2_;
-+  masm_.loadPtr(inputStart(), inputStartMinusOneReg);
-+  masm_.subPtr(Imm32(char_size()), inputStartMinusOneReg);
-+  if (num_capture_registers_ > 8) {
-+    masm_.movePtr(ImmWord(register_offset(0)), temp1_);
-+    js::jit::Label init_loop;
-+    masm_.bind(&init_loop);
-+    masm_.storePtr(inputStartMinusOneReg, BaseIndex(masm_.getStackPointer(),
-+                                                    temp1_, js::jit::TimesOne));
-+    masm_.addPtr(ImmWord(sizeof(void*)), temp1_);
-+    masm_.branchPtr(Assembler::LessThan, temp1_,
-+                    ImmWord(register_offset(num_capture_registers_)),
-+                    &init_loop);
-+  } else {
-+    // Unroll the loop
-+    for (int i = 0; i < num_capture_registers_; i++) {
-+      masm_.storePtr(inputStartMinusOneReg, register_location(i));
-+    }
-+  }
-+
-+  // Initialize backtrack stack pointer
-+  masm_.loadPtr(AbsoluteAddress(isolate()->top_of_regexp_stack()),
-+                backtrack_stack_pointer_);
-+  masm_.storePtr(backtrack_stack_pointer_, backtrackStackBase());
-+}
-+
-+// Called when we find a match. May not be generated if we can
-+// determine ahead of time that a regexp cannot match: for example,
-+// when compiling /\u1e9e/ for latin-1 inputs.
-+void SMRegExpMacroAssembler::successHandler() {
-+  if (!success_label_.used()) {
-+    return;
-+  }
-+  masm_.bind(&success_label_);
-+
-+  // Copy captures to the MatchPairs pointed to by the InputOutputData.
-+  // Captures are stored as positions, which are negative byte offsets
-+  // from the end of the string.  We must convert them to actual
-+  // indices.
-+  //
-+  // Index:        [ 0 ][ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][END]
-+  // Pos (1-byte): [-6 ][-5 ][-4 ][-3 ][-2 ][-1 ][ 0 ] // IS = -6
-+  // Pos (2-byte): [-12][-10][-8 ][-6 ][-4 ][-2 ][ 0 ] // IS = -12
-+  //
-+  // To convert a position to an index, we subtract InputStart, and
-+  // divide the result by char_size.
-+  Register matchesReg = temp1_;
-+  masm_.loadPtr(matches(), matchesReg);
-+
-+  Register inputStartReg = temp2_;
-+  masm_.loadPtr(inputStart(), inputStartReg);
-+
-+  for (int i = 0; i < num_capture_registers_; i++) {
-+    masm_.loadPtr(register_location(i), temp0_);
-+    masm_.subPtr(inputStartReg, temp0_);
-+    if (mode_ == UC16) {
-+      masm_.rshiftPtrArithmetic(Imm32(1), temp0_);
-+    }
-+    masm_.store32(temp0_, Address(matchesReg, i * sizeof(int32_t)));
-+  }
-+
-+  masm_.movePtr(ImmWord(js::RegExpRunStatus_Success), temp0_);
-+  // This falls through to the exit handler.
-+}
-+
-+void SMRegExpMacroAssembler::exitHandler() {
-+  masm_.bind(&exit_label_);
-+
-+  if (temp0_ != js::jit::ReturnReg) {
-+    masm_.movePtr(temp0_, js::jit::ReturnReg);
-+  }
-+
-+  masm_.freeStack(frameSize_);
-+
-+  // Restore registers which were saved on entry
-+  for (GeneralRegisterBackwardIterator iter(savedRegisters_); iter.more();
-+       ++iter) {
-+    masm_.Pop(*iter);
-+  }
-+
-+#ifdef JS_CODEGEN_ARM64
-+  // Now restore the value that was in the PSP register on entry, and return.
-+
-+  // Obtain the correct SP from the PSP.
-+  masm_.Mov(js::jit::sp, js::jit::PseudoStackPointer64);
-+
-+  // Restore the saved value of the PSP register, this value is whatever the
-+  // caller had saved in it, not any actual SP value, and it must not be
-+  // overwritten subsequently.
-+  masm_.Ldr(js::jit::PseudoStackPointer64,
-+            vixl::MemOperand(js::jit::sp, 16, vixl::PostIndex));
-+
-+  // Perform a plain Ret(), as abiret() will move SP <- PSP and that is wrong.
-+  masm_.Ret(vixl::lr);
-+#else
-+  masm_.abiret();
-+#endif
-+
-+  if (exit_with_exception_label_.used()) {
-+    masm_.bind(&exit_with_exception_label_);
-+
-+    // Exit with an error result to signal thrown exception
-+    masm_.movePtr(ImmWord(js::RegExpRunStatus_Error), temp0_);
-+    masm_.jump(&exit_label_);
-+  }
-+}
-+
-+void SMRegExpMacroAssembler::backtrackHandler() {
-+  if (!backtrack_label_.used()) {
-+    return;
-+  }
-+  masm_.bind(&backtrack_label_);
-+  Backtrack();
-+}
-+
-+void SMRegExpMacroAssembler::stackOverflowHandler() {
-+  if (!stack_overflow_label_.used()) {
-+    return;
-+  }
-+
-+  // Called if the backtrack-stack limit has been hit.
-+  masm_.bind(&stack_overflow_label_);
-+
-+  // Load argument
-+  masm_.movePtr(ImmPtr(isolate()->regexp_stack()), temp1_);
-+
-+  // Save registers before calling C function
-+  LiveGeneralRegisterSet volatileRegs(GeneralRegisterSet::Volatile());
-+
-+#ifdef JS_USE_LINK_REGISTER
-+  masm_.pushReturnAddress();
-+#endif
-+
-+  // Adjust for the return address on the stack.
-+  size_t frameOffset = sizeof(void*);
-+
-+  volatileRegs.takeUnchecked(temp0_);
-+  volatileRegs.takeUnchecked(temp1_);
-+  masm_.PushRegsInMask(volatileRegs);
-+
-+  masm_.setupUnalignedABICall(temp0_);
-+  masm_.passABIArg(temp1_);
-+  masm_.callWithABI(JS_FUNC_TO_DATA_PTR(void*, GrowBacktrackStack));
-+  masm_.storeCallBoolResult(temp0_);
-+
-+  masm_.PopRegsInMask(volatileRegs);
-+
-+  // If GrowBacktrackStack returned false, we have failed to grow the
-+  // stack, and must exit with a stack-overflow exception. Do this in
-+  // the caller so that the stack is adjusted by our return instruction.
-+  js::jit::Label overflow_return;
-+  masm_.branchTest32(Assembler::Zero, temp0_, temp0_, &overflow_return);
-+
-+  // Otherwise, store the new backtrack stack base and recompute the new
-+  // top of the stack.
-+  Address bsbAddress(masm_.getStackPointer(),
-+                     offsetof(FrameData, backtrackStackBase) + frameOffset);
-+  masm_.subPtr(bsbAddress, backtrack_stack_pointer_);
-+
-+  masm_.loadPtr(AbsoluteAddress(isolate()->top_of_regexp_stack()), temp1_);
-+  masm_.storePtr(temp1_, bsbAddress);
-+  masm_.addPtr(temp1_, backtrack_stack_pointer_);
-+
-+  // Resume execution in calling code.
-+  masm_.bind(&overflow_return);
-+  masm_.ret();
-+}
-+
-+// This is only used by tracing code.
-+// The return value doesn't matter.
-+RegExpMacroAssembler::IrregexpImplementation
-+SMRegExpMacroAssembler::Implementation() {
-+  return kBytecodeImplementation;
-+}
-+
-+// Compare two strings in `/i` mode (ignoreCase, but not unicode).
-+/*static */
-+uint32_t SMRegExpMacroAssembler::CaseInsensitiveCompareNonUnicode(
-+    const char16_t* substring1, const char16_t* substring2, size_t byteLength) {
-+  JS::AutoCheckCannotGC nogc;
-+
-+  MOZ_ASSERT(byteLength % sizeof(char16_t) == 0);
-+  size_t length = byteLength / sizeof(char16_t);
-+
-+  for (size_t i = 0; i < length; i++) {
-+    char16_t c1 = substring1[i];
-+    char16_t c2 = substring2[i];
-+    if (c1 != c2) {
-+#ifdef JS_HAS_INTL_API
-+      // Non-unicode regexps have weird case-folding rules.
-+      c1 = RegExpCaseFolding::Canonicalize(c1);
-+      c2 = RegExpCaseFolding::Canonicalize(c2);
-+#else
-+      // If we aren't building with ICU, fall back to `/iu` mode. The only
-+      // differences are in corner cases.
-+      c1 = js::unicode::FoldCase(c1);
-+      c2 = js::unicode::FoldCase(c2);
-+#endif
-+      if (c1 != c2) {
-+        return 0;
-+      }
-+    }
-+  }
-+
-+  return 1;
-+}
-+
-+// Compare two strings in `/iu` mode (ignoreCase and unicode).
-+/*static */
-+uint32_t SMRegExpMacroAssembler::CaseInsensitiveCompareUnicode(
-+    const char16_t* substring1, const char16_t* substring2, size_t byteLength) {
-+  JS::AutoCheckCannotGC nogc;
-+
-+  MOZ_ASSERT(byteLength % sizeof(char16_t) == 0);
-+  size_t length = byteLength / sizeof(char16_t);
-+
-+  for (size_t i = 0; i < length; i++) {
-+    char16_t c1 = substring1[i];
-+    char16_t c2 = substring2[i];
-+    if (c1 != c2) {
-+      // Unicode regexps use the common and simple case-folding
-+      // mappings of the Unicode Character Database.
-+      c1 = js::unicode::FoldCase(c1);
-+      c2 = js::unicode::FoldCase(c2);
-+      if (c1 != c2) {
-+        return 0;
-+      }
-+    }
-+  }
-+
-+  return 1;
-+}
-+
-+/* static */
-+bool SMRegExpMacroAssembler::GrowBacktrackStack(RegExpStack* regexp_stack) {
-+  JS::AutoCheckCannotGC nogc;
-+  size_t size = regexp_stack->stack_capacity();
-+  return !!regexp_stack->EnsureCapacity(size * 2);
-+}
-+
-+bool SMRegExpMacroAssembler::CanReadUnaligned() {
-+#if defined(JS_CODEGEN_ARM)
-+  return !js::jit::HasAlignmentFault();
-+#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
-+  return false;
-+#else
-+  return true;
-+#endif
-+}
-+
-+}  // namespace internal
-+}  // namespace v8
-diff --git a/js/src/irregexp/RegExpNativeMacroAssembler.h b/js/src/irregexp/RegExpNativeMacroAssembler.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/RegExpNativeMacroAssembler.h
-@@ -0,0 +1,297 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+// Copyright 2020 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+// This file implements the NativeRegExpMacroAssembler interface for
-+// SpiderMonkey. It provides the same interface as each of V8's
-+// architecture-specific implementations.
-+
-+#ifndef RegexpMacroAssemblerArch_h
-+#define RegexpMacroAssemblerArch_h
-+
-+#include "irregexp/imported/regexp-macro-assembler.h"
-+#include "jit/MacroAssembler.h"
-+
-+namespace v8 {
-+namespace internal {
-+
-+struct FrameData {
-+  // Character position at the start of the input, stored as a
-+  // negative offset from the end of the string (input_end_pointer_).
-+  size_t inputStart;
-+
-+  // The backtrack_stack_pointer_ register points to the top of the stack.
-+  // This points to the bottom of the backtrack stack.
-+  void* backtrackStackBase;
-+
-+  // Copy of the input MatchPairs.
-+  int32_t* matches;    // pointer to capture array
-+  int32_t numMatches;  // size of capture array
-+};
-+
-+class SMRegExpMacroAssembler final : public NativeRegExpMacroAssembler {
-+ public:
-+  SMRegExpMacroAssembler(JSContext* cx, js::jit::StackMacroAssembler& masm,
-+                         Zone* zone, Mode mode, uint32_t num_capture_registers);
-+  virtual ~SMRegExpMacroAssembler() {}  // Nothing to do here
-+
-+  virtual int stack_limit_slack();
-+  virtual IrregexpImplementation Implementation();
-+
-+  virtual bool Succeed();
-+  virtual void Fail();
-+
-+  virtual void AdvanceCurrentPosition(int by);
-+  virtual void PopCurrentPosition();
-+  virtual void PushCurrentPosition();
-+  virtual void SetCurrentPositionFromEnd(int by);
-+
-+  virtual void Backtrack();
-+  virtual void Bind(Label* label);
-+  virtual void GoTo(Label* label);
-+  virtual void PushBacktrack(Label* label);
-+
-+  virtual void CheckCharacter(uint32_t c, Label* on_equal);
-+  virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
-+  virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
-+  virtual void CheckCharacterLT(uc16 limit, Label* on_less);
-+  virtual void CheckCharacterAfterAnd(uint32_t c, uint32_t mask,
-+                                      Label* on_equal);
-+  virtual void CheckNotCharacterAfterAnd(uint32_t c, uint32_t mask,
-+                                         Label* on_not_equal);
-+  virtual void CheckNotCharacterAfterMinusAnd(uc16 c, uc16 minus, uc16 mask,
-+                                              Label* on_not_equal);
-+  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
-+  virtual void CheckCharacterInRange(uc16 from, uc16 to, Label* on_in_range);
-+  virtual void CheckCharacterNotInRange(uc16 from, uc16 to,
-+                                        Label* on_not_in_range);
-+  virtual void CheckAtStart(int cp_offset, Label* on_at_start);
-+  virtual void CheckNotAtStart(int cp_offset, Label* on_not_at_start);
-+  virtual void CheckPosition(int cp_offset, Label* on_outside_input);
-+  virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
-+  virtual bool CheckSpecialCharacterClass(uc16 type, Label* on_no_match);
-+  virtual void CheckNotBackReference(int start_reg, bool read_backward,
-+                                     Label* on_no_match);
-+  virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
-+                                               bool read_backward, bool unicode,
-+                                               Label* on_no_match);
-+
-+  virtual void LoadCurrentCharacterImpl(int cp_offset, Label* on_end_of_input,
-+                                        bool check_bounds, int characters,
-+                                        int eats_at_least);
-+
-+  virtual void AdvanceRegister(int reg, int by);
-+  virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
-+  virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
-+  virtual void IfRegisterEqPos(int reg, Label* if_eq);
-+  virtual void PopRegister(int register_index);
-+  virtual void PushRegister(int register_index,
-+                            StackCheckFlag check_stack_limit);
-+  virtual void ReadCurrentPositionFromRegister(int reg);
-+  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
-+  virtual void ReadStackPointerFromRegister(int reg);
-+  virtual void WriteStackPointerToRegister(int reg);
-+  virtual void SetRegister(int register_index, int to);
-+  virtual void ClearRegisters(int reg_from, int reg_to);
-+
-+  virtual Handle<HeapObject> GetCode(Handle<String> source);
-+
-+  virtual bool CanReadUnaligned();
-+
-+ private:
-+  size_t frameSize_ = 0;
-+
-+  void createStackFrame();
-+  void initFrameAndRegs();
-+  void successHandler();
-+  void exitHandler();
-+  void backtrackHandler();
-+  void stackOverflowHandler();
-+
-+  // Push a register on the backtrack stack.
-+  void Push(js::jit::Register value);
-+
-+  // Pop a value from the backtrack stack.
-+  void Pop(js::jit::Register target);
-+
-+  void CheckAtStartImpl(int cp_offset, Label* on_cond,
-+                        js::jit::Assembler::Condition cond);
-+  void CheckCharacterImpl(js::jit::Imm32 c, Label* on_cond,
-+                          js::jit::Assembler::Condition cond);
-+  void CheckCharacterAfterAndImpl(uint32_t c, uint32_t and_with, Label* on_cond,
-+                                  bool negate);
-+  void CheckCharacterInRangeImpl(uc16 from, uc16 to, Label* on_cond,
-+                                 js::jit::Assembler::Condition cond);
-+  void CheckNotBackReferenceImpl(int start_reg, bool read_backward,
-+                                 bool unicode, Label* on_no_match,
-+                                 bool ignore_case);
-+
-+  void LoadCurrentCharacterUnchecked(int cp_offset, int characters);
-+
-+  void JumpOrBacktrack(Label* to);
-+
-+  // MacroAssembler methods that take a Label can be called with a
-+  // null label, which means that we should backtrack if we would jump
-+  // to that label. This is a helper to avoid writing out the same
-+  // logic a dozen times.
-+  inline js::jit::Label* LabelOrBacktrack(Label* to) {
-+    return to ? to->inner() : &backtrack_label_;
-+  }
-+
-+  void CheckBacktrackStackLimit();
-+
-+  static bool GrowBacktrackStack(RegExpStack* regexp_stack);
-+
-+  static uint32_t CaseInsensitiveCompareNonUnicode(const char16_t* substring1,
-+                                                   const char16_t* substring2,
-+                                                   size_t byteLength);
-+  static uint32_t CaseInsensitiveCompareUnicode(const char16_t* substring1,
-+                                                const char16_t* substring2,
-+                                                size_t byteLength);
-+
-+  inline int char_size() { return static_cast<int>(mode_); }
-+  inline js::jit::Scale factor() {
-+    return mode_ == UC16 ? js::jit::TimesTwo : js::jit::TimesOne;
-+  }
-+
-+  js::jit::Address inputStart() {
-+    return js::jit::Address(masm_.getStackPointer(),
-+                            offsetof(FrameData, inputStart));
-+  }
-+  js::jit::Address backtrackStackBase() {
-+    return js::jit::Address(masm_.getStackPointer(),
-+                            offsetof(FrameData, backtrackStackBase));
-+  }
-+  js::jit::Address matches() {
-+    return js::jit::Address(masm_.getStackPointer(),
-+                            offsetof(FrameData, matches));
-+  }
-+  js::jit::Address numMatches() {
-+    return js::jit::Address(masm_.getStackPointer(),
-+                            offsetof(FrameData, numMatches));
-+  }
-+
-+  // The stack-pointer-relative location of a regexp register.
-+  js::jit::Address register_location(int register_index) {
-+    return js::jit::Address(masm_.getStackPointer(),
-+                            register_offset(register_index));
-+  }
-+
-+  int32_t register_offset(int register_index) {
-+    MOZ_ASSERT(register_index >= 0 && register_index <= kMaxRegister);
-+    if (num_registers_ <= register_index) {
-+      num_registers_ = register_index + 1;
-+    }
-+    static_assert(alignof(uintptr_t) <= alignof(FrameData),
-+                  "Regexp: Alignment of uintptr_t and FrameData mismatch");
-+    return sizeof(FrameData) + register_index * sizeof(uintptr_t*);
-+  }
-+
-+  JSContext* cx_;
-+  js::jit::StackMacroAssembler& masm_;
-+
-+  /*
-+   * This assembler uses the following registers:
-+   *
-+   * - current_character_:
-+   *     Contains the character (or characters) currently being examined.
-+   *     Must be loaded using LoadCurrentCharacter before using any of the
-+   *     dispatch methods. After a matching pass for a global regexp,
-+   *     temporarily stores the index of capture start.
-+   * - current_position_:
-+   *     Current position in input *as negative byte offset from end of string*.
-+   * - input_end_pointer_:
-+   *     Points to byte after last character in the input. current_position_ is
-+   *     relative to this.
-+   * - backtrack_stack_pointer_:
-+   *     Points to tip of the (heap-allocated) backtrack stack. The stack grows
-+   *     downward (like the native stack).
-+   * - temp0_, temp1_, temp2_:
-+   *     Scratch registers.
-+   *
-+   * The native stack pointer is used to access arguments (InputOutputData),
-+   * local variables (FrameData), and irregexp's internal virtual registers
-+   * (see register_location).
-+   */
-+
-+  js::jit::Register current_character_;
-+  js::jit::Register current_position_;
-+  js::jit::Register input_end_pointer_;
-+  js::jit::Register backtrack_stack_pointer_;
-+  js::jit::Register temp0_, temp1_, temp2_;
-+
-+  // These labels are used in various API calls and bound (if used) in
-+  // GetCode. If we abort in the middle of a compilation, as may
-+  // happen if a regexp is too big, they may be used but not
-+  // bound.
-+  js::jit::NonAssertingLabel entry_label_;
-+  js::jit::NonAssertingLabel start_label_;
-+  js::jit::NonAssertingLabel backtrack_label_;
-+  js::jit::NonAssertingLabel success_label_;
-+  js::jit::NonAssertingLabel exit_label_;
-+  js::jit::NonAssertingLabel stack_overflow_label_;
-+  js::jit::NonAssertingLabel exit_with_exception_label_;
-+
-+  // When we generate the code to push a backtrack label's address
-+  // onto the backtrack stack, we don't know its final address. We
-+  // have to patch it after linking. This is slightly delicate, as the
-+  // Label itself (which is allocated on the stack) may not exist by
-+  // the time we link. The approach is as follows:
-+  //
-+  // 1. When we push a label on the backtrack stack (PushBacktrack),
-+  //    we bind the label's patchOffset_ field to the offset within
-+  //    the code that should be overwritten. This works because each
-+  //    label is only pushed by a single instruction.
-+  //
-+  // 2. When we bind a label (Bind), we check to see if it has a
-+  //    bound patchOffset_. If it does, we create a LabelPatch mapping
-+  //    its patch offset to the offset of the label itself.
-+  //
-+  // 3. While linking the code, we walk the list of label patches
-+  //    and patch the code accordingly.
-+  class LabelPatch {
-+   public:
-+    LabelPatch(js::jit::CodeOffset patchOffset, size_t labelOffset)
-+        : patchOffset_(patchOffset), labelOffset_(labelOffset) {}
-+
-+    js::jit::CodeOffset patchOffset_;
-+    size_t labelOffset_ = 0;
-+  };
-+
-+  js::Vector<LabelPatch, 4, js::SystemAllocPolicy> labelPatches_;
-+  void AddLabelPatch(js::jit::CodeOffset patchOffset, size_t labelOffset) {
-+    js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+    if (!labelPatches_.emplaceBack(patchOffset, labelOffset)) {
-+      oomUnsafe.crash("Irregexp label patch");
-+    }
-+  }
-+
-+  Mode mode_;
-+  int num_registers_;
-+  int num_capture_registers_;
-+  js::jit::LiveGeneralRegisterSet savedRegisters_;
-+
-+ public:
-+  using TableVector =
-+      js::Vector<PseudoHandle<ByteArrayData>, 4, js::SystemAllocPolicy>;
-+  TableVector& tables() { return tables_; }
-+
-+ private:
-+  TableVector tables_;
-+  void AddTable(PseudoHandle<ByteArrayData> table) {
-+    js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+    if (!tables_.append(std::move(table))) {
-+      oomUnsafe.crash("Irregexp table append");
-+    }
-+  }
-+};
-+
-+}  // namespace internal
-+}  // namespace v8
-+
-+#endif  // RegexpMacroAssemblerArch_h
-diff --git a/js/src/irregexp/RegExpShim.cpp b/js/src/irregexp/RegExpShim.cpp
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/RegExpShim.cpp
-@@ -0,0 +1,255 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+// Copyright 2019 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include "irregexp/RegExpShim.h"
-+
-+#include "mozilla/MemoryReporting.h"
-+
-+#include <iostream>
-+
-+#include "irregexp/imported/regexp-macro-assembler.h"
-+#include "irregexp/imported/regexp-stack.h"
-+
-+#include "vm/NativeObject-inl.h"
-+
-+#include "mozilla/Sprintf.h"  // for SprintfLiteral
-+
-+namespace v8 {
-+namespace internal {
-+
-+void PrintF(const char* format, ...) {
-+  va_list arguments;
-+  va_start(arguments, format);
-+  vprintf(format, arguments);
-+  va_end(arguments);
-+}
-+
-+void PrintF(FILE* out, const char* format, ...) {
-+  va_list arguments;
-+  va_start(arguments, format);
-+  vfprintf(out, format, arguments);
-+  va_end(arguments);
-+}
-+
-+StdoutStream::operator std::ostream&() const { return std::cerr; }
-+
-+template <typename T>
-+std::ostream& StdoutStream::operator<<(T t) {
-+  return std::cerr << t;
-+}
-+
-+template std::ostream& StdoutStream::operator<<(char const* c);
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/855591a54d160303349a5f0a32fab15825c708d1/src/utils/ostreams.cc#L120-L169
-+// (This is a hand-simplified version.)
-+// Writes the given character to the output escaping everything outside
-+// of printable ASCII range.
-+std::ostream& operator<<(std::ostream& os, const AsUC16& c) {
-+  uc16 v = c.value;
-+  bool isPrint = 0x20 < v && v <= 0x7e;
-+  char buf[10];
-+  const char* format = isPrint ? "%c" : (v <= 0xFF) ? "\\x%02x" : "\\u%04x";
-+  SprintfLiteral(buf, format, v);
-+  return os << buf;
-+}
-+std::ostream& operator<<(std::ostream& os, const AsUC32& c) {
-+  int32_t v = c.value;
-+  if (v <= String::kMaxUtf16CodeUnit) {
-+    return os << AsUC16(v);
-+  }
-+  char buf[13];
-+  SprintfLiteral(buf, "\\u{%06x}", v);
-+  return os << buf;
-+}
-+
-+HandleScope::HandleScope(Isolate* isolate) : isolate_(isolate) {
-+  isolate->openHandleScope(*this);
-+}
-+
-+HandleScope::~HandleScope() {
-+  isolate_->closeHandleScope(level_, non_gc_level_);
-+}
-+
-+template <typename T>
-+Handle<T>::Handle(T object, Isolate* isolate)
-+    : location_(isolate->getHandleLocation(object.value())) {}
-+
-+template Handle<ByteArray>::Handle(ByteArray b, Isolate* isolate);
-+template Handle<HeapObject>::Handle(const JS::Value& v, Isolate* isolate);
-+template Handle<JSRegExp>::Handle(JSRegExp re, Isolate* isolate);
-+template Handle<String>::Handle(String s, Isolate* isolate);
-+
-+template <typename T>
-+Handle<T>::Handle(const JS::Value& value, Isolate* isolate)
-+    : location_(isolate->getHandleLocation(value)) {
-+  T::cast(Object(value));  // Assert that value has the correct type.
-+}
-+
-+JS::Value* Isolate::getHandleLocation(const JS::Value& value) {
-+  js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+  if (!handleArena_.Append(value)) {
-+    oomUnsafe.crash("Irregexp handle allocation");
-+  }
-+  return &handleArena_.GetLast();
-+}
-+
-+void* Isolate::allocatePseudoHandle(size_t bytes) {
-+  PseudoHandle<void> ptr;
-+  ptr.reset(js_malloc(bytes));
-+  if (!ptr) {
-+    return nullptr;
-+  }
-+  if (!uniquePtrArena_.Append(std::move(ptr))) {
-+    return nullptr;
-+  }
-+  return uniquePtrArena_.GetLast().get();
-+}
-+
-+template <typename T>
-+PseudoHandle<T> Isolate::takeOwnership(void* ptr) {
-+  for (auto iter = uniquePtrArena_.IterFromLast(); !iter.Done(); iter.Prev()) {
-+    auto& entry = iter.Get();
-+    if (entry.get() == ptr) {
-+      PseudoHandle<T> result;
-+      result.reset(static_cast<T*>(entry.release()));
-+      return result;
-+    }
-+  }
-+  MOZ_CRASH("Tried to take ownership of pseudohandle that is not in the arena");
-+}
-+
-+PseudoHandle<ByteArrayData> ByteArray::takeOwnership(Isolate* isolate) {
-+  PseudoHandle<ByteArrayData> result =
-+      isolate->takeOwnership<ByteArrayData>(value().toPrivate());
-+  setValue(JS::PrivateValue(nullptr));
-+  return result;
-+}
-+
-+void Isolate::trace(JSTracer* trc) {
-+  for (auto iter = handleArena_.Iter(); !iter.Done(); iter.Next()) {
-+    auto& elem = iter.Get();
-+    JS::GCPolicy<JS::Value>::trace(trc, &elem, "Isolate handle arena");
-+  }
-+}
-+
-+size_t Isolate::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
-+  size_t size = mallocSizeOf(this);
-+
-+  // The RegExpStack code is imported from V8, so we peek inside it to
-+  // measure its memory from here.
-+  size += mallocSizeOf(regexpStack_);
-+  if (regexpStack_->thread_local_.owns_memory_) {
-+    size += mallocSizeOf(regexpStack_->thread_local_.memory_);
-+  }
-+
-+  size += handleArena_.SizeOfExcludingThis(mallocSizeOf);
-+  size += uniquePtrArena_.SizeOfExcludingThis(mallocSizeOf);
-+  return size;
-+}
-+
-+/*static*/ Handle<String> String::Flatten(Isolate* isolate,
-+                                          Handle<String> string) {
-+  if (string->IsFlat()) {
-+    return string;
-+  }
-+  js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+  JSLinearString* linear = string->str()->ensureLinear(isolate->cx());
-+  if (!linear) {
-+    oomUnsafe.crash("Irregexp String::Flatten");
-+  }
-+  return Handle<String>(JS::StringValue(linear), isolate);
-+}
-+
-+// This is only used for trace messages printing the source pattern of
-+// a regular expression. We have to return a unique_ptr, but we don't
-+// care about the contents, so we return an empty null-terminated string.
-+std::unique_ptr<char[]> String::ToCString() {
-+  js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+
-+  std::unique_ptr<char[]> ptr;
-+  ptr.reset(static_cast<char*>(js_malloc(1)));
-+  if (!ptr) {
-+    oomUnsafe.crash("Irregexp String::ToCString");
-+  }
-+  ptr[0] = '\0';
-+
-+  return ptr;
-+}
-+
-+bool Isolate::init() {
-+  regexpStack_ = js_new<RegExpStack>();
-+  if (!regexpStack_) {
-+    return false;
-+  }
-+  return true;
-+}
-+
-+Isolate::~Isolate() {
-+  if (regexpStack_) {
-+    js_delete(regexpStack_);
-+  }
-+}
-+
-+byte* Isolate::top_of_regexp_stack() const {
-+  return reinterpret_cast<byte*>(regexpStack_->memory_top_address_address());
-+}
-+
-+Handle<ByteArray> Isolate::NewByteArray(int length, AllocationType alloc) {
-+  MOZ_RELEASE_ASSERT(length >= 0);
-+
-+  js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+
-+  size_t alloc_size = sizeof(uint32_t) + length;
-+  ByteArrayData* data =
-+      static_cast<ByteArrayData*>(allocatePseudoHandle(alloc_size));
-+  if (!data) {
-+    oomUnsafe.crash("Irregexp NewByteArray");
-+  }
-+  data->length = length;
-+
-+  return Handle<ByteArray>(JS::PrivateValue(data), this);
-+}
-+
-+Handle<FixedArray> Isolate::NewFixedArray(int length) {
-+  MOZ_RELEASE_ASSERT(length >= 0);
-+  js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+  js::ArrayObject* array = js::NewDenseFullyAllocatedArray(cx(), length);
-+  if (!array) {
-+    oomUnsafe.crash("Irregexp NewFixedArray");
-+  }
-+  array->ensureDenseInitializedLength(cx(), 0, length);
-+  return Handle<FixedArray>(JS::ObjectValue(*array), this);
-+}
-+
-+template <typename CharT>
-+Handle<String> Isolate::InternalizeString(const Vector<const CharT>& str) {
-+  js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+  JSAtom* atom = js::AtomizeChars(cx(), str.begin(), str.length());
-+  if (!atom) {
-+    oomUnsafe.crash("Irregexp InternalizeString");
-+  }
-+  return Handle<String>(JS::StringValue(atom), this);
-+}
-+
-+template Handle<String> Isolate::InternalizeString(
-+    const Vector<const uint8_t>& str);
-+template Handle<String> Isolate::InternalizeString(
-+    const Vector<const char16_t>& str);
-+
-+static_assert(JSRegExp::RegistersForCaptureCount(JSRegExp::kMaxCaptures) <=
-+              RegExpMacroAssembler::kMaxRegisterCount, "e1");
-+
-+bool FLAG_trace_regexp_assembler = false;
-+bool FLAG_trace_regexp_bytecodes = false;
-+bool FLAG_trace_regexp_parser = false;
-+bool FLAG_trace_regexp_peephole_optimization = false;
-+
-+}  // namespace internal
-+}  // namespace v8
-diff --git a/js/src/irregexp/RegExpShim.h b/js/src/irregexp/RegExpShim.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/RegExpShim.h
-@@ -0,0 +1,1261 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+// Copyright 2019 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#ifndef RegexpShim_h
-+#define RegexpShim_h
-+
-+#include "mozilla/Assertions.h"
-+#include "mozilla/Attributes.h"
-+#include "mozilla/MathAlgorithms.h"
-+#include "mozilla/Maybe.h"
-+#include "mozilla/SegmentedVector.h"
-+#include "mozilla/Sprintf.h"
-+#include "mozilla/Types.h"
-+
-+#include <algorithm>
-+#include <cctype>
-+#include <iostream>  // needed for gcc 10
-+
-+#include "irregexp/RegExpTypes.h"
-+#include "irregexp/util/FlagsShim.h"
-+#include "irregexp/util/VectorShim.h"
-+#include "irregexp/util/ZoneShim.h"
-+#include "jit/Label.h"
-+#include "jit/shared/Assembler-shared.h"
-+#include "js/Value.h"
-+#include "threading/ExclusiveData.h"
-+#include "vm/MutexIDs.h"
-+#include "vm/NativeObject.h"
-+
-+// Forward declaration of classes
-+namespace v8 {
-+namespace internal {
-+
-+class Heap;
-+class Isolate;
-+class RegExpMatchInfo;
-+class RegExpStack;
-+
-+}  // namespace internal
-+}  // namespace v8
-+
-+#define V8_WARN_UNUSED_RESULT MOZ_MUST_USE
-+#define V8_EXPORT_PRIVATE MOZ_EXPORT
-+#define V8_FALLTHROUGH [[fallthrough]]
-+#define V8_NODISCARD [[nodiscard]]
-+
-+#define FATAL(x) MOZ_CRASH(x)
-+#define UNREACHABLE() MOZ_CRASH("unreachable code")
-+#define UNIMPLEMENTED() MOZ_CRASH("unimplemented code")
-+#define STATIC_ASSERT(exp) static_assert(exp, #exp)
-+
-+#define DCHECK MOZ_ASSERT
-+#define DCHECK_EQ(lhs, rhs) MOZ_ASSERT((lhs) == (rhs))
-+#define DCHECK_NE(lhs, rhs) MOZ_ASSERT((lhs) != (rhs))
-+#define DCHECK_GT(lhs, rhs) MOZ_ASSERT((lhs) > (rhs))
-+#define DCHECK_GE(lhs, rhs) MOZ_ASSERT((lhs) >= (rhs))
-+#define DCHECK_LT(lhs, rhs) MOZ_ASSERT((lhs) < (rhs))
-+#define DCHECK_LE(lhs, rhs) MOZ_ASSERT((lhs) <= (rhs))
-+#define DCHECK_NULL(val) MOZ_ASSERT((val) == nullptr)
-+#define DCHECK_NOT_NULL(val) MOZ_ASSERT((val) != nullptr)
-+#define DCHECK_IMPLIES(lhs, rhs) MOZ_ASSERT_IF(lhs, rhs)
-+#define CHECK MOZ_RELEASE_ASSERT
-+#define CHECK_LE(lhs, rhs) MOZ_RELEASE_ASSERT((lhs) <= (rhs))
-+#define CHECK_GE(lhs, rhs) MOZ_RELEASE_ASSERT((lhs) >= (rhs))
-+#define CONSTEXPR_DCHECK MOZ_ASSERT
-+
-+template <class T>
-+static constexpr inline T Min(T t1, T t2) {
-+  return t1 < t2 ? t1 : t2;
-+}
-+
-+template <class T>
-+static constexpr inline T Max(T t1, T t2) {
-+  return t1 > t2 ? t1 : t2;
-+}
-+#define MemCopy memcpy
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/855591a54d160303349a5f0a32fab15825c708d1/src/base/macros.h#L310-L319
-+// ptrdiff_t is 't' according to the standard, but MSVC uses 'I'.
-+#ifdef _MSC_VER
-+#  define V8PRIxPTRDIFF "Ix"
-+#  define V8PRIdPTRDIFF "Id"
-+#  define V8PRIuPTRDIFF "Iu"
-+#else
-+#  define V8PRIxPTRDIFF "tx"
-+#  define V8PRIdPTRDIFF "td"
-+#  define V8PRIuPTRDIFF "tu"
-+#endif
-+
-+#define arraysize mozilla::ArrayLength
-+
-+// Explicitly declare the assignment operator as deleted.
-+#define DISALLOW_ASSIGN(TypeName) TypeName& operator=(const TypeName&) = delete
-+
-+// Explicitly declare the copy constructor and assignment operator as deleted.
-+// This also deletes the implicit move constructor and implicit move assignment
-+// operator, but still allows to manually define them.
-+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
-+  TypeName(const TypeName&) = delete;      \
-+  DISALLOW_ASSIGN(TypeName)
-+
-+// Explicitly declare all implicit constructors as deleted, namely the
-+// default constructor, copy constructor and operator= functions.
-+// This is especially useful for classes containing only static methods.
-+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
-+  TypeName() = delete;                           \
-+  DISALLOW_COPY_AND_ASSIGN(TypeName)
-+
-+namespace v8 {
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/855591a54d160303349a5f0a32fab15825c708d1/src/base/macros.h#L364-L367
-+template <typename T, typename U>
-+constexpr inline bool IsAligned(T value, U alignment) {
-+  return (value & (alignment - 1)) == 0;
-+}
-+
-+using byte = uint8_t;
-+using Address = uintptr_t;
-+static const Address kNullAddress = 0;
-+
-+// Latin1/UTF-16 constants
-+// Code-point values in Unicode 4.0 are 21 bits wide.
-+// Code units in UTF-16 are 16 bits wide.
-+using uc16 = char16_t;
-+using uc32 = uint32_t;
-+
-+namespace base {
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/855591a54d160303349a5f0a32fab15825c708d1/src/base/macros.h#L247-L258
-+// The USE(x, ...) template is used to silence C++ compiler warnings
-+// issued for (yet) unused variables (typically parameters).
-+// The arguments are guaranteed to be evaluated from left to right.
-+struct Use {
-+  template <typename T>
-+  Use(T&&) {}  // NOLINT(runtime/explicit)
-+};
-+#define USE(...)                                                   \
-+  do {                                                             \
-+    ::v8::base::Use unused_tmp_array_for_use_macro[]{__VA_ARGS__}; \
-+    (void)unused_tmp_array_for_use_macro;                          \
-+  } while (false)
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/855591a54d160303349a5f0a32fab15825c708d1/src/base/safe_conversions.h#L35-L39
-+// saturated_cast<> is analogous to static_cast<> for numeric types, except
-+// that the specified numeric conversion will saturate rather than overflow or
-+// underflow.
-+template <typename Dst, typename Src>
-+inline Dst saturated_cast(Src value);
-+
-+// This is the only specialization that is needed for regexp code.
-+// Instead of pulling in dozens of lines of template goo
-+// to derive it, I used the implementation from uint8_clamped in
-+// ArrayBufferObject.h.
-+template <>
-+inline uint8_t saturated_cast<uint8_t, int>(int x) {
-+  return (x >= 0) ? ((x < 255) ? uint8_t(x) : 255) : 0;
-+}
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/fc088cdaccadede84886eee881e67af9db53669a/src/base/bounds.h#L14-L28
-+// Checks if value is in range [lower_limit, higher_limit] using a single
-+// branch.
-+template <typename T, typename U>
-+inline constexpr bool IsInRange(T value, U lower_limit, U higher_limit) {
-+  using unsigned_T = typename std::make_unsigned<T>::type;
-+  // Use static_cast to support enum classes.
-+  return static_cast<unsigned_T>(static_cast<unsigned_T>(value) -
-+                                 static_cast<unsigned_T>(lower_limit)) <=
-+         static_cast<unsigned_T>(static_cast<unsigned_T>(higher_limit) -
-+                                 static_cast<unsigned_T>(lower_limit));
-+}
-+
-+#define LAZY_INSTANCE_INITIALIZER \
-+  {}
-+
-+template <typename T>
-+class LazyInstanceImpl {
-+ public:
-+  LazyInstanceImpl() : value_(js::mutexid::IrregexpLazyStatic) {}
-+
-+  const T* Pointer() {
-+    auto val = value_.lock();
-+    if (val->isNothing()) {
-+      val->emplace();
-+    }
-+    return val->ptr();
-+  }
-+
-+ private:
-+  js::ExclusiveData<mozilla::Maybe<T>> value_;
-+};
-+
-+template <typename T>
-+class LazyInstance {
-+ public:
-+  using type = LazyInstanceImpl<T>;
-+};
-+
-+namespace bits {
-+
-+inline uint64_t CountTrailingZeros(uint64_t value) {
-+  return mozilla::CountTrailingZeroes64(value);
-+}
-+
-+inline size_t RoundUpToPowerOfTwo32(size_t value) {
-+  return mozilla::RoundUpPow2(value);
-+}
-+
-+template <typename T>
-+constexpr bool IsPowerOfTwo(T value) {
-+  return value > 0 && (value & (value - 1)) == 0;
-+}
-+
-+}  // namespace bits
-+}  // namespace base
-+
-+namespace unibrow {
-+
-+using uchar = unsigned int;
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/1f1e4cdb04c75eab77adbecd5f5514ddc3eb56cf/src/strings/unicode.h#L133-L150
-+class Latin1 {
-+ public:
-+  static const uc16 kMaxChar = 0xff;
-+
-+  // Convert the character to Latin-1 case equivalent if possible.
-+  static inline uc16 TryConvertToLatin1(uc16 c) {
-+    // "GREEK CAPITAL LETTER MU" case maps to "MICRO SIGN".
-+    // "GREEK SMALL LETTER MU" case maps to "MICRO SIGN".
-+    if (c == 0x039C || c == 0x03BC) {
-+      return 0xB5;
-+    }
-+    // "LATIN CAPITAL LETTER Y WITH DIAERESIS" case maps to "LATIN SMALL LETTER
-+    // Y WITH DIAERESIS".
-+    if (c == 0x0178) {
-+      return 0xFF;
-+    }
-+    return c;
-+  }
-+};
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/b4bfbce6f91fc2cc72178af42bb3172c5f5eaebb/src/strings/unicode.h#L99-L131
-+class Utf16 {
-+ public:
-+  static inline bool IsLeadSurrogate(int code) {
-+    return js::unicode::IsLeadSurrogate(code);
-+  }
-+  static inline bool IsTrailSurrogate(int code) {
-+    return js::unicode::IsTrailSurrogate(code);
-+  }
-+  static inline uc16 LeadSurrogate(uint32_t char_code) {
-+    return js::unicode::LeadSurrogate(char_code);
-+  }
-+  static inline uc16 TrailSurrogate(uint32_t char_code) {
-+    return js::unicode::TrailSurrogate(char_code);
-+  }
-+  static inline uint32_t CombineSurrogatePair(char16_t lead, char16_t trail) {
-+    return js::unicode::UTF16Decode(lead, trail);
-+  }
-+  static const uchar kMaxNonSurrogateCharCode = 0xffff;
-+};
-+
-+#ifndef V8_INTL_SUPPORT
-+
-+// A cache used in case conversion.  It caches the value for characters
-+// that either have no mapping or map to a single character independent
-+// of context.  Characters that map to more than one character or that
-+// map differently depending on context are always looked up.
-+// Origin:
-+// https://github.com/v8/v8/blob/b4bfbce6f91fc2cc72178af42bb3172c5f5eaebb/src/strings/unicode.h#L64-L88
-+template <class T, int size = 256>
-+class Mapping {
-+ public:
-+  inline Mapping() = default;
-+  inline int get(uchar c, uchar n, uchar* result) {
-+    CacheEntry entry = entries_[c & kMask];
-+    if (entry.code_point_ == c) {
-+      if (entry.offset_ == 0) {
-+        return 0;
-+      } else {
-+        result[0] = c + entry.offset_;
-+        return 1;
-+      }
-+    } else {
-+      return CalculateValue(c, n, result);
-+    }
-+  }
-+
-+ private:
-+  int CalculateValue(uchar c, uchar n, uchar* result) {
-+    bool allow_caching = true;
-+    int length = T::Convert(c, n, result, &allow_caching);
-+    if (allow_caching) {
-+      if (length == 1) {
-+        entries_[c & kMask] = CacheEntry(c, result[0] - c);
-+        return 1;
-+      } else {
-+        entries_[c & kMask] = CacheEntry(c, 0);
-+        return 0;
-+      }
-+    } else {
-+      return length;
-+    }
-+  }
-+
-+  struct CacheEntry {
-+    inline CacheEntry() : code_point_(kNoChar), offset_(0) {}
-+    inline CacheEntry(uchar code_point, signed offset)
-+        : code_point_(code_point), offset_(offset) {}
-+    uchar code_point_;
-+    signed offset_;
-+    static const int kNoChar = (1 << 21) - 1;
-+  };
-+  static const int kSize = size;
-+  static const int kMask = kSize - 1;
-+  CacheEntry entries_[kSize];
-+};
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/b4bfbce6f91fc2cc72178af42bb3172c5f5eaebb/src/strings/unicode.h#L241-L252
-+struct Ecma262Canonicalize {
-+  static const int kMaxWidth = 1;
-+  static int Convert(uchar c, uchar n, uchar* result, bool* allow_caching_ptr);
-+};
-+struct Ecma262UnCanonicalize {
-+  static const int kMaxWidth = 4;
-+  static int Convert(uchar c, uchar n, uchar* result, bool* allow_caching_ptr);
-+};
-+struct CanonicalizationRange {
-+  static const int kMaxWidth = 1;
-+  static int Convert(uchar c, uchar n, uchar* result, bool* allow_caching_ptr);
-+};
-+
-+#endif  // !V8_INTL_SUPPORT
-+
-+struct Letter {
-+  static bool Is(uchar c);
-+};
-+
-+}  // namespace unibrow
-+
-+namespace internal {
-+
-+#define PRINTF_FORMAT(x, y) MOZ_FORMAT_PRINTF(x, y)
-+void PRINTF_FORMAT(1, 2) PrintF(const char* format, ...);
-+void PRINTF_FORMAT(2, 3) PrintF(FILE* out, const char* format, ...);
-+
-+// Superclass for classes only using static method functions.
-+// The subclass of AllStatic cannot be instantiated at all.
-+class AllStatic {
-+#ifdef DEBUG
-+ public:
-+  AllStatic() = delete;
-+#endif
-+};
-+
-+// Superclass for classes managed with new and delete.
-+// In irregexp, this is only AlternativeGeneration (in regexp-compiler.cc)
-+// Compare:
-+// https://github.com/v8/v8/blob/7b3332844212d78ee87a9426f3a6f7f781a8fbfa/src/utils/allocation.cc#L88-L96
-+class Malloced {
-+ public:
-+  static void* operator new(size_t size) {
-+    js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+    void* result = js_malloc(size);
-+    if (!result) {
-+      oomUnsafe.crash("Irregexp Malloced shim");
-+    }
-+    return result;
-+  }
-+  static void operator delete(void* p) { js_free(p); }
-+};
-+
-+constexpr int32_t KB = 1024;
-+constexpr int32_t MB = 1024 * 1024;
-+
-+#define kMaxInt JSVAL_INT_MAX
-+#define kMinInt JSVAL_INT_MIN
-+constexpr int kSystemPointerSize = sizeof(void*);
-+
-+// The largest integer n such that n and n + 1 are both exactly
-+// representable as a Number value.  ES6 section 20.1.2.6
-+constexpr double kMaxSafeInteger = 9007199254740991.0;  // 2^53-1
-+
-+constexpr int kBitsPerByte = 8;
-+constexpr int kBitsPerByteLog2 = 3;
-+constexpr int kUInt32Size = sizeof(uint32_t);
-+constexpr int kInt64Size = sizeof(int64_t);
-+constexpr int kUC16Size = sizeof(uc16);
-+
-+inline constexpr bool IsDecimalDigit(uc32 c) { return c >= '0' && c <= '9'; }
-+
-+inline bool is_uint24(int64_t val) { return (val >> 24) == 0; }
-+inline bool is_int24(int64_t val) {
-+  int64_t limit = int64_t(1) << 23;
-+  return (-limit <= val) && (val < limit);
-+}
-+
-+inline bool IsIdentifierStart(uc32 c) {
-+  return js::unicode::IsIdentifierStart(uint32_t(c));
-+}
-+inline bool IsIdentifierPart(uc32 c) {
-+  return js::unicode::IsIdentifierPart(uint32_t(c));
-+}
-+
-+// Wrappers to disambiguate char16_t and uc16.
-+struct AsUC16 {
-+  explicit AsUC16(char16_t v) : value(v) {}
-+  char16_t value;
-+};
-+
-+struct AsUC32 {
-+  explicit AsUC32(int32_t v) : value(v) {}
-+  int32_t value;
-+};
-+
-+std::ostream& operator<<(std::ostream& os, const AsUC16& c);
-+std::ostream& operator<<(std::ostream& os, const AsUC32& c);
-+
-+// This class is used for the output of trace-regexp-parser.  V8 has
-+// an elaborate implementation to ensure that the output gets to the
-+// right place, even on Android. We just need something that will
-+// print output (ideally to stderr, to match the rest of our tracing
-+// code). This is an empty wrapper that will convert itself to
-+// std::cerr when used.
-+class StdoutStream {
-+ public:
-+  operator std::ostream&() const;
-+  template <typename T>
-+  std::ostream& operator<<(T t);
-+};
-+
-+// Reuse existing Maybe implementation
-+using mozilla::Maybe;
-+
-+template <typename T>
-+Maybe<T> Just(const T& value) {
-+  return mozilla::Some(value);
-+}
-+
-+template <typename T>
-+mozilla::Nothing Nothing() {
-+  return mozilla::Nothing();
-+}
-+
-+template <typename T>
-+using PseudoHandle = mozilla::UniquePtr<T, JS::FreePolicy>;
-+
-+// Compare 8bit/16bit chars to 8bit/16bit chars.
-+// Used indirectly by regexp-interpreter.cc
-+// Taken from: https://github.com/v8/v8/blob/master/src/utils/utils.h
-+template <typename lchar, typename rchar>
-+inline int CompareCharsUnsigned(const lchar* lhs, const rchar* rhs,
-+                                size_t chars) {
-+  const lchar* limit = lhs + chars;
-+  if (sizeof(*lhs) == sizeof(char) && sizeof(*rhs) == sizeof(char)) {
-+    // memcmp compares byte-by-byte, yielding wrong results for two-byte
-+    // strings on little-endian systems.
-+    return memcmp(lhs, rhs, chars);
-+  }
-+  while (lhs < limit) {
-+    int r = static_cast<int>(*lhs) - static_cast<int>(*rhs);
-+    if (r != 0) return r;
-+    ++lhs;
-+    ++rhs;
-+  }
-+  return 0;
-+}
-+template <typename lchar, typename rchar>
-+inline int CompareChars(const lchar* lhs, const rchar* rhs, size_t chars) {
-+  DCHECK_LE(sizeof(lchar), 2);
-+  DCHECK_LE(sizeof(rchar), 2);
-+  if (sizeof(lchar) == 1) {
-+    if (sizeof(rchar) == 1) {
-+      return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
-+                                  reinterpret_cast<const uint8_t*>(rhs), chars);
-+    } else {
-+      return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
-+                                  reinterpret_cast<const char16_t*>(rhs),
-+                                  chars);
-+    }
-+  } else {
-+    if (sizeof(rchar) == 1) {
-+      return CompareCharsUnsigned(reinterpret_cast<const char16_t*>(lhs),
-+                                  reinterpret_cast<const uint8_t*>(rhs), chars);
-+    } else {
-+      return CompareCharsUnsigned(reinterpret_cast<const char16_t*>(lhs),
-+                                  reinterpret_cast<const char16_t*>(rhs),
-+                                  chars);
-+    }
-+  }
-+}
-+
-+// Compare 8bit/16bit chars to 8bit/16bit chars.
-+template <typename lchar, typename rchar>
-+inline bool CompareCharsEqualUnsigned(const lchar* lhs, const rchar* rhs,
-+                                      size_t chars) {
-+  STATIC_ASSERT(std::is_unsigned<lchar>::value);
-+  STATIC_ASSERT(std::is_unsigned<rchar>::value);
-+  if (sizeof(*lhs) == sizeof(*rhs)) {
-+    // memcmp compares byte-by-byte, but for equality it doesn't matter whether
-+    // two-byte char comparison is little- or big-endian.
-+    return memcmp(lhs, rhs, chars * sizeof(*lhs)) == 0;
-+  }
-+  for (const lchar* limit = lhs + chars; lhs < limit; ++lhs, ++rhs) {
-+    if (*lhs != *rhs) return false;
-+  }
-+  return true;
-+}
-+
-+template <typename lchar, typename rchar>
-+inline bool CompareCharsEqual(const lchar* lhs, const rchar* rhs,
-+                              size_t chars) {
-+  using ulchar = typename std::make_unsigned<lchar>::type;
-+  using urchar = typename std::make_unsigned<rchar>::type;
-+  return CompareCharsEqualUnsigned(reinterpret_cast<const ulchar*>(lhs),
-+                                   reinterpret_cast<const urchar*>(rhs), chars);
-+}
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/855591a54d160303349a5f0a32fab15825c708d1/src/utils/utils.h#L40-L48
-+// Returns the value (0 .. 15) of a hexadecimal character c.
-+// If c is not a legal hexadecimal character, returns a value < 0.
-+// Used in regexp-parser.cc
-+inline int HexValue(uc32 c) {
-+  c -= '0';
-+  if (static_cast<unsigned>(c) <= 9) return c;
-+  c = (c | 0x20) - ('a' - '0');  // detect 0x11..0x16 and 0x31..0x36.
-+  if (static_cast<unsigned>(c) <= 5) return c + 10;
-+  return -1;
-+}
-+
-+// V8::Object ~= JS::Value
-+class Object {
-+ public:
-+  // The default object constructor in V8 stores a nullptr,
-+  // which has its low bit clear and is interpreted as Smi(0).
-+  constexpr Object() : asBits_(JS::Int32Value(0).asRawBits()) {}
-+
-+  Object(const JS::Value& value) { setValue(value); }
-+
-+  // Used in regexp-interpreter.cc to check the return value of
-+  // isolate->stack_guard()->HandleInterrupts(). We want to handle
-+  // interrupts in the caller, so we always return false from
-+  // HandleInterrupts and true here.
-+  inline bool IsException(Isolate*) const {
-+    MOZ_ASSERT(!value().toBoolean());
-+    return true;
-+  }
-+
-+  JS::Value value() const { return JS::Value::fromRawBits(asBits_); }
-+
-+  inline static Object cast(Object object) { return object; }
-+
-+ protected:
-+  void setValue(const JS::Value& val) { asBits_ = val.asRawBits(); }
-+  uint64_t asBits_;
-+} JS_HAZ_GC_POINTER;
-+
-+class Smi : public Object {
-+ public:
-+  static Smi FromInt(int32_t value) {
-+    Smi smi;
-+    smi.setValue(JS::Int32Value(value));
-+    return smi;
-+  }
-+  static inline int32_t ToInt(const Object object) {
-+    return object.value().toInt32();
-+  }
-+};
-+
-+// V8::HeapObject ~= GC thing
-+class HeapObject : public Object {
-+ public:
-+  inline static HeapObject cast(Object object) {
-+    HeapObject h;
-+    h.setValue(object.value());
-+    return h;
-+  }
-+};
-+
-+// A fixed-size array with Objects (aka Values) as element types.
-+// Implemented using the dense elements of an ArrayObject.
-+// Used for named captures.
-+class FixedArray : public HeapObject {
-+ public:
-+  inline void set(uint32_t index, Object value) {
-+    inner()->setDenseElement(index, value.value());
-+  }
-+  inline static FixedArray cast(Object object) {
-+    FixedArray f;
-+    f.setValue(object.value());
-+    return f;
-+  }
-+  js::NativeObject* inner() {
-+    return &value().toObject().as<js::NativeObject>();
-+  }
-+};
-+
-+/*
-+ * Conceptually, ByteArrayData is a variable-size structure. To
-+ * implement this in a C++-approved way, we allocate a struct
-+ * containing the 32-bit length field, followed by additional memory
-+ * for the data. To access the data, we get a pointer to the next byte
-+ * after the length field and cast it to the correct type.
-+ */
-+inline uint8_t* ByteArrayData::data() {
-+  static_assert(alignof(uint8_t) <= alignof(ByteArrayData),
-+                "The trailing data must be aligned to start immediately "
-+                "after the header with no padding.");
-+  ByteArrayData* immediatelyAfter = this + 1;
-+  return reinterpret_cast<uint8_t*>(immediatelyAfter);
-+}
-+
-+// A fixed-size array of bytes.
-+class ByteArray : public HeapObject {
-+  ByteArrayData* inner() const {
-+    return static_cast<ByteArrayData*>(value().toPrivate());
-+  }
-+
-+ public:
-+  PseudoHandle<ByteArrayData> takeOwnership(Isolate* isolate);
-+  byte get(uint32_t index) {
-+    MOZ_ASSERT(index < length());
-+    return inner()->data()[index];
-+  }
-+  void set(uint32_t index, byte val) {
-+    MOZ_ASSERT(index < length());
-+    inner()->data()[index] = val;
-+  }
-+  uint32_t length() const { return inner()->length; }
-+  byte* GetDataStartAddress() { return inner()->data(); }
-+
-+  static ByteArray cast(Object object) {
-+    ByteArray b;
-+    b.setValue(object.value());
-+    return b;
-+  }
-+};
-+
-+// Like Handles in SM, V8 handles are references to marked pointers.
-+// Unlike SM, where Rooted pointers are created individually on the
-+// stack, the target of a V8 handle lives in an arena on the isolate
-+// (~= JSContext). Whenever a Handle is created, a new "root" is
-+// created at the end of the arena.
-+//
-+// HandleScopes are used to manage the lifetimes of these handles.  A
-+// HandleScope lives on the stack and stores the size of the arena at
-+// the time of its creation. When the function returns and the
-+// HandleScope is destroyed, the arena is truncated to its previous
-+// size, clearing all roots that were created since the creation of
-+// the HandleScope.
-+//
-+// In some cases, objects that are GC-allocated in V8 are not in SM.
-+// In particular, irregexp allocates ByteArrays during code generation
-+// to store lookup tables. This does not play nicely with the SM
-+// macroassembler's requirement that no GC allocations take place
-+// while it is on the stack. To work around this, this shim layer also
-+// provides the ability to create pseudo-handles, which are not
-+// managed by the GC but provide the same API to irregexp. The "root"
-+// of a pseudohandle is a unique pointer living in a second arena. If
-+// the allocated object should outlive the HandleScope, it must be
-+// manually moved out of the arena using takeOwnership.
-+
-+class MOZ_STACK_CLASS HandleScope {
-+ public:
-+  HandleScope(Isolate* isolate);
-+  ~HandleScope();
-+
-+ private:
-+  size_t level_;
-+  size_t non_gc_level_;
-+  Isolate* isolate_;
-+
-+  friend class Isolate;
-+};
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/5792f3587116503fc047d2f68c951c72dced08a5/src/handles/handles.h#L88-L171
-+template <typename T>
-+class MOZ_NONHEAP_CLASS Handle {
-+ public:
-+  Handle() : location_(nullptr) {}
-+  Handle(T object, Isolate* isolate);
-+  Handle(const JS::Value& value, Isolate* isolate);
-+
-+  // Constructor for handling automatic up casting.
-+  template <typename S,
-+            typename = typename std::enable_if<std::is_convertible<S*, T*>::value>::type>
-+  inline Handle(Handle<S> handle) : location_(handle.location_) {}
-+
-+  inline bool is_null() const { return location_ == nullptr; }
-+
-+  inline T operator*() const { return T::cast(Object(*location_)); };
-+
-+  // {ObjectRef} is returned by {Handle::operator->}. It should never be stored
-+  // anywhere or used in any other code; no one should ever have to spell out
-+  // {ObjectRef} in code. Its only purpose is to be dereferenced immediately by
-+  // "operator-> chaining". Returning the address of the field is valid because
-+  // this object's lifetime only ends at the end of the full statement.
-+  // Origin:
-+  // https://github.com/v8/v8/blob/03aaa4b3bf4cb01eee1f223b252e6869b04ab08c/src/handles/handles.h#L91-L105
-+  class ObjectRef {
-+   public:
-+    T* operator->() { return &object_; }
-+
-+   private:
-+    friend class Handle;
-+    explicit ObjectRef(T object) : object_(object) {}
-+
-+    T object_;
-+  };
-+  inline ObjectRef operator->() const { return ObjectRef{**this}; }
-+
-+  static Handle<T> fromHandleValue(JS::HandleValue handle) {
-+    return Handle(handle.address());
-+  }
-+
-+ private:
-+  Handle(const JS::Value* location) : location_(location) {}
-+
-+  template <typename>
-+  friend class Handle;
-+  template <typename>
-+  friend class MaybeHandle;
-+
-+  const JS::Value* location_;
-+};
-+
-+// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
-+// into a Handle requires checking that it does not point to nullptr.  This
-+// ensures nullptr checks before use.
-+//
-+// Also note that Handles do not provide default equality comparison or hashing
-+// operators on purpose. Such operators would be misleading, because intended
-+// semantics is ambiguous between Handle location and object identity.
-+// Origin:
-+// https://github.com/v8/v8/blob/5792f3587116503fc047d2f68c951c72dced08a5/src/handles/maybe-handles.h#L15-L78
-+template <typename T>
-+class MOZ_NONHEAP_CLASS MaybeHandle final {
-+ public:
-+  MaybeHandle() : location_(nullptr) {}
-+
-+  // Constructor for handling automatic up casting from Handle.
-+  // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
-+  template <typename S,
-+            typename = typename std::enable_if<std::is_convertible<S*, T*>::value>::type>
-+  MaybeHandle(Handle<S> handle) : location_(handle.location_) {}
-+
-+  inline Handle<T> ToHandleChecked() const {
-+    MOZ_RELEASE_ASSERT(location_);
-+    return Handle<T>(location_);
-+  }
-+
-+  // Convert to a Handle with a type that can be upcasted to.
-+  template <typename S>
-+  inline bool ToHandle(Handle<S>* out) const {
-+    if (location_) {
-+      *out = Handle<T>(location_);
-+      return true;
-+    } else {
-+      *out = Handle<T>();
-+      return false;
-+    }
-+  }
-+
-+ private:
-+  JS::Value* location_;
-+};
-+
-+// From v8/src/handles/handles-inl.h
-+
-+template <typename T>
-+inline Handle<T> handle(T object, Isolate* isolate) {
-+  return Handle<T>(object, isolate);
-+}
-+
-+// RAII Guard classes
-+
-+using DisallowGarbageCollection = JS::AutoCheckCannotGC;
-+
-+// V8 uses this inside DisallowGarbageCollection regions to turn
-+// allocation back on before throwing a stack overflow exception or
-+// handling interrupts. AutoSuppressGC is sufficient for the former
-+// case, but not for the latter: handling interrupts can execute
-+// arbitrary script code, and V8 jumps through some scary hoops to
-+// "manually relocate unhandlified references" afterwards. To keep
-+// things sane, we don't try to handle interrupts while regex code is
-+// still on the stack. Instead, we return EXCEPTION and handle
-+// interrupts in the caller. (See RegExpShared::execute.)
-+
-+class AllowGarbageCollection {
-+ public:
-+  AllowGarbageCollection() {}
-+};
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/84f3877c15bc7f8956d21614da4311337525a3c8/src/objects/string.h#L83-L474
-+class String : public HeapObject {
-+ private:
-+  JSString* str() const { return value().toString(); }
-+
-+ public:
-+  String() = default;
-+  String(JSString* str) { setValue(JS::StringValue(str)); }
-+
-+  operator JSString*() const { return str(); }
-+
-+  // Max char codes.
-+  static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
-+  static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar;
-+  static const int kMaxUtf16CodeUnit = 0xffff;
-+  static const uint32_t kMaxUtf16CodeUnitU = kMaxUtf16CodeUnit;
-+  static const uc32 kMaxCodePoint = 0x10ffff;
-+
-+  MOZ_ALWAYS_INLINE int length() const { return str()->length(); }
-+  bool IsFlat() { return str()->isLinear(); };
-+
-+  // Origin:
-+  // https://github.com/v8/v8/blob/84f3877c15bc7f8956d21614da4311337525a3c8/src/objects/string.h#L95-L152
-+  class FlatContent {
-+   public:
-+    FlatContent(JSLinearString* string, const DisallowGarbageCollection& no_gc)
-+        : string_(string), no_gc_(no_gc) {}
-+    inline bool IsOneByte() const { return string_->hasLatin1Chars(); }
-+    inline bool IsTwoByte() const { return !string_->hasLatin1Chars(); }
-+
-+    Vector<const uint8_t> ToOneByteVector() const {
-+      MOZ_ASSERT(IsOneByte());
-+      return Vector<const uint8_t>(string_->latin1Chars(no_gc_),
-+                                   string_->length());
-+    }
-+    Vector<const uc16> ToUC16Vector() const {
-+      MOZ_ASSERT(IsTwoByte());
-+      return Vector<const uc16>(string_->twoByteChars(no_gc_),
-+                                string_->length());
-+    }
-+
-+   private:
-+    const JSLinearString* string_;
-+    const JS::AutoCheckCannotGC& no_gc_;
-+  };
-+  FlatContent GetFlatContent(const DisallowGarbageCollection& no_gc) {
-+    MOZ_ASSERT(IsFlat());
-+    return FlatContent(&str()->asLinear(), no_gc);
-+  }
-+
-+  static Handle<String> Flatten(Isolate* isolate, Handle<String> string);
-+
-+  inline static String cast(Object object) {
-+    String s;
-+    MOZ_ASSERT(object.value().isString());
-+    s.setValue(object.value());
-+    return s;
-+  }
-+
-+  inline static bool IsOneByteRepresentationUnderneath(String string) {
-+    return string.str()->hasLatin1Chars();
-+  }
-+  inline bool IsOneByteRepresentation() const {
-+    return str()->hasLatin1Chars();
-+  }
-+
-+  std::unique_ptr<char[]> ToCString();
-+
-+  template <typename Char>
-+  Vector<const Char> GetCharVector(const DisallowGarbageCollection& no_gc);
-+};
-+
-+template <>
-+inline Vector<const uint8_t> String::GetCharVector(
-+    const DisallowGarbageCollection& no_gc) {
-+  String::FlatContent flat = GetFlatContent(no_gc);
-+  MOZ_ASSERT(flat.IsOneByte());
-+  return flat.ToOneByteVector();
-+}
-+
-+template <>
-+inline Vector<const uc16> String::GetCharVector(
-+    const DisallowGarbageCollection& no_gc) {
-+  String::FlatContent flat = GetFlatContent(no_gc);
-+  MOZ_ASSERT(flat.IsTwoByte());
-+  return flat.ToUC16Vector();
-+}
-+
-+// A flat string reader provides random access to the contents of a
-+// string independent of the character width of the string.
-+class MOZ_STACK_CLASS FlatStringReader {
-+ public:
-+  FlatStringReader(JSContext* cx, js::HandleLinearString string)
-+      : string_(string), length_(string->length()) {}
-+
-+  FlatStringReader(const mozilla::Range<const char16_t> range)
-+      : string_(nullptr), range_(range), length_(range.length()) {}
-+
-+  int length() { return length_; }
-+
-+  inline char16_t Get(size_t index) {
-+    MOZ_ASSERT(index < length_);
-+    if (string_) {
-+      return string_->latin1OrTwoByteChar(index);
-+    }
-+    return range_[index];
-+  }
-+
-+ private:
-+  js::HandleLinearString string_;
-+  const mozilla::Range<const char16_t> range_;
-+  size_t length_;
-+};
-+
-+class JSRegExp : public HeapObject {
-+ public:
-+  JSRegExp() : HeapObject() {}
-+  JSRegExp(js::RegExpShared* re) { setValue(JS::PrivateGCThingValue(re)); }
-+
-+  // ******************************************************
-+  // Methods that are called from inside the implementation
-+  // ******************************************************
-+  void TierUpTick() { inner()->tierUpTick(); }
-+
-+  Object Code(bool is_latin1) const {
-+    return Object(JS::PrivateGCThingValue(inner()->getJitCode(is_latin1)));
-+  }
-+  Object Bytecode(bool is_latin1) const {
-+    return Object(JS::PrivateValue(inner()->getByteCode(is_latin1)));
-+  }
-+
-+  // TODO: should we expose this?
-+  uint32_t BacktrackLimit() const { return 0; }
-+
-+  static JSRegExp cast(Object object) {
-+    JSRegExp regexp;
-+    js::gc::Cell* regexpShared = object.value().toGCThing();
-+    MOZ_ASSERT(regexpShared->is<js::RegExpShared>());
-+    regexp.setValue(JS::PrivateGCThingValue(regexpShared));
-+    return regexp;
-+  }
-+
-+  // Each capture (including the match itself) needs two registers.
-+  static constexpr int RegistersForCaptureCount(int count) {
-+    return (count + 1) * 2;
-+  }
-+
-+  inline int MaxRegisterCount() const { return inner()->getMaxRegisters(); }
-+
-+  // ******************************
-+  // Static constants
-+  // ******************************
-+
-+  // Maximum number of captures allowed.
-+  static constexpr int kMaxCaptures = (1 << 15) - 1;
-+
-+  // **************************************************
-+  // JSRegExp::Flags
-+  // **************************************************
-+
-+  enum Flag : uint8_t {
-+    kNone = JS::RegExpFlag::NoFlags,
-+    kGlobal = JS::RegExpFlag::Global,
-+    kIgnoreCase = JS::RegExpFlag::IgnoreCase,
-+    kMultiline = JS::RegExpFlag::Multiline,
-+    kSticky = JS::RegExpFlag::Sticky,
-+    kUnicode = JS::RegExpFlag::Unicode,
-+    kDotAll = JS::RegExpFlag::DotAll,
-+  };
-+  using Flags = JS::RegExpFlags;
-+
-+  static constexpr int kNoBacktrackLimit = 0;
-+
-+ private:
-+  js::RegExpShared* inner() const {
-+    return static_cast<js::RegExpShared*>(value().toGCThing());
-+  }
-+};
-+
-+class Histogram {
-+ public:
-+  inline void AddSample(int sample) {}
-+};
-+
-+class Counters {
-+ public:
-+  Histogram* regexp_backtracks() { return &regexp_backtracks_; }
-+
-+ private:
-+  Histogram regexp_backtracks_;
-+};
-+
-+#define PROFILE(isolate, call) \
-+  do {                         \
-+  } while (false);
-+
-+enum class AllocationType : uint8_t {
-+  kYoung,  // Allocate in the nursery
-+  kOld,    // Allocate in the tenured heap
-+};
-+
-+using StackGuard = Isolate;
-+using Factory = Isolate;
-+
-+class Isolate {
-+ public:
-+  Isolate(JSContext* cx) : cx_(cx) {}
-+  ~Isolate();
-+  bool init();
-+
-+  size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
-+
-+  //********** Isolate code **********//
-+  RegExpStack* regexp_stack() const { return regexpStack_; }
-+  byte* top_of_regexp_stack() const;
-+
-+  // This is called from inside no-GC code. Instead of suppressing GC
-+  // to allocate the error, we return false from Execute and call
-+  // ReportOverRecursed in the caller.
-+  void StackOverflow() {}
-+
-+#ifndef V8_INTL_SUPPORT
-+  unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
-+    return &jsregexp_uncanonicalize_;
-+  }
-+  unibrow::Mapping<unibrow::Ecma262Canonicalize>*
-+  regexp_macro_assembler_canonicalize() {
-+    return &regexp_macro_assembler_canonicalize_;
-+  }
-+  unibrow::Mapping<unibrow::CanonicalizationRange>* jsregexp_canonrange() {
-+    return &jsregexp_canonrange_;
-+  }
-+
-+ private:
-+  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_;
-+  unibrow::Mapping<unibrow::Ecma262Canonicalize>
-+      regexp_macro_assembler_canonicalize_;
-+  unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_;
-+#endif  // !V8_INTL_SUPPORT
-+
-+ public:
-+  // An empty stub for telemetry we don't support
-+  void IncreaseTotalRegexpCodeGenerated(Handle<HeapObject> code) {}
-+
-+  Counters* counters() { return &counters_; }
-+
-+  //********** Factory code **********//
-+  inline Factory* factory() { return this; }
-+
-+  Handle<ByteArray> NewByteArray(
-+      int length, AllocationType allocation = AllocationType::kYoung);
-+
-+  // Allocates a fixed array initialized with undefined values.
-+  Handle<FixedArray> NewFixedArray(int length);
-+
-+  template <typename Char>
-+  Handle<String> InternalizeString(const Vector<const Char>& str);
-+
-+  //********** Stack guard code **********//
-+  inline StackGuard* stack_guard() { return this; }
-+
-+  // This is called from inside no-GC code. V8 runs the interrupt
-+  // inside the no-GC code and then "manually relocates unhandlified
-+  // references" afterwards. We just return false and let the caller
-+  // handle interrupts.
-+  Object HandleInterrupts() { return Object(JS::BooleanValue(false)); }
-+
-+  JSContext* cx() const { return cx_; }
-+
-+  void trace(JSTracer* trc);
-+
-+  //********** Handle code **********//
-+
-+  JS::Value* getHandleLocation(const JS::Value& value);
-+
-+ private:
-+  mozilla::SegmentedVector<JS::Value, 256> handleArena_;
-+  mozilla::SegmentedVector<PseudoHandle<void>, 256> uniquePtrArena_;
-+
-+  void* allocatePseudoHandle(size_t bytes);
-+
-+ public:
-+  template <typename T>
-+  PseudoHandle<T> takeOwnership(void* ptr);
-+
-+  uint32_t liveHandles() const { return handleArena_.Length(); }
-+  uint32_t livePseudoHandles() const { return uniquePtrArena_.Length(); }
-+
-+ private:
-+  void openHandleScope(HandleScope& scope) {
-+    scope.level_ = handleArena_.Length();
-+    scope.non_gc_level_ = uniquePtrArena_.Length();
-+  }
-+  void closeHandleScope(size_t prevLevel, size_t prevUniqueLevel) {
-+    size_t currLevel = handleArena_.Length();
-+    handleArena_.PopLastN(currLevel - prevLevel);
-+
-+    size_t currUniqueLevel = uniquePtrArena_.Length();
-+    uniquePtrArena_.PopLastN(currUniqueLevel - prevUniqueLevel);
-+  }
-+  friend class HandleScope;
-+
-+  JSContext* cx_;
-+  RegExpStack* regexpStack_;
-+  Counters counters_;
-+};
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/50dcf2af54ce27801a71c47c1be1d2c5e36b0dd6/src/execution/isolate.h#L1909-L1931
-+class StackLimitCheck {
-+ public:
-+  StackLimitCheck(Isolate* isolate) : cx_(isolate->cx()) {}
-+
-+  // Use this to check for stack-overflows in C++ code.
-+  bool HasOverflowed() {
-+    bool overflowed = !CheckRecursionLimitDontReport(cx_);
-+#ifdef JS_MORE_DETERMINISTIC
-+    if (overflowed) {
-+      // We don't report overrecursion here, but we throw an exception later
-+      // and this still affects differential testing. Mimic ReportOverRecursed
-+      // (the fuzzers check for this particular string).
-+      fprintf(stderr, "ReportOverRecursed called\n");
-+    }
-+#endif
-+    return overflowed;
-+  }
-+
-+  // Use this to check for interrupt request in C++ code.
-+  bool InterruptRequested() { return cx_->hasPendingInterrupt(); }
-+
-+  // Use this to check for stack-overflow when entering runtime from JS code.
-+  bool JsHasOverflowed() {
-+    return !CheckRecursionLimitConservativeDontReport(cx_);
-+  }
-+
-+ private:
-+  JSContext* cx_;
-+};
-+
-+class Code : public HeapObject {
-+ public:
-+  uint8_t* raw_instruction_start() { return inner()->raw(); }
-+
-+  static Code cast(Object object) {
-+    Code c;
-+    js::gc::Cell* jitCode = object.value().toGCThing();
-+    MOZ_ASSERT(jitCode->is<js::jit::JitCode>());
-+    c.setValue(JS::PrivateGCThingValue(jitCode));
-+    return c;
-+  }
-+  js::jit::JitCode* inner() {
-+    return static_cast<js::jit::JitCode*>(value().toGCThing());
-+  }
-+};
-+
-+enum class MessageTemplate { kStackOverflow };
-+
-+class MessageFormatter {
-+ public:
-+  static const char* TemplateString(MessageTemplate index) {
-+    switch (index) {
-+      case MessageTemplate::kStackOverflow:
-+        return "too much recursion";
-+    }
-+  }
-+};
-+
-+// Origin: https://github.com/v8/v8/blob/master/src/codegen/label.h
-+class Label {
-+ public:
-+  Label() : inner_(js::jit::Label()) {}
-+
-+  js::jit::Label* inner() { return &inner_; }
-+
-+  void Unuse() { inner_.reset(); }
-+
-+  bool is_linked() { return inner_.used(); }
-+  bool is_bound() { return inner_.bound(); }
-+  bool is_unused() { return !inner_.used() && !inner_.bound(); }
-+
-+  int pos() { return inner_.offset(); }
-+  void link_to(int pos) { inner_.use(pos); }
-+  void bind_to(int pos) { inner_.bind(pos); }
-+
-+ private:
-+  js::jit::Label inner_;
-+  js::jit::CodeOffset patchOffset_;
-+
-+  friend class SMRegExpMacroAssembler;
-+};
-+
-+//**************************************************
-+// Constant Flags
-+//**************************************************
-+
-+// V8 uses this for differential fuzzing to handle stack overflows.
-+// We address the same problem in StackLimitCheck::HasOverflowed.
-+const bool FLAG_correctness_fuzzer_suppressions = false;
-+
-+// Instead of using a flag for this, we provide an implementation of
-+// CanReadUnaligned in SMRegExpMacroAssembler.
-+const bool FLAG_enable_regexp_unaligned_accesses = false;
-+
-+// This is used to guard a prototype implementation of sequence properties.
-+// See: https://github.com/tc39/proposal-regexp-unicode-sequence-properties
-+// TODO: Expose this behind a pref once it is past stage 2?
-+const bool FLAG_harmony_regexp_sequence = false;
-+
-+// This is only used in a helper function in regex.h that we never call.
-+const bool FLAG_regexp_interpret_all = false;
-+
-+// This is used to guard a prototype implementation of mode modifiers,
-+// which can modify the regexp flags on the fly inside the pattern.
-+// As far as I can tell, there isn't even a TC39 proposal for this.
-+const bool FLAG_regexp_mode_modifiers = false;
-+
-+// This is used to guard an old prototype implementation of possessive
-+// quantifiers, which never got past the point of adding parser support.
-+const bool FLAG_regexp_possessive_quantifier = false;
-+
-+// These affect the default level of optimization. We can still turn
-+// optimization off on a case-by-case basis in CompilePattern - for
-+// example, if a regexp is too long - so we might as well turn these
-+// flags on unconditionally.
-+const bool FLAG_regexp_optimization = true;
-+#if MOZ_BIG_ENDIAN
-+// peephole optimization not supported on big endian
-+const bool FLAG_regexp_peephole_optimization = false;
-+#else
-+const bool FLAG_regexp_peephole_optimization = true;
-+#endif
-+
-+// This is used to control whether regexps tier up from interpreted to
-+// compiled. We control this with --no-native-regexp and
-+// --regexp-warmup-threshold.
-+const bool FLAG_regexp_tier_up = true;
-+
-+//**************************************************
-+// Debugging Flags
-+//**************************************************
-+
-+extern bool FLAG_trace_regexp_assembler;
-+extern bool FLAG_trace_regexp_bytecodes;
-+extern bool FLAG_trace_regexp_parser;
-+extern bool FLAG_trace_regexp_peephole_optimization;
-+
-+#define COMPILING_IRREGEXP_FOR_EXTERNAL_EMBEDDER
-+
-+}  // namespace internal
-+}  // namespace v8
-+
-+#endif  // RegexpShim_h
-diff --git a/js/src/irregexp/RegExpTypes.h b/js/src/irregexp/RegExpTypes.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/RegExpTypes.h
-@@ -0,0 +1,64 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+// This file forward-defines Irregexp classes that need to be visible
-+// to the rest of Spidermonkey and re-exports them into js::irregexp.
-+
-+#ifndef regexp_RegExpTypes_h
-+#define regexp_RegExpTypes_h
-+
-+#include "js/UniquePtr.h"
-+
-+namespace js {
-+class MatchPairs;
-+}
-+
-+namespace v8 {
-+namespace internal {
-+
-+class ByteArrayData {
-+ public:
-+  uint32_t length;
-+  uint8_t* data();
-+};
-+class Isolate;
-+class RegExpStack;
-+class RegExpStackScope;
-+
-+struct InputOutputData {
-+  const void* inputStart;
-+  const void* inputEnd;
-+
-+  // Index into inputStart (in chars) at which to begin matching.
-+  size_t startIndex;
-+
-+  js::MatchPairs* matches;
-+
-+  template <typename CharT>
-+  InputOutputData(const CharT* inputStart, const CharT* inputEnd,
-+                  size_t startIndex, js::MatchPairs* matches)
-+      : inputStart(inputStart),
-+        inputEnd(inputEnd),
-+        startIndex(startIndex),
-+        matches(matches) {}
-+};
-+
-+}  // namespace internal
-+}  // namespace v8
-+
-+namespace js {
-+namespace irregexp {
-+
-+using Isolate = v8::internal::Isolate;
-+using RegExpStack = v8::internal::RegExpStack;
-+using RegExpStackScope = v8::internal::RegExpStackScope;
-+using ByteArrayData = v8::internal::ByteArrayData;
-+using ByteArray = js::UniquePtr<v8::internal::ByteArrayData, JS::FreePolicy>;
-+using InputOutputData = v8::internal::InputOutputData;
-+
-+}  // namespace irregexp
-+}  // namespace js
-+
-+#endif  // regexp_RegExpTypes_h
-diff --git a/js/src/irregexp/import-irregexp.py b/js/src/irregexp/import-irregexp.py
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/import-irregexp.py
-@@ -0,0 +1,148 @@
-+#!/usr/bin/env python3
-+
-+# This Source Code Form is subject to the terms of the Mozilla Public
-+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
-+# You can obtain one at http://mozilla.org/MPL/2.0/.
-+
-+# This script handles all the mechanical steps of importing irregexp from v8:
-+#
-+# 1. Acquire the source: either from github, or optionally from a local copy of v8.
-+# 2. Copy the contents of v8/src/regexp into js/src/irregexp/imported
-+#    - Exclude files that we have chosen not to import.
-+# 3. While doing so, update #includes:
-+#    - Change "src/regexp/*" to "irregexp/imported/*".
-+#    - Remove other v8-specific headers completely.
-+# 4. Add '#include "irregexp/RegExpShim.h" in the necessary places.
-+# 5. Update the IRREGEXP_VERSION file to include the correct git hash.
-+#
-+# Usage:
-+#  cd path/to/js/src/irregexp
-+#  ./import-irregexp.py --path path/to/v8/src/regexp
-+#
-+# Alternatively, without the --path argument, import-irregexp.py will
-+# clone v8 from github into a temporary directory.
-+#
-+# After running this script, changes to the shim code may be necessary
-+# to account for changes in upstream irregexp.
-+
-+import os
-+import re
-+import subprocess
-+import sys
-+from pathlib import Path
-+
-+
-+def get_hash(path):
-+    # Get the hash for the current git revision
-+    cwd = os.getcwd()
-+    os.chdir(path)
-+    command = ["git", "rev-parse", "HEAD"]
-+    result = subprocess.check_output(command, encoding="utf-8")
-+    os.chdir(cwd)
-+    return result.rstrip()
-+
-+
-+def copy_and_update_includes(src_path, dst_path):
-+    # List of header files that need to include the shim header
-+    need_shim = [
-+        "property-sequences.h",
-+        "regexp-ast.h",
-+        "regexp-bytecode-peephole.h",
-+        "regexp-bytecodes.h",
-+        "regexp-dotprinter.h",
-+        "regexp-error.h",
-+        "regexp.h",
-+        "regexp-macro-assembler.h",
-+        "regexp-stack.h",
-+        "special-case.h",
-+    ]
-+
-+    src = open(str(src_path), "r")
-+    dst = open(str(dst_path), "w")
-+
-+    # 1. Rewrite includes of V8 regexp headers:
-+    regexp_include = re.compile('#include "src/regexp')
-+    regexp_include_new = '#include "irregexp/imported'
-+
-+    # 2. Remove includes of other V8 headers
-+    other_include = re.compile('#include "src/')
-+
-+    # 3. If needed, add '#include "irregexp/RegExpShim.h"'.
-+    #    Note: We get a little fancy to ensure that header files are
-+    #    in alphabetic order. `need_to_add_shim` is true if we still
-+    #    have to add the shim header in this file. `adding_shim_now`
-+    #    is true if we have found a '#include "src/*' and we are just
-+    #    waiting to find an empty line so that we can insert the shim
-+    #    header in the right place.
-+    need_to_add_shim = src_path.name in need_shim
-+    adding_shim_now = False
-+
-+    for line in src:
-+        if adding_shim_now:
-+            if line == "\n":
-+                dst.write('#include "irregexp/RegExpShim.h"\n')
-+                need_to_add_shim = False
-+                adding_shim_now = False
-+
-+        if regexp_include.search(line):
-+            dst.write(re.sub(regexp_include, regexp_include_new, line))
-+        elif other_include.search(line):
-+            if need_to_add_shim:
-+                adding_shim_now = True
-+        else:
-+            dst.write(line)
-+
-+
-+def import_from(srcdir, dstdir):
-+    excluded = [
-+        "DIR_METADATA",
-+        "OWNERS",
-+        "regexp.cc",
-+        "regexp-utils.cc",
-+        "regexp-utils.h",
-+        "regexp-macro-assembler-arch.h",
-+    ]
-+
-+    for file in srcdir.iterdir():
-+        if file.is_dir():
-+            continue
-+        if str(file.name) in excluded:
-+            continue
-+        copy_and_update_includes(file, dstdir / "imported" / file.name)
-+
-+    # Update IRREGEXP_VERSION file
-+    hash = get_hash(srcdir)
-+    version_file = open(str(dstdir / "IRREGEXP_VERSION"), "w")
-+    version_file.write("Imported using import-irregexp.py from:\n")
-+    version_file.write("https://github.com/v8/v8/tree/%s/src/regexp\n" % hash)
-+
-+
-+if __name__ == "__main__":
-+    import argparse
-+    import tempfile
-+
-+    # This script should be run from js/src/irregexp to work correctly.
-+    current_path = Path(os.getcwd())
-+    expected_path = "js/src/irregexp"
-+    if not current_path.match(expected_path):
-+        raise RuntimeError("%s must be run from %s" % (sys.argv[0], expected_path))
-+
-+    parser = argparse.ArgumentParser(description="Import irregexp from v8")
-+    parser.add_argument("-p", "--path", help="path to v8/src/regexp")
-+    args = parser.parse_args()
-+
-+    if args.path:
-+        src_path = Path(args.path)
-+
-+        if not (src_path / "regexp.h").exists():
-+            print("Usage:\n  import-irregexp.py --path <path/to/v8/src/regexp>")
-+            sys.exit(1)
-+        import_from(src_path, current_path)
-+        sys.exit(0)
-+
-+    with tempfile.TemporaryDirectory() as tempdir:
-+        v8_git = "https://github.com/v8/v8.git"
-+        clone = "git clone --depth 1 %s %s" % (v8_git, tempdir)
-+        os.system(clone)
-+        src_path = Path(tempdir) / "src/regexp"
-+        import_from(src_path, current_path)
-diff --git a/js/src/irregexp/moz.build b/js/src/irregexp/moz.build
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/moz.build
-@@ -0,0 +1,45 @@
-+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-+# This Source Code Form is subject to the terms of the Mozilla Public
-+# License, v. 2.0. If a copy of the MPL was not distributed with this
-+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-+
-+include('../js-config.mozbuild')
-+include('../js-cxxflags.mozbuild')
-+
-+FINAL_LIBRARY = "js"
-+
-+# Includes should be relative to parent path
-+LOCAL_INCLUDES += ["!..", ".."]
-+
-+CXXFLAGS += ["-Wno-error=type-limits"]
-+
-+SOURCES += [
-+    'imported/regexp-ast.cc',
-+    'imported/regexp-bytecode-generator.cc',
-+    'imported/regexp-bytecode-peephole.cc',
-+    'imported/regexp-bytecodes.cc',
-+    'imported/regexp-compiler-tonode.cc',
-+    'imported/regexp-compiler.cc',
-+    'imported/regexp-dotprinter.cc',
-+    'imported/regexp-interpreter.cc',
-+    'imported/regexp-macro-assembler-tracer.cc',
-+    'imported/regexp-macro-assembler.cc',
-+    'imported/regexp-parser.cc',
-+    'imported/regexp-stack.cc',
-+    'RegExpAPI.cpp',
-+    'RegExpNativeMacroAssembler.cpp',
-+    'RegExpShim.cpp',
-+    'util/UnicodeShim.cpp'
-+]
-+
-+if CONFIG['JS_HAS_INTL_API']:
-+    CXXFLAGS += ['-DV8_INTL_SUPPORT']
-+    SOURCES += [
-+        'imported/property-sequences.cc',
-+        'imported/special-case.cc'
-+    ]
-+
-+if CONFIG['_MSC_VER']:
-+    # This is intended as a temporary workaround to unblock compilation
-+    # on VS2015 in warnings as errors mode.
-+    CXXFLAGS += ['-wd4275']
-\ No newline at end of file
-diff --git a/js/src/irregexp/util/FlagsShim.h b/js/src/irregexp/util/FlagsShim.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/util/FlagsShim.h
-@@ -0,0 +1,87 @@
-+// Copyright 2014 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#ifndef V8_UTIL_FLAGS_H_
-+#define V8_UTIL_FLAGS_H_
-+
-+// Origin:
-+// https://github.com/v8/v8/blob/1bafcc6b999b23ea1d394f5d267a08183e3c4e19/src/base/flags.h#L15-L90
-+
-+namespace v8 {
-+namespace base {
-+
-+// The Flags class provides a type-safe way of storing OR-combinations of enum
-+// values. The Flags<T, S> class is a template class, where T is an enum type,
-+// and S is the underlying storage type (usually int).
-+//
-+// The traditional C++ approach for storing OR-combinations of enum values is to
-+// use an int or unsigned int variable. The inconvenience with this approach is
-+// that there's no type checking at all; any enum value can be OR'd with any
-+// other enum value and passed on to a function that takes an int or unsigned
-+// int.
-+template <typename T, typename S = int>
-+class Flags final {
-+ public:
-+  using flag_type = T;
-+  using mask_type = S;
-+
-+  Flags() : mask_(0) {}
-+  Flags(flag_type flag) : mask_(static_cast<S>(flag)) {}
-+  Flags(mask_type mask) : mask_(static_cast<S>(mask)) {}
-+
-+  bool operator==(flag_type flag) const {
-+    return mask_ == static_cast<S>(flag);
-+  }
-+  bool operator!=(flag_type flag) const {
-+    return mask_ != static_cast<S>(flag);
-+  }
-+
-+  Flags& operator&=(const Flags& flags) {
-+    mask_ &= flags.mask_;
-+    return *this;
-+  }
-+  Flags& operator|=(const Flags& flags) {
-+    mask_ |= flags.mask_;
-+    return *this;
-+  }
-+  Flags& operator^=(const Flags& flags) {
-+    mask_ ^= flags.mask_;
-+    return *this;
-+  }
-+
-+  Flags operator&(const Flags& flags) const {
-+    return Flags(mask_ & flags.mask_);
-+  }
-+  Flags operator|(const Flags& flags) const {
-+    return Flags(mask_ | flags.mask_);
-+  }
-+  Flags operator^(const Flags& flags) const {
-+    return Flags(mask_ ^ flags.mask_);
-+  }
-+
-+  Flags& operator&=(flag_type flag) { return operator&=(Flags(flag)); }
-+  Flags& operator|=(flag_type flag) { return operator|=(Flags(flag)); }
-+  Flags& operator^=(flag_type flag) { return operator^=(Flags(flag)); }
-+
-+  Flags operator&(flag_type flag) const { return operator&(Flags(flag)); }
-+  Flags operator|(flag_type flag) const { return operator|(Flags(flag)); }
-+  Flags operator^(flag_type flag) const { return operator^(Flags(flag)); }
-+
-+  Flags operator~() const { return Flags(~mask_); }
-+
-+  operator mask_type() const { return mask_; }
-+  bool operator!() const { return !mask_; }
-+
-+  Flags without(flag_type flag) { return *this & (~Flags(flag)); }
-+
-+  friend size_t hash_value(const Flags& flags) { return flags.mask_; }
-+
-+ private:
-+  mask_type mask_;
-+};
-+
-+}  // namespace base
-+}  // namespace v8
-+
-+#endif  // V8_UTIL_FLAG_H_
-diff --git a/js/src/irregexp/util/UnicodeShim.cpp b/js/src/irregexp/util/UnicodeShim.cpp
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/util/UnicodeShim.cpp
-@@ -0,0 +1,1866 @@
-+// Copyright 2012 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+//
-+// This file is a subset of:
-+//  https://github.com/v8/v8/blob/master/src/strings/unicode.cc
-+
-+#include "irregexp/RegExpShim.h"
-+
-+#ifdef V8_INTL_SUPPORT
-+#  include "unicode/uchar.h"
-+#endif
-+
-+namespace v8 {
-+namespace unibrow {
-+
-+#ifndef V8_INTL_SUPPORT
-+static const int kStartBit = (1 << 30);
-+static const int kChunkBits = (1 << 13);
-+#endif  // !V8_INTL_SUPPORT
-+
-+static const uchar kSentinel = static_cast<uchar>(-1);
-+
-+/**
-+ * \file
-+ * Implementations of functions for working with Unicode.
-+ */
-+
-+using int16_t = signed short;     // NOLINT
-+using uint16_t = unsigned short;  // NOLINT
-+using int32_t = int;              // NOLINT
-+
-+#ifndef V8_INTL_SUPPORT
-+// All access to the character table should go through this function.
-+template <int D>
-+static inline uchar TableGet(const int32_t* table, int index) {
-+  return table[D * index];
-+}
-+
-+static inline uchar GetEntry(int32_t entry) { return entry & (kStartBit - 1); }
-+
-+static inline bool IsStart(int32_t entry) { return (entry & kStartBit) != 0; }
-+
-+/**
-+ * Look up a character in the Unicode table using a mix of binary and
-+ * interpolation search.  For a uniformly distributed array
-+ * interpolation search beats binary search by a wide margin.  However,
-+ * in this case interpolation search degenerates because of some very
-+ * high values in the lower end of the table so this function uses a
-+ * combination.  The average number of steps to look up the information
-+ * about a character is around 10, slightly higher if there is no
-+ * information available about the character.
-+ */
-+static bool LookupPredicate(const int32_t* table, uint16_t size, uchar chr) {
-+  static const int kEntryDist = 1;
-+  uint16_t value = chr & (kChunkBits - 1);
-+  unsigned int low = 0;
-+  unsigned int high = size - 1;
-+  while (high != low) {
-+    unsigned int mid = low + ((high - low) >> 1);
-+    uchar current_value = GetEntry(TableGet<kEntryDist>(table, mid));
-+    // If we've found an entry less than or equal to this one, and the
-+    // next one is not also less than this one, we've arrived.
-+    if ((current_value <= value) &&
-+        (mid + 1 == size ||
-+         GetEntry(TableGet<kEntryDist>(table, mid + 1)) > value)) {
-+      low = mid;
-+      break;
-+    } else if (current_value < value) {
-+      low = mid + 1;
-+    } else if (current_value > value) {
-+      // If we've just checked the bottom-most value and it's not
-+      // the one we're looking for, we're done.
-+      if (mid == 0) break;
-+      high = mid - 1;
-+    }
-+  }
-+  int32_t field = TableGet<kEntryDist>(table, low);
-+  uchar entry = GetEntry(field);
-+  bool is_start = IsStart(field);
-+  return (entry == value) || (entry < value && is_start);
-+}
-+#endif  // !V8_INTL_SUPPORT
-+
-+template <int kW>
-+struct MultiCharacterSpecialCase {
-+  static const uchar kEndOfEncoding = kSentinel;
-+  uchar chars[kW];
-+};
-+
-+#ifndef V8_INTL_SUPPORT
-+// Look up the mapping for the given character in the specified table,
-+// which is of the specified length and uses the specified special case
-+// mapping for multi-char mappings.  The next parameter is the character
-+// following the one to map.  The result will be written in to the result
-+// buffer and the number of characters written will be returned.  Finally,
-+// if the allow_caching_ptr is non-null then false will be stored in
-+// it if the result contains multiple characters or depends on the
-+// context.
-+// If ranges are linear, a match between a start and end point is
-+// offset by the distance between the match and the start. Otherwise
-+// the result is the same as for the start point on the entire range.
-+template <bool ranges_are_linear, int kW>
-+static int LookupMapping(const int32_t* table, uint16_t size,
-+                         const MultiCharacterSpecialCase<kW>* multi_chars,
-+                         uchar chr, uchar next, uchar* result,
-+                         bool* allow_caching_ptr) {
-+  static const int kEntryDist = 2;
-+  uint16_t key = chr & (kChunkBits - 1);
-+  uint16_t chunk_start = chr - key;
-+  unsigned int low = 0;
-+  unsigned int high = size - 1;
-+  while (high != low) {
-+    unsigned int mid = low + ((high - low) >> 1);
-+    uchar current_value = GetEntry(TableGet<kEntryDist>(table, mid));
-+    // If we've found an entry less than or equal to this one, and the next one
-+    // is not also less than this one, we've arrived.
-+    if ((current_value <= key) &&
-+        (mid + 1 == size ||
-+         GetEntry(TableGet<kEntryDist>(table, mid + 1)) > key)) {
-+      low = mid;
-+      break;
-+    } else if (current_value < key) {
-+      low = mid + 1;
-+    } else if (current_value > key) {
-+      // If we've just checked the bottom-most value and it's not
-+      // the one we're looking for, we're done.
-+      if (mid == 0) break;
-+      high = mid - 1;
-+    }
-+  }
-+  int32_t field = TableGet<kEntryDist>(table, low);
-+  uchar entry = GetEntry(field);
-+  bool is_start = IsStart(field);
-+  bool found = (entry == key) || (entry < key && is_start);
-+  if (found) {
-+    int32_t value = table[2 * low + 1];
-+    if (value == 0) {
-+      // 0 means not present
-+      return 0;
-+    } else if ((value & 3) == 0) {
-+      // Low bits 0 means a constant offset from the given character.
-+      if (ranges_are_linear) {
-+        result[0] = chr + (value >> 2);
-+      } else {
-+        result[0] = entry + chunk_start + (value >> 2);
-+      }
-+      return 1;
-+    } else if ((value & 3) == 1) {
-+      // Low bits 1 means a special case mapping
-+      if (allow_caching_ptr) *allow_caching_ptr = false;
-+      const MultiCharacterSpecialCase<kW>& mapping = multi_chars[value >> 2];
-+      int length = 0;
-+      for (length = 0; length < kW; length++) {
-+        uchar mapped = mapping.chars[length];
-+        if (mapped == MultiCharacterSpecialCase<kW>::kEndOfEncoding) break;
-+        if (ranges_are_linear) {
-+          result[length] = mapped + (key - entry);
-+        } else {
-+          result[length] = mapped;
-+        }
-+      }
-+      return length;
-+    } else {
-+      // Low bits 2 means a really really special case
-+      if (allow_caching_ptr) *allow_caching_ptr = false;
-+      // The cases of this switch are defined in unicode.py in the
-+      // really_special_cases mapping.
-+      switch (value >> 2) {
-+        case 1:
-+          // Really special case 1: upper case sigma.  This letter
-+          // converts to two different lower case sigmas depending on
-+          // whether or not it occurs at the end of a word.
-+          if (next != 0 && Letter::Is(next)) {
-+            result[0] = 0x03C3;
-+          } else {
-+            result[0] = 0x03C2;
-+          }
-+          return 1;
-+        default:
-+          return 0;
-+      }
-+      return -1;
-+    }
-+  } else {
-+    return 0;
-+  }
-+}
-+#endif  // !V8_INTL_SUPPORT
-+
-+// Letter:               point.category in ['Lu', 'Ll', 'Lt', 'Lm', 'Lo', 'Nl']
-+#ifdef V8_INTL_SUPPORT
-+bool Letter::Is(uchar c) { return static_cast<bool>(u_isalpha(c)); }
-+#else
-+static const uint16_t kLetterTable0Size = 431;
-+static const int32_t kLetterTable0[431] = {
-+    1073741889, 90,         1073741921, 122,
-+    170,        181,        186,        1073742016,  // NOLINT
-+    214,        1073742040, 246,        1073742072,
-+    705,        1073742534, 721,        1073742560,  // NOLINT
-+    740,        748,        750,        1073742704,
-+    884,        1073742710, 887,        1073742714,  // NOLINT
-+    893,        895,        902,        1073742728,
-+    906,        908,        1073742734, 929,  // NOLINT
-+    1073742755, 1013,       1073742839, 1153,
-+    1073742986, 1327,       1073743153, 1366,  // NOLINT
-+    1369,       1073743201, 1415,       1073743312,
-+    1514,       1073743344, 1522,       1073743392,  // NOLINT
-+    1610,       1073743470, 1647,       1073743473,
-+    1747,       1749,       1073743589, 1766,  // NOLINT
-+    1073743598, 1775,       1073743610, 1788,
-+    1791,       1808,       1073743634, 1839,  // NOLINT
-+    1073743693, 1957,       1969,       1073743818,
-+    2026,       1073743860, 2037,       2042,  // NOLINT
-+    1073743872, 2069,       2074,       2084,
-+    2088,       1073743936, 2136,       1073744032,  // NOLINT
-+    2226,       1073744132, 2361,       2365,
-+    2384,       1073744216, 2401,       1073744241,  // NOLINT
-+    2432,       1073744261, 2444,       1073744271,
-+    2448,       1073744275, 2472,       1073744298,  // NOLINT
-+    2480,       2482,       1073744310, 2489,
-+    2493,       2510,       1073744348, 2525,  // NOLINT
-+    1073744351, 2529,       1073744368, 2545,
-+    1073744389, 2570,       1073744399, 2576,  // NOLINT
-+    1073744403, 2600,       1073744426, 2608,
-+    1073744434, 2611,       1073744437, 2614,  // NOLINT
-+    1073744440, 2617,       1073744473, 2652,
-+    2654,       1073744498, 2676,       1073744517,  // NOLINT
-+    2701,       1073744527, 2705,       1073744531,
-+    2728,       1073744554, 2736,       1073744562,  // NOLINT
-+    2739,       1073744565, 2745,       2749,
-+    2768,       1073744608, 2785,       1073744645,  // NOLINT
-+    2828,       1073744655, 2832,       1073744659,
-+    2856,       1073744682, 2864,       1073744690,  // NOLINT
-+    2867,       1073744693, 2873,       2877,
-+    1073744732, 2909,       1073744735, 2913,  // NOLINT
-+    2929,       2947,       1073744773, 2954,
-+    1073744782, 2960,       1073744786, 2965,  // NOLINT
-+    1073744793, 2970,       2972,       1073744798,
-+    2975,       1073744803, 2980,       1073744808,  // NOLINT
-+    2986,       1073744814, 3001,       3024,
-+    1073744901, 3084,       1073744910, 3088,  // NOLINT
-+    1073744914, 3112,       1073744938, 3129,
-+    3133,       1073744984, 3161,       1073744992,  // NOLINT
-+    3169,       1073745029, 3212,       1073745038,
-+    3216,       1073745042, 3240,       1073745066,  // NOLINT
-+    3251,       1073745077, 3257,       3261,
-+    3294,       1073745120, 3297,       1073745137,  // NOLINT
-+    3314,       1073745157, 3340,       1073745166,
-+    3344,       1073745170, 3386,       3389,  // NOLINT
-+    3406,       1073745248, 3425,       1073745274,
-+    3455,       1073745285, 3478,       1073745306,  // NOLINT
-+    3505,       1073745331, 3515,       3517,
-+    1073745344, 3526,       1073745409, 3632,  // NOLINT
-+    1073745458, 3635,       1073745472, 3654,
-+    1073745537, 3714,       3716,       1073745543,  // NOLINT
-+    3720,       3722,       3725,       1073745556,
-+    3735,       1073745561, 3743,       1073745569,  // NOLINT
-+    3747,       3749,       3751,       1073745578,
-+    3755,       1073745581, 3760,       1073745586,  // NOLINT
-+    3763,       3773,       1073745600, 3780,
-+    3782,       1073745628, 3807,       3840,  // NOLINT
-+    1073745728, 3911,       1073745737, 3948,
-+    1073745800, 3980,       1073745920, 4138,  // NOLINT
-+    4159,       1073746000, 4181,       1073746010,
-+    4189,       4193,       1073746021, 4198,  // NOLINT
-+    1073746030, 4208,       1073746037, 4225,
-+    4238,       1073746080, 4293,       4295,  // NOLINT
-+    4301,       1073746128, 4346,       1073746172,
-+    4680,       1073746506, 4685,       1073746512,  // NOLINT
-+    4694,       4696,       1073746522, 4701,
-+    1073746528, 4744,       1073746570, 4749,  // NOLINT
-+    1073746576, 4784,       1073746610, 4789,
-+    1073746616, 4798,       4800,       1073746626,  // NOLINT
-+    4805,       1073746632, 4822,       1073746648,
-+    4880,       1073746706, 4885,       1073746712,  // NOLINT
-+    4954,       1073746816, 5007,       1073746848,
-+    5108,       1073746945, 5740,       1073747567,  // NOLINT
-+    5759,       1073747585, 5786,       1073747616,
-+    5866,       1073747694, 5880,       1073747712,  // NOLINT
-+    5900,       1073747726, 5905,       1073747744,
-+    5937,       1073747776, 5969,       1073747808,  // NOLINT
-+    5996,       1073747822, 6000,       1073747840,
-+    6067,       6103,       6108,       1073748000,  // NOLINT
-+    6263,       1073748096, 6312,       6314,
-+    1073748144, 6389,       1073748224, 6430,  // NOLINT
-+    1073748304, 6509,       1073748336, 6516,
-+    1073748352, 6571,       1073748417, 6599,  // NOLINT
-+    1073748480, 6678,       1073748512, 6740,
-+    6823,       1073748741, 6963,       1073748805,  // NOLINT
-+    6987,       1073748867, 7072,       1073748910,
-+    7087,       1073748922, 7141,       1073748992,  // NOLINT
-+    7203,       1073749069, 7247,       1073749082,
-+    7293,       1073749225, 7404,       1073749230,  // NOLINT
-+    7409,       1073749237, 7414,       1073749248,
-+    7615,       1073749504, 7957,       1073749784,  // NOLINT
-+    7965,       1073749792, 8005,       1073749832,
-+    8013,       1073749840, 8023,       8025,  // NOLINT
-+    8027,       8029,       1073749855, 8061,
-+    1073749888, 8116,       1073749942, 8124,  // NOLINT
-+    8126,       1073749954, 8132,       1073749958,
-+    8140,       1073749968, 8147,       1073749974,  // NOLINT
-+    8155,       1073749984, 8172,       1073750002,
-+    8180,       1073750006, 8188};  // NOLINT
-+static const uint16_t kLetterTable1Size = 87;
-+static const int32_t kLetterTable1[87] = {
-+    113,        127,        1073741968, 156,
-+    258,        263,        1073742090, 275,  // NOLINT
-+    277,        1073742105, 285,        292,
-+    294,        296,        1073742122, 301,  // NOLINT
-+    1073742127, 313,        1073742140, 319,
-+    1073742149, 329,        334,        1073742176,  // NOLINT
-+    392,        1073744896, 3118,       1073744944,
-+    3166,       1073744992, 3300,       1073745131,  // NOLINT
-+    3310,       1073745138, 3315,       1073745152,
-+    3365,       3367,       3373,       1073745200,  // NOLINT
-+    3431,       3439,       1073745280, 3478,
-+    1073745312, 3494,       1073745320, 3502,  // NOLINT
-+    1073745328, 3510,       1073745336, 3518,
-+    1073745344, 3526,       1073745352, 3534,  // NOLINT
-+    1073745360, 3542,       1073745368, 3550,
-+    3631,       1073745925, 4103,       1073745953,  // NOLINT
-+    4137,       1073745969, 4149,       1073745976,
-+    4156,       1073745985, 4246,       1073746077,  // NOLINT
-+    4255,       1073746081, 4346,       1073746172,
-+    4351,       1073746181, 4397,       1073746225,  // NOLINT
-+    4494,       1073746336, 4538,       1073746416,
-+    4607,       1073746944, 8191};  // NOLINT
-+static const uint16_t kLetterTable2Size = 4;
-+static const int32_t kLetterTable2[4] = {1073741824, 3509, 1073745408,
-+                                         8191};  // NOLINT
-+static const uint16_t kLetterTable3Size = 2;
-+static const int32_t kLetterTable3[2] = {1073741824, 8191};  // NOLINT
-+static const uint16_t kLetterTable4Size = 2;
-+static const int32_t kLetterTable4[2] = {1073741824, 8140};  // NOLINT
-+static const uint16_t kLetterTable5Size = 100;
-+static const int32_t kLetterTable5[100] = {
-+    1073741824, 1164,       1073743056, 1277,
-+    1073743104, 1548,       1073743376, 1567,  // NOLINT
-+    1073743402, 1579,       1073743424, 1646,
-+    1073743487, 1693,       1073743520, 1775,  // NOLINT
-+    1073743639, 1823,       1073743650, 1928,
-+    1073743755, 1934,       1073743760, 1965,  // NOLINT
-+    1073743792, 1969,       1073743863, 2049,
-+    1073743875, 2053,       1073743879, 2058,  // NOLINT
-+    1073743884, 2082,       1073743936, 2163,
-+    1073744002, 2227,       1073744114, 2295,  // NOLINT
-+    2299,       1073744138, 2341,       1073744176,
-+    2374,       1073744224, 2428,       1073744260,  // NOLINT
-+    2482,       2511,       1073744352, 2532,
-+    1073744358, 2543,       1073744378, 2558,  // NOLINT
-+    1073744384, 2600,       1073744448, 2626,
-+    1073744452, 2635,       1073744480, 2678,  // NOLINT
-+    2682,       1073744510, 2735,       2737,
-+    1073744565, 2742,       1073744569, 2749,  // NOLINT
-+    2752,       2754,       1073744603, 2781,
-+    1073744608, 2794,       1073744626, 2804,  // NOLINT
-+    1073744641, 2822,       1073744649, 2830,
-+    1073744657, 2838,       1073744672, 2854,  // NOLINT
-+    1073744680, 2862,       1073744688, 2906,
-+    1073744732, 2911,       1073744740, 2917,   // NOLINT
-+    1073744832, 3042,       1073744896, 8191};  // NOLINT
-+static const uint16_t kLetterTable6Size = 6;
-+static const int32_t kLetterTable6[6] = {1073741824, 6051, 1073747888, 6086,
-+                                         1073747915, 6139};  // NOLINT
-+static const uint16_t kLetterTable7Size = 48;
-+static const int32_t kLetterTable7[48] = {
-+    1073748224, 6765,       1073748592, 6873,
-+    1073748736, 6918,       1073748755, 6935,  // NOLINT
-+    6941,       1073748767, 6952,       1073748778,
-+    6966,       1073748792, 6972,       6974,  // NOLINT
-+    1073748800, 6977,       1073748803, 6980,
-+    1073748806, 7089,       1073748947, 7485,  // NOLINT
-+    1073749328, 7567,       1073749394, 7623,
-+    1073749488, 7675,       1073749616, 7796,  // NOLINT
-+    1073749622, 7932,       1073749793, 7994,
-+    1073749825, 8026,       1073749862, 8126,  // NOLINT
-+    1073749954, 8135,       1073749962, 8143,
-+    1073749970, 8151,       1073749978, 8156};  // NOLINT
-+bool Letter::Is(uchar c) {
-+  int chunk_index = c >> 13;
-+  switch (chunk_index) {
-+    case 0:
-+      return LookupPredicate(kLetterTable0, kLetterTable0Size, c);
-+    case 1:
-+      return LookupPredicate(kLetterTable1, kLetterTable1Size, c);
-+    case 2:
-+      return LookupPredicate(kLetterTable2, kLetterTable2Size, c);
-+    case 3:
-+      return LookupPredicate(kLetterTable3, kLetterTable3Size, c);
-+    case 4:
-+      return LookupPredicate(kLetterTable4, kLetterTable4Size, c);
-+    case 5:
-+      return LookupPredicate(kLetterTable5, kLetterTable5Size, c);
-+    case 6:
-+      return LookupPredicate(kLetterTable6, kLetterTable6Size, c);
-+    case 7:
-+      return LookupPredicate(kLetterTable7, kLetterTable7Size, c);
-+    default:
-+      return false;
-+  }
-+}
-+#endif
-+
-+#ifndef V8_INTL_SUPPORT
-+
-+static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings0[1] =
-+    {                                                        // NOLINT
-+        {{kSentinel}}};                                      // NOLINT
-+static const uint16_t kEcma262CanonicalizeTable0Size = 498;  // NOLINT
-+static const int32_t kEcma262CanonicalizeTable0[996] = {
-+    1073741921, -128,   122,        -128,   181,        2972,
-+    1073742048, -128,   246,        -128,   1073742072, -128,
-+    254,        -128,   255,        484,  // NOLINT
-+    257,        -4,     259,        -4,     261,        -4,
-+    263,        -4,     265,        -4,     267,        -4,
-+    269,        -4,     271,        -4,  // NOLINT
-+    273,        -4,     275,        -4,     277,        -4,
-+    279,        -4,     281,        -4,     283,        -4,
-+    285,        -4,     287,        -4,  // NOLINT
-+    289,        -4,     291,        -4,     293,        -4,
-+    295,        -4,     297,        -4,     299,        -4,
-+    301,        -4,     303,        -4,  // NOLINT
-+    307,        -4,     309,        -4,     311,        -4,
-+    314,        -4,     316,        -4,     318,        -4,
-+    320,        -4,     322,        -4,  // NOLINT
-+    324,        -4,     326,        -4,     328,        -4,
-+    331,        -4,     333,        -4,     335,        -4,
-+    337,        -4,     339,        -4,  // NOLINT
-+    341,        -4,     343,        -4,     345,        -4,
-+    347,        -4,     349,        -4,     351,        -4,
-+    353,        -4,     355,        -4,  // NOLINT
-+    357,        -4,     359,        -4,     361,        -4,
-+    363,        -4,     365,        -4,     367,        -4,
-+    369,        -4,     371,        -4,  // NOLINT
-+    373,        -4,     375,        -4,     378,        -4,
-+    380,        -4,     382,        -4,     384,        780,
-+    387,        -4,     389,        -4,  // NOLINT
-+    392,        -4,     396,        -4,     402,        -4,
-+    405,        388,    409,        -4,     410,        652,
-+    414,        520,    417,        -4,  // NOLINT
-+    419,        -4,     421,        -4,     424,        -4,
-+    429,        -4,     432,        -4,     436,        -4,
-+    438,        -4,     441,        -4,  // NOLINT
-+    445,        -4,     447,        224,    453,        -4,
-+    454,        -8,     456,        -4,     457,        -8,
-+    459,        -4,     460,        -8,  // NOLINT
-+    462,        -4,     464,        -4,     466,        -4,
-+    468,        -4,     470,        -4,     472,        -4,
-+    474,        -4,     476,        -4,  // NOLINT
-+    477,        -316,   479,        -4,     481,        -4,
-+    483,        -4,     485,        -4,     487,        -4,
-+    489,        -4,     491,        -4,  // NOLINT
-+    493,        -4,     495,        -4,     498,        -4,
-+    499,        -8,     501,        -4,     505,        -4,
-+    507,        -4,     509,        -4,  // NOLINT
-+    511,        -4,     513,        -4,     515,        -4,
-+    517,        -4,     519,        -4,     521,        -4,
-+    523,        -4,     525,        -4,  // NOLINT
-+    527,        -4,     529,        -4,     531,        -4,
-+    533,        -4,     535,        -4,     537,        -4,
-+    539,        -4,     541,        -4,  // NOLINT
-+    543,        -4,     547,        -4,     549,        -4,
-+    551,        -4,     553,        -4,     555,        -4,
-+    557,        -4,     559,        -4,  // NOLINT
-+    561,        -4,     563,        -4,     572,        -4,
-+    1073742399, 43260,  576,        43260,  578,        -4,
-+    583,        -4,     585,        -4,  // NOLINT
-+    587,        -4,     589,        -4,     591,        -4,
-+    592,        43132,  593,        43120,  594,        43128,
-+    595,        -840,   596,        -824,  // NOLINT
-+    1073742422, -820,   599,        -820,   601,        -808,
-+    603,        -812,   604,        169276, 608,        -820,
-+    609,        169260, 611,        -828,  // NOLINT
-+    613,        169120, 614,        169232, 616,        -836,
-+    617,        -844,   619,        42972,  620,        169220,
-+    623,        -844,   625,        42996,  // NOLINT
-+    626,        -852,   629,        -856,   637,        42908,
-+    640,        -872,   643,        -872,   647,        169128,
-+    648,        -872,   649,        -276,  // NOLINT
-+    1073742474, -868,   651,        -868,   652,        -284,
-+    658,        -876,   670,        169032, 837,        336,
-+    881,        -4,     883,        -4,  // NOLINT
-+    887,        -4,     1073742715, 520,    893,        520,
-+    940,        -152,   1073742765, -148,   943,        -148,
-+    1073742769, -128,   961,        -128,  // NOLINT
-+    962,        -124,   1073742787, -128,   971,        -128,
-+    972,        -256,   1073742797, -252,   974,        -252,
-+    976,        -248,   977,        -228,  // NOLINT
-+    981,        -188,   982,        -216,   983,        -32,
-+    985,        -4,     987,        -4,     989,        -4,
-+    991,        -4,     993,        -4,  // NOLINT
-+    995,        -4,     997,        -4,     999,        -4,
-+    1001,       -4,     1003,       -4,     1005,       -4,
-+    1007,       -4,     1008,       -344,  // NOLINT
-+    1009,       -320,   1010,       28,     1011,       -464,
-+    1013,       -384,   1016,       -4,     1019,       -4,
-+    1073742896, -128,   1103,       -128,  // NOLINT
-+    1073742928, -320,   1119,       -320,   1121,       -4,
-+    1123,       -4,     1125,       -4,     1127,       -4,
-+    1129,       -4,     1131,       -4,  // NOLINT
-+    1133,       -4,     1135,       -4,     1137,       -4,
-+    1139,       -4,     1141,       -4,     1143,       -4,
-+    1145,       -4,     1147,       -4,  // NOLINT
-+    1149,       -4,     1151,       -4,     1153,       -4,
-+    1163,       -4,     1165,       -4,     1167,       -4,
-+    1169,       -4,     1171,       -4,  // NOLINT
-+    1173,       -4,     1175,       -4,     1177,       -4,
-+    1179,       -4,     1181,       -4,     1183,       -4,
-+    1185,       -4,     1187,       -4,  // NOLINT
-+    1189,       -4,     1191,       -4,     1193,       -4,
-+    1195,       -4,     1197,       -4,     1199,       -4,
-+    1201,       -4,     1203,       -4,  // NOLINT
-+    1205,       -4,     1207,       -4,     1209,       -4,
-+    1211,       -4,     1213,       -4,     1215,       -4,
-+    1218,       -4,     1220,       -4,  // NOLINT
-+    1222,       -4,     1224,       -4,     1226,       -4,
-+    1228,       -4,     1230,       -4,     1231,       -60,
-+    1233,       -4,     1235,       -4,  // NOLINT
-+    1237,       -4,     1239,       -4,     1241,       -4,
-+    1243,       -4,     1245,       -4,     1247,       -4,
-+    1249,       -4,     1251,       -4,  // NOLINT
-+    1253,       -4,     1255,       -4,     1257,       -4,
-+    1259,       -4,     1261,       -4,     1263,       -4,
-+    1265,       -4,     1267,       -4,  // NOLINT
-+    1269,       -4,     1271,       -4,     1273,       -4,
-+    1275,       -4,     1277,       -4,     1279,       -4,
-+    1281,       -4,     1283,       -4,  // NOLINT
-+    1285,       -4,     1287,       -4,     1289,       -4,
-+    1291,       -4,     1293,       -4,     1295,       -4,
-+    1297,       -4,     1299,       -4,  // NOLINT
-+    1301,       -4,     1303,       -4,     1305,       -4,
-+    1307,       -4,     1309,       -4,     1311,       -4,
-+    1313,       -4,     1315,       -4,  // NOLINT
-+    1317,       -4,     1319,       -4,     1321,       -4,
-+    1323,       -4,     1325,       -4,     1327,       -4,
-+    1073743201, -192,   1414,       -192,  // NOLINT
-+    7545,       141328, 7549,       15256,  7681,       -4,
-+    7683,       -4,     7685,       -4,     7687,       -4,
-+    7689,       -4,     7691,       -4,  // NOLINT
-+    7693,       -4,     7695,       -4,     7697,       -4,
-+    7699,       -4,     7701,       -4,     7703,       -4,
-+    7705,       -4,     7707,       -4,  // NOLINT
-+    7709,       -4,     7711,       -4,     7713,       -4,
-+    7715,       -4,     7717,       -4,     7719,       -4,
-+    7721,       -4,     7723,       -4,  // NOLINT
-+    7725,       -4,     7727,       -4,     7729,       -4,
-+    7731,       -4,     7733,       -4,     7735,       -4,
-+    7737,       -4,     7739,       -4,  // NOLINT
-+    7741,       -4,     7743,       -4,     7745,       -4,
-+    7747,       -4,     7749,       -4,     7751,       -4,
-+    7753,       -4,     7755,       -4,  // NOLINT
-+    7757,       -4,     7759,       -4,     7761,       -4,
-+    7763,       -4,     7765,       -4,     7767,       -4,
-+    7769,       -4,     7771,       -4,  // NOLINT
-+    7773,       -4,     7775,       -4,     7777,       -4,
-+    7779,       -4,     7781,       -4,     7783,       -4,
-+    7785,       -4,     7787,       -4,  // NOLINT
-+    7789,       -4,     7791,       -4,     7793,       -4,
-+    7795,       -4,     7797,       -4,     7799,       -4,
-+    7801,       -4,     7803,       -4,  // NOLINT
-+    7805,       -4,     7807,       -4,     7809,       -4,
-+    7811,       -4,     7813,       -4,     7815,       -4,
-+    7817,       -4,     7819,       -4,  // NOLINT
-+    7821,       -4,     7823,       -4,     7825,       -4,
-+    7827,       -4,     7829,       -4,     7835,       -236,
-+    7841,       -4,     7843,       -4,  // NOLINT
-+    7845,       -4,     7847,       -4,     7849,       -4,
-+    7851,       -4,     7853,       -4,     7855,       -4,
-+    7857,       -4,     7859,       -4,  // NOLINT
-+    7861,       -4,     7863,       -4,     7865,       -4,
-+    7867,       -4,     7869,       -4,     7871,       -4,
-+    7873,       -4,     7875,       -4,  // NOLINT
-+    7877,       -4,     7879,       -4,     7881,       -4,
-+    7883,       -4,     7885,       -4,     7887,       -4,
-+    7889,       -4,     7891,       -4,  // NOLINT
-+    7893,       -4,     7895,       -4,     7897,       -4,
-+    7899,       -4,     7901,       -4,     7903,       -4,
-+    7905,       -4,     7907,       -4,  // NOLINT
-+    7909,       -4,     7911,       -4,     7913,       -4,
-+    7915,       -4,     7917,       -4,     7919,       -4,
-+    7921,       -4,     7923,       -4,  // NOLINT
-+    7925,       -4,     7927,       -4,     7929,       -4,
-+    7931,       -4,     7933,       -4,     7935,       -4,
-+    1073749760, 32,     7943,       32,  // NOLINT
-+    1073749776, 32,     7957,       32,     1073749792, 32,
-+    7975,       32,     1073749808, 32,     7991,       32,
-+    1073749824, 32,     8005,       32,  // NOLINT
-+    8017,       32,     8019,       32,     8021,       32,
-+    8023,       32,     1073749856, 32,     8039,       32,
-+    1073749872, 296,    8049,       296,  // NOLINT
-+    1073749874, 344,    8053,       344,    1073749878, 400,
-+    8055,       400,    1073749880, 512,    8057,       512,
-+    1073749882, 448,    8059,       448,  // NOLINT
-+    1073749884, 504,    8061,       504,    1073749936, 32,
-+    8113,       32,     8126,       -28820, 1073749968, 32,
-+    8145,       32,     1073749984, 32,   // NOLINT
-+    8161,       32,     8165,       28};  // NOLINT
-+static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings1[1] =
-+    {                                                       // NOLINT
-+        {{kSentinel}}};                                     // NOLINT
-+static const uint16_t kEcma262CanonicalizeTable1Size = 73;  // NOLINT
-+static const int32_t kEcma262CanonicalizeTable1[146] = {
-+    334,        -112,   1073742192, -64,    383,        -64,
-+    388,        -4,     1073743056, -104,   1257,       -104,
-+    1073744944, -192,   3166,       -192,  // NOLINT
-+    3169,       -4,     3173,       -43180, 3174,       -43168,
-+    3176,       -4,     3178,       -4,     3180,       -4,
-+    3187,       -4,     3190,       -4,  // NOLINT
-+    3201,       -4,     3203,       -4,     3205,       -4,
-+    3207,       -4,     3209,       -4,     3211,       -4,
-+    3213,       -4,     3215,       -4,  // NOLINT
-+    3217,       -4,     3219,       -4,     3221,       -4,
-+    3223,       -4,     3225,       -4,     3227,       -4,
-+    3229,       -4,     3231,       -4,  // NOLINT
-+    3233,       -4,     3235,       -4,     3237,       -4,
-+    3239,       -4,     3241,       -4,     3243,       -4,
-+    3245,       -4,     3247,       -4,  // NOLINT
-+    3249,       -4,     3251,       -4,     3253,       -4,
-+    3255,       -4,     3257,       -4,     3259,       -4,
-+    3261,       -4,     3263,       -4,  // NOLINT
-+    3265,       -4,     3267,       -4,     3269,       -4,
-+    3271,       -4,     3273,       -4,     3275,       -4,
-+    3277,       -4,     3279,       -4,  // NOLINT
-+    3281,       -4,     3283,       -4,     3285,       -4,
-+    3287,       -4,     3289,       -4,     3291,       -4,
-+    3293,       -4,     3295,       -4,  // NOLINT
-+    3297,       -4,     3299,       -4,     3308,       -4,
-+    3310,       -4,     3315,       -4,     1073745152, -29056,
-+    3365,       -29056, 3367,       -29056,  // NOLINT
-+    3373,       -29056};                     // NOLINT
-+static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings5[1] =
-+    {                                                       // NOLINT
-+        {{kSentinel}}};                                     // NOLINT
-+static const uint16_t kEcma262CanonicalizeTable5Size = 95;  // NOLINT
-+static const int32_t kEcma262CanonicalizeTable5[190] =
-+    {
-+        1601, -4, 1603, -4, 1605, -4, 1607, -4,
-+        1609, -4, 1611, -4, 1613, -4, 1615, -4,  // NOLINT
-+        1617, -4, 1619, -4, 1621, -4, 1623, -4,
-+        1625, -4, 1627, -4, 1629, -4, 1631, -4,  // NOLINT
-+        1633, -4, 1635, -4, 1637, -4, 1639, -4,
-+        1641, -4, 1643, -4, 1645, -4, 1665, -4,  // NOLINT
-+        1667, -4, 1669, -4, 1671, -4, 1673, -4,
-+        1675, -4, 1677, -4, 1679, -4, 1681, -4,  // NOLINT
-+        1683, -4, 1685, -4, 1687, -4, 1689, -4,
-+        1691, -4, 1827, -4, 1829, -4, 1831, -4,  // NOLINT
-+        1833, -4, 1835, -4, 1837, -4, 1839, -4,
-+        1843, -4, 1845, -4, 1847, -4, 1849, -4,  // NOLINT
-+        1851, -4, 1853, -4, 1855, -4, 1857, -4,
-+        1859, -4, 1861, -4, 1863, -4, 1865, -4,  // NOLINT
-+        1867, -4, 1869, -4, 1871, -4, 1873, -4,
-+        1875, -4, 1877, -4, 1879, -4, 1881, -4,  // NOLINT
-+        1883, -4, 1885, -4, 1887, -4, 1889, -4,
-+        1891, -4, 1893, -4, 1895, -4, 1897, -4,  // NOLINT
-+        1899, -4, 1901, -4, 1903, -4, 1914, -4,
-+        1916, -4, 1919, -4, 1921, -4, 1923, -4,  // NOLINT
-+        1925, -4, 1927, -4, 1932, -4, 1937, -4,
-+        1939, -4, 1943, -4, 1945, -4, 1947, -4,  // NOLINT
-+        1949, -4, 1951, -4, 1953, -4, 1955, -4,
-+        1957, -4, 1959, -4, 1961, -4};  // NOLINT
-+static const MultiCharacterSpecialCase<1> kEcma262CanonicalizeMultiStrings7[1] =
-+    {                                                      // NOLINT
-+        {{kSentinel}}};                                    // NOLINT
-+static const uint16_t kEcma262CanonicalizeTable7Size = 2;  // NOLINT
-+static const int32_t kEcma262CanonicalizeTable7[4] = {1073749825, -128, 8026,
-+                                                      -128};  // NOLINT
-+int Ecma262Canonicalize::Convert(uchar c, uchar n, uchar* result,
-+                                 bool* allow_caching_ptr) {
-+  int chunk_index = c >> 13;
-+  switch (chunk_index) {
-+    case 0:
-+      return LookupMapping<true>(
-+          kEcma262CanonicalizeTable0, kEcma262CanonicalizeTable0Size,
-+          kEcma262CanonicalizeMultiStrings0, c, n, result, allow_caching_ptr);
-+    case 1:
-+      return LookupMapping<true>(
-+          kEcma262CanonicalizeTable1, kEcma262CanonicalizeTable1Size,
-+          kEcma262CanonicalizeMultiStrings1, c, n, result, allow_caching_ptr);
-+    case 5:
-+      return LookupMapping<true>(
-+          kEcma262CanonicalizeTable5, kEcma262CanonicalizeTable5Size,
-+          kEcma262CanonicalizeMultiStrings5, c, n, result, allow_caching_ptr);
-+    case 7:
-+      return LookupMapping<true>(
-+          kEcma262CanonicalizeTable7, kEcma262CanonicalizeTable7Size,
-+          kEcma262CanonicalizeMultiStrings7, c, n, result, allow_caching_ptr);
-+    default:
-+      return 0;
-+  }
-+}
-+
-+static const MultiCharacterSpecialCase<4>
-+    kEcma262UnCanonicalizeMultiStrings0[507] = {  // NOLINT
-+        {{65, 97, kSentinel}},
-+        {{90, 122, kSentinel}},
-+        {{181, 924, 956, kSentinel}},
-+        {{192, 224, kSentinel}},  // NOLINT
-+        {{214, 246, kSentinel}},
-+        {{216, 248, kSentinel}},
-+        {{222, 254, kSentinel}},
-+        {{255, 376, kSentinel}},  // NOLINT
-+        {{256, 257, kSentinel}},
-+        {{258, 259, kSentinel}},
-+        {{260, 261, kSentinel}},
-+        {{262, 263, kSentinel}},  // NOLINT
-+        {{264, 265, kSentinel}},
-+        {{266, 267, kSentinel}},
-+        {{268, 269, kSentinel}},
-+        {{270, 271, kSentinel}},  // NOLINT
-+        {{272, 273, kSentinel}},
-+        {{274, 275, kSentinel}},
-+        {{276, 277, kSentinel}},
-+        {{278, 279, kSentinel}},  // NOLINT
-+        {{280, 281, kSentinel}},
-+        {{282, 283, kSentinel}},
-+        {{284, 285, kSentinel}},
-+        {{286, 287, kSentinel}},  // NOLINT
-+        {{288, 289, kSentinel}},
-+        {{290, 291, kSentinel}},
-+        {{292, 293, kSentinel}},
-+        {{294, 295, kSentinel}},  // NOLINT
-+        {{296, 297, kSentinel}},
-+        {{298, 299, kSentinel}},
-+        {{300, 301, kSentinel}},
-+        {{302, 303, kSentinel}},  // NOLINT
-+        {{306, 307, kSentinel}},
-+        {{308, 309, kSentinel}},
-+        {{310, 311, kSentinel}},
-+        {{313, 314, kSentinel}},  // NOLINT
-+        {{315, 316, kSentinel}},
-+        {{317, 318, kSentinel}},
-+        {{319, 320, kSentinel}},
-+        {{321, 322, kSentinel}},  // NOLINT
-+        {{323, 324, kSentinel}},
-+        {{325, 326, kSentinel}},
-+        {{327, 328, kSentinel}},
-+        {{330, 331, kSentinel}},  // NOLINT
-+        {{332, 333, kSentinel}},
-+        {{334, 335, kSentinel}},
-+        {{336, 337, kSentinel}},
-+        {{338, 339, kSentinel}},  // NOLINT
-+        {{340, 341, kSentinel}},
-+        {{342, 343, kSentinel}},
-+        {{344, 345, kSentinel}},
-+        {{346, 347, kSentinel}},  // NOLINT
-+        {{348, 349, kSentinel}},
-+        {{350, 351, kSentinel}},
-+        {{352, 353, kSentinel}},
-+        {{354, 355, kSentinel}},  // NOLINT
-+        {{356, 357, kSentinel}},
-+        {{358, 359, kSentinel}},
-+        {{360, 361, kSentinel}},
-+        {{362, 363, kSentinel}},  // NOLINT
-+        {{364, 365, kSentinel}},
-+        {{366, 367, kSentinel}},
-+        {{368, 369, kSentinel}},
-+        {{370, 371, kSentinel}},  // NOLINT
-+        {{372, 373, kSentinel}},
-+        {{374, 375, kSentinel}},
-+        {{377, 378, kSentinel}},
-+        {{379, 380, kSentinel}},  // NOLINT
-+        {{381, 382, kSentinel}},
-+        {{384, 579, kSentinel}},
-+        {{385, 595, kSentinel}},
-+        {{386, 387, kSentinel}},  // NOLINT
-+        {{388, 389, kSentinel}},
-+        {{390, 596, kSentinel}},
-+        {{391, 392, kSentinel}},
-+        {{393, 598, kSentinel}},  // NOLINT
-+        {{394, 599, kSentinel}},
-+        {{395, 396, kSentinel}},
-+        {{398, 477, kSentinel}},
-+        {{399, 601, kSentinel}},  // NOLINT
-+        {{400, 603, kSentinel}},
-+        {{401, 402, kSentinel}},
-+        {{403, 608, kSentinel}},
-+        {{404, 611, kSentinel}},  // NOLINT
-+        {{405, 502, kSentinel}},
-+        {{406, 617, kSentinel}},
-+        {{407, 616, kSentinel}},
-+        {{408, 409, kSentinel}},  // NOLINT
-+        {{410, 573, kSentinel}},
-+        {{412, 623, kSentinel}},
-+        {{413, 626, kSentinel}},
-+        {{414, 544, kSentinel}},  // NOLINT
-+        {{415, 629, kSentinel}},
-+        {{416, 417, kSentinel}},
-+        {{418, 419, kSentinel}},
-+        {{420, 421, kSentinel}},  // NOLINT
-+        {{422, 640, kSentinel}},
-+        {{423, 424, kSentinel}},
-+        {{425, 643, kSentinel}},
-+        {{428, 429, kSentinel}},  // NOLINT
-+        {{430, 648, kSentinel}},
-+        {{431, 432, kSentinel}},
-+        {{433, 650, kSentinel}},
-+        {{434, 651, kSentinel}},  // NOLINT
-+        {{435, 436, kSentinel}},
-+        {{437, 438, kSentinel}},
-+        {{439, 658, kSentinel}},
-+        {{440, 441, kSentinel}},  // NOLINT
-+        {{444, 445, kSentinel}},
-+        {{447, 503, kSentinel}},
-+        {{452, 453, 454, kSentinel}},
-+        {{455, 456, 457, kSentinel}},  // NOLINT
-+        {{458, 459, 460, kSentinel}},
-+        {{461, 462, kSentinel}},
-+        {{463, 464, kSentinel}},
-+        {{465, 466, kSentinel}},  // NOLINT
-+        {{467, 468, kSentinel}},
-+        {{469, 470, kSentinel}},
-+        {{471, 472, kSentinel}},
-+        {{473, 474, kSentinel}},  // NOLINT
-+        {{475, 476, kSentinel}},
-+        {{478, 479, kSentinel}},
-+        {{480, 481, kSentinel}},
-+        {{482, 483, kSentinel}},  // NOLINT
-+        {{484, 485, kSentinel}},
-+        {{486, 487, kSentinel}},
-+        {{488, 489, kSentinel}},
-+        {{490, 491, kSentinel}},  // NOLINT
-+        {{492, 493, kSentinel}},
-+        {{494, 495, kSentinel}},
-+        {{497, 498, 499, kSentinel}},
-+        {{500, 501, kSentinel}},  // NOLINT
-+        {{504, 505, kSentinel}},
-+        {{506, 507, kSentinel}},
-+        {{508, 509, kSentinel}},
-+        {{510, 511, kSentinel}},  // NOLINT
-+        {{512, 513, kSentinel}},
-+        {{514, 515, kSentinel}},
-+        {{516, 517, kSentinel}},
-+        {{518, 519, kSentinel}},  // NOLINT
-+        {{520, 521, kSentinel}},
-+        {{522, 523, kSentinel}},
-+        {{524, 525, kSentinel}},
-+        {{526, 527, kSentinel}},  // NOLINT
-+        {{528, 529, kSentinel}},
-+        {{530, 531, kSentinel}},
-+        {{532, 533, kSentinel}},
-+        {{534, 535, kSentinel}},  // NOLINT
-+        {{536, 537, kSentinel}},
-+        {{538, 539, kSentinel}},
-+        {{540, 541, kSentinel}},
-+        {{542, 543, kSentinel}},  // NOLINT
-+        {{546, 547, kSentinel}},
-+        {{548, 549, kSentinel}},
-+        {{550, 551, kSentinel}},
-+        {{552, 553, kSentinel}},  // NOLINT
-+        {{554, 555, kSentinel}},
-+        {{556, 557, kSentinel}},
-+        {{558, 559, kSentinel}},
-+        {{560, 561, kSentinel}},  // NOLINT
-+        {{562, 563, kSentinel}},
-+        {{570, 11365, kSentinel}},
-+        {{571, 572, kSentinel}},
-+        {{574, 11366, kSentinel}},  // NOLINT
-+        {{575, 11390, kSentinel}},
-+        {{576, 11391, kSentinel}},
-+        {{577, 578, kSentinel}},
-+        {{580, 649, kSentinel}},  // NOLINT
-+        {{581, 652, kSentinel}},
-+        {{582, 583, kSentinel}},
-+        {{584, 585, kSentinel}},
-+        {{586, 587, kSentinel}},  // NOLINT
-+        {{588, 589, kSentinel}},
-+        {{590, 591, kSentinel}},
-+        {{592, 11375, kSentinel}},
-+        {{593, 11373, kSentinel}},  // NOLINT
-+        {{594, 11376, kSentinel}},
-+        {{604, 42923, kSentinel}},
-+        {{609, 42924, kSentinel}},
-+        {{613, 42893, kSentinel}},  // NOLINT
-+        {{614, 42922, kSentinel}},
-+        {{619, 11362, kSentinel}},
-+        {{620, 42925, kSentinel}},
-+        {{625, 11374, kSentinel}},  // NOLINT
-+        {{637, 11364, kSentinel}},
-+        {{647, 42929, kSentinel}},
-+        {{670, 42928, kSentinel}},
-+        {{837, 921, 953, 8126}},  // NOLINT
-+        {{880, 881, kSentinel}},
-+        {{882, 883, kSentinel}},
-+        {{886, 887, kSentinel}},
-+        {{891, 1021, kSentinel}},  // NOLINT
-+        {{893, 1023, kSentinel}},
-+        {{895, 1011, kSentinel}},
-+        {{902, 940, kSentinel}},
-+        {{904, 941, kSentinel}},  // NOLINT
-+        {{906, 943, kSentinel}},
-+        {{908, 972, kSentinel}},
-+        {{910, 973, kSentinel}},
-+        {{911, 974, kSentinel}},  // NOLINT
-+        {{913, 945, kSentinel}},
-+        {{914, 946, 976, kSentinel}},
-+        {{915, 947, kSentinel}},
-+        {{916, 948, kSentinel}},  // NOLINT
-+        {{917, 949, 1013, kSentinel}},
-+        {{918, 950, kSentinel}},
-+        {{919, 951, kSentinel}},
-+        {{920, 952, 977, kSentinel}},  // NOLINT
-+        {{922, 954, 1008, kSentinel}},
-+        {{923, 955, kSentinel}},
-+        {{925, 957, kSentinel}},
-+        {{927, 959, kSentinel}},  // NOLINT
-+        {{928, 960, 982, kSentinel}},
-+        {{929, 961, 1009, kSentinel}},
-+        {{931, 962, 963, kSentinel}},
-+        {{932, 964, kSentinel}},  // NOLINT
-+        {{933, 965, kSentinel}},
-+        {{934, 966, 981, kSentinel}},
-+        {{935, 967, kSentinel}},
-+        {{939, 971, kSentinel}},  // NOLINT
-+        {{975, 983, kSentinel}},
-+        {{984, 985, kSentinel}},
-+        {{986, 987, kSentinel}},
-+        {{988, 989, kSentinel}},  // NOLINT
-+        {{990, 991, kSentinel}},
-+        {{992, 993, kSentinel}},
-+        {{994, 995, kSentinel}},
-+        {{996, 997, kSentinel}},  // NOLINT
-+        {{998, 999, kSentinel}},
-+        {{1000, 1001, kSentinel}},
-+        {{1002, 1003, kSentinel}},
-+        {{1004, 1005, kSentinel}},  // NOLINT
-+        {{1006, 1007, kSentinel}},
-+        {{1010, 1017, kSentinel}},
-+        {{1015, 1016, kSentinel}},
-+        {{1018, 1019, kSentinel}},  // NOLINT
-+        {{1024, 1104, kSentinel}},
-+        {{1039, 1119, kSentinel}},
-+        {{1040, 1072, kSentinel}},
-+        {{1071, 1103, kSentinel}},  // NOLINT
-+        {{1120, 1121, kSentinel}},
-+        {{1122, 1123, kSentinel}},
-+        {{1124, 1125, kSentinel}},
-+        {{1126, 1127, kSentinel}},  // NOLINT
-+        {{1128, 1129, kSentinel}},
-+        {{1130, 1131, kSentinel}},
-+        {{1132, 1133, kSentinel}},
-+        {{1134, 1135, kSentinel}},  // NOLINT
-+        {{1136, 1137, kSentinel}},
-+        {{1138, 1139, kSentinel}},
-+        {{1140, 1141, kSentinel}},
-+        {{1142, 1143, kSentinel}},  // NOLINT
-+        {{1144, 1145, kSentinel}},
-+        {{1146, 1147, kSentinel}},
-+        {{1148, 1149, kSentinel}},
-+        {{1150, 1151, kSentinel}},  // NOLINT
-+        {{1152, 1153, kSentinel}},
-+        {{1162, 1163, kSentinel}},
-+        {{1164, 1165, kSentinel}},
-+        {{1166, 1167, kSentinel}},  // NOLINT
-+        {{1168, 1169, kSentinel}},
-+        {{1170, 1171, kSentinel}},
-+        {{1172, 1173, kSentinel}},
-+        {{1174, 1175, kSentinel}},  // NOLINT
-+        {{1176, 1177, kSentinel}},
-+        {{1178, 1179, kSentinel}},
-+        {{1180, 1181, kSentinel}},
-+        {{1182, 1183, kSentinel}},  // NOLINT
-+        {{1184, 1185, kSentinel}},
-+        {{1186, 1187, kSentinel}},
-+        {{1188, 1189, kSentinel}},
-+        {{1190, 1191, kSentinel}},  // NOLINT
-+        {{1192, 1193, kSentinel}},
-+        {{1194, 1195, kSentinel}},
-+        {{1196, 1197, kSentinel}},
-+        {{1198, 1199, kSentinel}},  // NOLINT
-+        {{1200, 1201, kSentinel}},
-+        {{1202, 1203, kSentinel}},
-+        {{1204, 1205, kSentinel}},
-+        {{1206, 1207, kSentinel}},  // NOLINT
-+        {{1208, 1209, kSentinel}},
-+        {{1210, 1211, kSentinel}},
-+        {{1212, 1213, kSentinel}},
-+        {{1214, 1215, kSentinel}},  // NOLINT
-+        {{1216, 1231, kSentinel}},
-+        {{1217, 1218, kSentinel}},
-+        {{1219, 1220, kSentinel}},
-+        {{1221, 1222, kSentinel}},  // NOLINT
-+        {{1223, 1224, kSentinel}},
-+        {{1225, 1226, kSentinel}},
-+        {{1227, 1228, kSentinel}},
-+        {{1229, 1230, kSentinel}},  // NOLINT
-+        {{1232, 1233, kSentinel}},
-+        {{1234, 1235, kSentinel}},
-+        {{1236, 1237, kSentinel}},
-+        {{1238, 1239, kSentinel}},  // NOLINT
-+        {{1240, 1241, kSentinel}},
-+        {{1242, 1243, kSentinel}},
-+        {{1244, 1245, kSentinel}},
-+        {{1246, 1247, kSentinel}},  // NOLINT
-+        {{1248, 1249, kSentinel}},
-+        {{1250, 1251, kSentinel}},
-+        {{1252, 1253, kSentinel}},
-+        {{1254, 1255, kSentinel}},  // NOLINT
-+        {{1256, 1257, kSentinel}},
-+        {{1258, 1259, kSentinel}},
-+        {{1260, 1261, kSentinel}},
-+        {{1262, 1263, kSentinel}},  // NOLINT
-+        {{1264, 1265, kSentinel}},
-+        {{1266, 1267, kSentinel}},
-+        {{1268, 1269, kSentinel}},
-+        {{1270, 1271, kSentinel}},  // NOLINT
-+        {{1272, 1273, kSentinel}},
-+        {{1274, 1275, kSentinel}},
-+        {{1276, 1277, kSentinel}},
-+        {{1278, 1279, kSentinel}},  // NOLINT
-+        {{1280, 1281, kSentinel}},
-+        {{1282, 1283, kSentinel}},
-+        {{1284, 1285, kSentinel}},
-+        {{1286, 1287, kSentinel}},  // NOLINT
-+        {{1288, 1289, kSentinel}},
-+        {{1290, 1291, kSentinel}},
-+        {{1292, 1293, kSentinel}},
-+        {{1294, 1295, kSentinel}},  // NOLINT
-+        {{1296, 1297, kSentinel}},
-+        {{1298, 1299, kSentinel}},
-+        {{1300, 1301, kSentinel}},
-+        {{1302, 1303, kSentinel}},  // NOLINT
-+        {{1304, 1305, kSentinel}},
-+        {{1306, 1307, kSentinel}},
-+        {{1308, 1309, kSentinel}},
-+        {{1310, 1311, kSentinel}},  // NOLINT
-+        {{1312, 1313, kSentinel}},
-+        {{1314, 1315, kSentinel}},
-+        {{1316, 1317, kSentinel}},
-+        {{1318, 1319, kSentinel}},  // NOLINT
-+        {{1320, 1321, kSentinel}},
-+        {{1322, 1323, kSentinel}},
-+        {{1324, 1325, kSentinel}},
-+        {{1326, 1327, kSentinel}},  // NOLINT
-+        {{1329, 1377, kSentinel}},
-+        {{1366, 1414, kSentinel}},
-+        {{4256, 11520, kSentinel}},
-+        {{4293, 11557, kSentinel}},  // NOLINT
-+        {{4295, 11559, kSentinel}},
-+        {{4301, 11565, kSentinel}},
-+        {{7545, 42877, kSentinel}},
-+        {{7549, 11363, kSentinel}},  // NOLINT
-+        {{7680, 7681, kSentinel}},
-+        {{7682, 7683, kSentinel}},
-+        {{7684, 7685, kSentinel}},
-+        {{7686, 7687, kSentinel}},  // NOLINT
-+        {{7688, 7689, kSentinel}},
-+        {{7690, 7691, kSentinel}},
-+        {{7692, 7693, kSentinel}},
-+        {{7694, 7695, kSentinel}},  // NOLINT
-+        {{7696, 7697, kSentinel}},
-+        {{7698, 7699, kSentinel}},
-+        {{7700, 7701, kSentinel}},
-+        {{7702, 7703, kSentinel}},  // NOLINT
-+        {{7704, 7705, kSentinel}},
-+        {{7706, 7707, kSentinel}},
-+        {{7708, 7709, kSentinel}},
-+        {{7710, 7711, kSentinel}},  // NOLINT
-+        {{7712, 7713, kSentinel}},
-+        {{7714, 7715, kSentinel}},
-+        {{7716, 7717, kSentinel}},
-+        {{7718, 7719, kSentinel}},  // NOLINT
-+        {{7720, 7721, kSentinel}},
-+        {{7722, 7723, kSentinel}},
-+        {{7724, 7725, kSentinel}},
-+        {{7726, 7727, kSentinel}},  // NOLINT
-+        {{7728, 7729, kSentinel}},
-+        {{7730, 7731, kSentinel}},
-+        {{7732, 7733, kSentinel}},
-+        {{7734, 7735, kSentinel}},  // NOLINT
-+        {{7736, 7737, kSentinel}},
-+        {{7738, 7739, kSentinel}},
-+        {{7740, 7741, kSentinel}},
-+        {{7742, 7743, kSentinel}},  // NOLINT
-+        {{7744, 7745, kSentinel}},
-+        {{7746, 7747, kSentinel}},
-+        {{7748, 7749, kSentinel}},
-+        {{7750, 7751, kSentinel}},  // NOLINT
-+        {{7752, 7753, kSentinel}},
-+        {{7754, 7755, kSentinel}},
-+        {{7756, 7757, kSentinel}},
-+        {{7758, 7759, kSentinel}},  // NOLINT
-+        {{7760, 7761, kSentinel}},
-+        {{7762, 7763, kSentinel}},
-+        {{7764, 7765, kSentinel}},
-+        {{7766, 7767, kSentinel}},  // NOLINT
-+        {{7768, 7769, kSentinel}},
-+        {{7770, 7771, kSentinel}},
-+        {{7772, 7773, kSentinel}},
-+        {{7774, 7775, kSentinel}},  // NOLINT
-+        {{7776, 7777, 7835, kSentinel}},
-+        {{7778, 7779, kSentinel}},
-+        {{7780, 7781, kSentinel}},
-+        {{7782, 7783, kSentinel}},  // NOLINT
-+        {{7784, 7785, kSentinel}},
-+        {{7786, 7787, kSentinel}},
-+        {{7788, 7789, kSentinel}},
-+        {{7790, 7791, kSentinel}},  // NOLINT
-+        {{7792, 7793, kSentinel}},
-+        {{7794, 7795, kSentinel}},
-+        {{7796, 7797, kSentinel}},
-+        {{7798, 7799, kSentinel}},  // NOLINT
-+        {{7800, 7801, kSentinel}},
-+        {{7802, 7803, kSentinel}},
-+        {{7804, 7805, kSentinel}},
-+        {{7806, 7807, kSentinel}},  // NOLINT
-+        {{7808, 7809, kSentinel}},
-+        {{7810, 7811, kSentinel}},
-+        {{7812, 7813, kSentinel}},
-+        {{7814, 7815, kSentinel}},  // NOLINT
-+        {{7816, 7817, kSentinel}},
-+        {{7818, 7819, kSentinel}},
-+        {{7820, 7821, kSentinel}},
-+        {{7822, 7823, kSentinel}},  // NOLINT
-+        {{7824, 7825, kSentinel}},
-+        {{7826, 7827, kSentinel}},
-+        {{7828, 7829, kSentinel}},
-+        {{7840, 7841, kSentinel}},  // NOLINT
-+        {{7842, 7843, kSentinel}},
-+        {{7844, 7845, kSentinel}},
-+        {{7846, 7847, kSentinel}},
-+        {{7848, 7849, kSentinel}},  // NOLINT
-+        {{7850, 7851, kSentinel}},
-+        {{7852, 7853, kSentinel}},
-+        {{7854, 7855, kSentinel}},
-+        {{7856, 7857, kSentinel}},  // NOLINT
-+        {{7858, 7859, kSentinel}},
-+        {{7860, 7861, kSentinel}},
-+        {{7862, 7863, kSentinel}},
-+        {{7864, 7865, kSentinel}},  // NOLINT
-+        {{7866, 7867, kSentinel}},
-+        {{7868, 7869, kSentinel}},
-+        {{7870, 7871, kSentinel}},
-+        {{7872, 7873, kSentinel}},  // NOLINT
-+        {{7874, 7875, kSentinel}},
-+        {{7876, 7877, kSentinel}},
-+        {{7878, 7879, kSentinel}},
-+        {{7880, 7881, kSentinel}},  // NOLINT
-+        {{7882, 7883, kSentinel}},
-+        {{7884, 7885, kSentinel}},
-+        {{7886, 7887, kSentinel}},
-+        {{7888, 7889, kSentinel}},  // NOLINT
-+        {{7890, 7891, kSentinel}},
-+        {{7892, 7893, kSentinel}},
-+        {{7894, 7895, kSentinel}},
-+        {{7896, 7897, kSentinel}},  // NOLINT
-+        {{7898, 7899, kSentinel}},
-+        {{7900, 7901, kSentinel}},
-+        {{7902, 7903, kSentinel}},
-+        {{7904, 7905, kSentinel}},  // NOLINT
-+        {{7906, 7907, kSentinel}},
-+        {{7908, 7909, kSentinel}},
-+        {{7910, 7911, kSentinel}},
-+        {{7912, 7913, kSentinel}},  // NOLINT
-+        {{7914, 7915, kSentinel}},
-+        {{7916, 7917, kSentinel}},
-+        {{7918, 7919, kSentinel}},
-+        {{7920, 7921, kSentinel}},  // NOLINT
-+        {{7922, 7923, kSentinel}},
-+        {{7924, 7925, kSentinel}},
-+        {{7926, 7927, kSentinel}},
-+        {{7928, 7929, kSentinel}},  // NOLINT
-+        {{7930, 7931, kSentinel}},
-+        {{7932, 7933, kSentinel}},
-+        {{7934, 7935, kSentinel}},
-+        {{7936, 7944, kSentinel}},  // NOLINT
-+        {{7943, 7951, kSentinel}},
-+        {{7952, 7960, kSentinel}},
-+        {{7957, 7965, kSentinel}},
-+        {{7968, 7976, kSentinel}},  // NOLINT
-+        {{7975, 7983, kSentinel}},
-+        {{7984, 7992, kSentinel}},
-+        {{7991, 7999, kSentinel}},
-+        {{8000, 8008, kSentinel}},  // NOLINT
-+        {{8005, 8013, kSentinel}},
-+        {{8017, 8025, kSentinel}},
-+        {{8019, 8027, kSentinel}},
-+        {{8021, 8029, kSentinel}},  // NOLINT
-+        {{8023, 8031, kSentinel}},
-+        {{8032, 8040, kSentinel}},
-+        {{8039, 8047, kSentinel}},
-+        {{8048, 8122, kSentinel}},  // NOLINT
-+        {{8049, 8123, kSentinel}},
-+        {{8050, 8136, kSentinel}},
-+        {{8053, 8139, kSentinel}},
-+        {{8054, 8154, kSentinel}},  // NOLINT
-+        {{8055, 8155, kSentinel}},
-+        {{8056, 8184, kSentinel}},
-+        {{8057, 8185, kSentinel}},
-+        {{8058, 8170, kSentinel}},  // NOLINT
-+        {{8059, 8171, kSentinel}},
-+        {{8060, 8186, kSentinel}},
-+        {{8061, 8187, kSentinel}},
-+        {{8112, 8120, kSentinel}},  // NOLINT
-+        {{8113, 8121, kSentinel}},
-+        {{8144, 8152, kSentinel}},
-+        {{8145, 8153, kSentinel}},
-+        {{8160, 8168, kSentinel}},  // NOLINT
-+        {{8161, 8169, kSentinel}},
-+        {{8165, 8172, kSentinel}},
-+        {{kSentinel}}};                                         // NOLINT
-+static const uint16_t kEcma262UnCanonicalizeTable0Size = 1005;  // NOLINT
-+static const int32_t kEcma262UnCanonicalizeTable0[2010] = {
-+    1073741889, 1,    90,         5,    1073741921, 1,
-+    122,        5,    181,        9,    1073742016, 13,
-+    214,        17,   1073742040, 21,  // NOLINT
-+    222,        25,   1073742048, 13,   246,        17,
-+    1073742072, 21,   254,        25,   255,        29,
-+    256,        33,   257,        33,  // NOLINT
-+    258,        37,   259,        37,   260,        41,
-+    261,        41,   262,        45,   263,        45,
-+    264,        49,   265,        49,  // NOLINT
-+    266,        53,   267,        53,   268,        57,
-+    269,        57,   270,        61,   271,        61,
-+    272,        65,   273,        65,  // NOLINT
-+    274,        69,   275,        69,   276,        73,
-+    277,        73,   278,        77,   279,        77,
-+    280,        81,   281,        81,  // NOLINT
-+    282,        85,   283,        85,   284,        89,
-+    285,        89,   286,        93,   287,        93,
-+    288,        97,   289,        97,  // NOLINT
-+    290,        101,  291,        101,  292,        105,
-+    293,        105,  294,        109,  295,        109,
-+    296,        113,  297,        113,  // NOLINT
-+    298,        117,  299,        117,  300,        121,
-+    301,        121,  302,        125,  303,        125,
-+    306,        129,  307,        129,  // NOLINT
-+    308,        133,  309,        133,  310,        137,
-+    311,        137,  313,        141,  314,        141,
-+    315,        145,  316,        145,  // NOLINT
-+    317,        149,  318,        149,  319,        153,
-+    320,        153,  321,        157,  322,        157,
-+    323,        161,  324,        161,  // NOLINT
-+    325,        165,  326,        165,  327,        169,
-+    328,        169,  330,        173,  331,        173,
-+    332,        177,  333,        177,  // NOLINT
-+    334,        181,  335,        181,  336,        185,
-+    337,        185,  338,        189,  339,        189,
-+    340,        193,  341,        193,  // NOLINT
-+    342,        197,  343,        197,  344,        201,
-+    345,        201,  346,        205,  347,        205,
-+    348,        209,  349,        209,  // NOLINT
-+    350,        213,  351,        213,  352,        217,
-+    353,        217,  354,        221,  355,        221,
-+    356,        225,  357,        225,  // NOLINT
-+    358,        229,  359,        229,  360,        233,
-+    361,        233,  362,        237,  363,        237,
-+    364,        241,  365,        241,  // NOLINT
-+    366,        245,  367,        245,  368,        249,
-+    369,        249,  370,        253,  371,        253,
-+    372,        257,  373,        257,  // NOLINT
-+    374,        261,  375,        261,  376,        29,
-+    377,        265,  378,        265,  379,        269,
-+    380,        269,  381,        273,  // NOLINT
-+    382,        273,  384,        277,  385,        281,
-+    386,        285,  387,        285,  388,        289,
-+    389,        289,  390,        293,  // NOLINT
-+    391,        297,  392,        297,  1073742217, 301,
-+    394,        305,  395,        309,  396,        309,
-+    398,        313,  399,        317,  // NOLINT
-+    400,        321,  401,        325,  402,        325,
-+    403,        329,  404,        333,  405,        337,
-+    406,        341,  407,        345,  // NOLINT
-+    408,        349,  409,        349,  410,        353,
-+    412,        357,  413,        361,  414,        365,
-+    415,        369,  416,        373,  // NOLINT
-+    417,        373,  418,        377,  419,        377,
-+    420,        381,  421,        381,  422,        385,
-+    423,        389,  424,        389,  // NOLINT
-+    425,        393,  428,        397,  429,        397,
-+    430,        401,  431,        405,  432,        405,
-+    1073742257, 409,  434,        413,  // NOLINT
-+    435,        417,  436,        417,  437,        421,
-+    438,        421,  439,        425,  440,        429,
-+    441,        429,  444,        433,  // NOLINT
-+    445,        433,  447,        437,  452,        441,
-+    453,        441,  454,        441,  455,        445,
-+    456,        445,  457,        445,  // NOLINT
-+    458,        449,  459,        449,  460,        449,
-+    461,        453,  462,        453,  463,        457,
-+    464,        457,  465,        461,  // NOLINT
-+    466,        461,  467,        465,  468,        465,
-+    469,        469,  470,        469,  471,        473,
-+    472,        473,  473,        477,  // NOLINT
-+    474,        477,  475,        481,  476,        481,
-+    477,        313,  478,        485,  479,        485,
-+    480,        489,  481,        489,  // NOLINT
-+    482,        493,  483,        493,  484,        497,
-+    485,        497,  486,        501,  487,        501,
-+    488,        505,  489,        505,  // NOLINT
-+    490,        509,  491,        509,  492,        513,
-+    493,        513,  494,        517,  495,        517,
-+    497,        521,  498,        521,  // NOLINT
-+    499,        521,  500,        525,  501,        525,
-+    502,        337,  503,        437,  504,        529,
-+    505,        529,  506,        533,  // NOLINT
-+    507,        533,  508,        537,  509,        537,
-+    510,        541,  511,        541,  512,        545,
-+    513,        545,  514,        549,  // NOLINT
-+    515,        549,  516,        553,  517,        553,
-+    518,        557,  519,        557,  520,        561,
-+    521,        561,  522,        565,  // NOLINT
-+    523,        565,  524,        569,  525,        569,
-+    526,        573,  527,        573,  528,        577,
-+    529,        577,  530,        581,  // NOLINT
-+    531,        581,  532,        585,  533,        585,
-+    534,        589,  535,        589,  536,        593,
-+    537,        593,  538,        597,  // NOLINT
-+    539,        597,  540,        601,  541,        601,
-+    542,        605,  543,        605,  544,        365,
-+    546,        609,  547,        609,  // NOLINT
-+    548,        613,  549,        613,  550,        617,
-+    551,        617,  552,        621,  553,        621,
-+    554,        625,  555,        625,  // NOLINT
-+    556,        629,  557,        629,  558,        633,
-+    559,        633,  560,        637,  561,        637,
-+    562,        641,  563,        641,  // NOLINT
-+    570,        645,  571,        649,  572,        649,
-+    573,        353,  574,        653,  1073742399, 657,
-+    576,        661,  577,        665,  // NOLINT
-+    578,        665,  579,        277,  580,        669,
-+    581,        673,  582,        677,  583,        677,
-+    584,        681,  585,        681,  // NOLINT
-+    586,        685,  587,        685,  588,        689,
-+    589,        689,  590,        693,  591,        693,
-+    592,        697,  593,        701,  // NOLINT
-+    594,        705,  595,        281,  596,        293,
-+    1073742422, 301,  599,        305,  601,        317,
-+    603,        321,  604,        709,  // NOLINT
-+    608,        329,  609,        713,  611,        333,
-+    613,        717,  614,        721,  616,        345,
-+    617,        341,  619,        725,  // NOLINT
-+    620,        729,  623,        357,  625,        733,
-+    626,        361,  629,        369,  637,        737,
-+    640,        385,  643,        393,  // NOLINT
-+    647,        741,  648,        401,  649,        669,
-+    1073742474, 409,  651,        413,  652,        673,
-+    658,        425,  670,        745,  // NOLINT
-+    837,        749,  880,        753,  881,        753,
-+    882,        757,  883,        757,  886,        761,
-+    887,        761,  1073742715, 765,  // NOLINT
-+    893,        769,  895,        773,  902,        777,
-+    1073742728, 781,  906,        785,  908,        789,
-+    1073742734, 793,  911,        797,  // NOLINT
-+    913,        801,  914,        805,  1073742739, 809,
-+    916,        813,  917,        817,  1073742742, 821,
-+    919,        825,  920,        829,  // NOLINT
-+    921,        749,  922,        833,  923,        837,
-+    924,        9,    1073742749, 841,  927,        845,
-+    928,        849,  929,        853,  // NOLINT
-+    931,        857,  1073742756, 861,  933,        865,
-+    934,        869,  1073742759, 873,  939,        877,
-+    940,        777,  1073742765, 781,  // NOLINT
-+    943,        785,  945,        801,  946,        805,
-+    1073742771, 809,  948,        813,  949,        817,
-+    1073742774, 821,  951,        825,  // NOLINT
-+    952,        829,  953,        749,  954,        833,
-+    955,        837,  956,        9,    1073742781, 841,
-+    959,        845,  960,        849,  // NOLINT
-+    961,        853,  962,        857,  963,        857,
-+    1073742788, 861,  965,        865,  966,        869,
-+    1073742791, 873,  971,        877,  // NOLINT
-+    972,        789,  1073742797, 793,  974,        797,
-+    975,        881,  976,        805,  977,        829,
-+    981,        869,  982,        849,  // NOLINT
-+    983,        881,  984,        885,  985,        885,
-+    986,        889,  987,        889,  988,        893,
-+    989,        893,  990,        897,  // NOLINT
-+    991,        897,  992,        901,  993,        901,
-+    994,        905,  995,        905,  996,        909,
-+    997,        909,  998,        913,  // NOLINT
-+    999,        913,  1000,       917,  1001,       917,
-+    1002,       921,  1003,       921,  1004,       925,
-+    1005,       925,  1006,       929,  // NOLINT
-+    1007,       929,  1008,       833,  1009,       853,
-+    1010,       933,  1011,       773,  1013,       817,
-+    1015,       937,  1016,       937,  // NOLINT
-+    1017,       933,  1018,       941,  1019,       941,
-+    1073742845, 765,  1023,       769,  1073742848, 945,
-+    1039,       949,  1073742864, 953,  // NOLINT
-+    1071,       957,  1073742896, 953,  1103,       957,
-+    1073742928, 945,  1119,       949,  1120,       961,
-+    1121,       961,  1122,       965,  // NOLINT
-+    1123,       965,  1124,       969,  1125,       969,
-+    1126,       973,  1127,       973,  1128,       977,
-+    1129,       977,  1130,       981,  // NOLINT
-+    1131,       981,  1132,       985,  1133,       985,
-+    1134,       989,  1135,       989,  1136,       993,
-+    1137,       993,  1138,       997,  // NOLINT
-+    1139,       997,  1140,       1001, 1141,       1001,
-+    1142,       1005, 1143,       1005, 1144,       1009,
-+    1145,       1009, 1146,       1013,  // NOLINT
-+    1147,       1013, 1148,       1017, 1149,       1017,
-+    1150,       1021, 1151,       1021, 1152,       1025,
-+    1153,       1025, 1162,       1029,  // NOLINT
-+    1163,       1029, 1164,       1033, 1165,       1033,
-+    1166,       1037, 1167,       1037, 1168,       1041,
-+    1169,       1041, 1170,       1045,  // NOLINT
-+    1171,       1045, 1172,       1049, 1173,       1049,
-+    1174,       1053, 1175,       1053, 1176,       1057,
-+    1177,       1057, 1178,       1061,  // NOLINT
-+    1179,       1061, 1180,       1065, 1181,       1065,
-+    1182,       1069, 1183,       1069, 1184,       1073,
-+    1185,       1073, 1186,       1077,  // NOLINT
-+    1187,       1077, 1188,       1081, 1189,       1081,
-+    1190,       1085, 1191,       1085, 1192,       1089,
-+    1193,       1089, 1194,       1093,  // NOLINT
-+    1195,       1093, 1196,       1097, 1197,       1097,
-+    1198,       1101, 1199,       1101, 1200,       1105,
-+    1201,       1105, 1202,       1109,  // NOLINT
-+    1203,       1109, 1204,       1113, 1205,       1113,
-+    1206,       1117, 1207,       1117, 1208,       1121,
-+    1209,       1121, 1210,       1125,  // NOLINT
-+    1211,       1125, 1212,       1129, 1213,       1129,
-+    1214,       1133, 1215,       1133, 1216,       1137,
-+    1217,       1141, 1218,       1141,  // NOLINT
-+    1219,       1145, 1220,       1145, 1221,       1149,
-+    1222,       1149, 1223,       1153, 1224,       1153,
-+    1225,       1157, 1226,       1157,  // NOLINT
-+    1227,       1161, 1228,       1161, 1229,       1165,
-+    1230,       1165, 1231,       1137, 1232,       1169,
-+    1233,       1169, 1234,       1173,  // NOLINT
-+    1235,       1173, 1236,       1177, 1237,       1177,
-+    1238,       1181, 1239,       1181, 1240,       1185,
-+    1241,       1185, 1242,       1189,  // NOLINT
-+    1243,       1189, 1244,       1193, 1245,       1193,
-+    1246,       1197, 1247,       1197, 1248,       1201,
-+    1249,       1201, 1250,       1205,  // NOLINT
-+    1251,       1205, 1252,       1209, 1253,       1209,
-+    1254,       1213, 1255,       1213, 1256,       1217,
-+    1257,       1217, 1258,       1221,  // NOLINT
-+    1259,       1221, 1260,       1225, 1261,       1225,
-+    1262,       1229, 1263,       1229, 1264,       1233,
-+    1265,       1233, 1266,       1237,  // NOLINT
-+    1267,       1237, 1268,       1241, 1269,       1241,
-+    1270,       1245, 1271,       1245, 1272,       1249,
-+    1273,       1249, 1274,       1253,  // NOLINT
-+    1275,       1253, 1276,       1257, 1277,       1257,
-+    1278,       1261, 1279,       1261, 1280,       1265,
-+    1281,       1265, 1282,       1269,  // NOLINT
-+    1283,       1269, 1284,       1273, 1285,       1273,
-+    1286,       1277, 1287,       1277, 1288,       1281,
-+    1289,       1281, 1290,       1285,  // NOLINT
-+    1291,       1285, 1292,       1289, 1293,       1289,
-+    1294,       1293, 1295,       1293, 1296,       1297,
-+    1297,       1297, 1298,       1301,  // NOLINT
-+    1299,       1301, 1300,       1305, 1301,       1305,
-+    1302,       1309, 1303,       1309, 1304,       1313,
-+    1305,       1313, 1306,       1317,  // NOLINT
-+    1307,       1317, 1308,       1321, 1309,       1321,
-+    1310,       1325, 1311,       1325, 1312,       1329,
-+    1313,       1329, 1314,       1333,  // NOLINT
-+    1315,       1333, 1316,       1337, 1317,       1337,
-+    1318,       1341, 1319,       1341, 1320,       1345,
-+    1321,       1345, 1322,       1349,  // NOLINT
-+    1323,       1349, 1324,       1353, 1325,       1353,
-+    1326,       1357, 1327,       1357, 1073743153, 1361,
-+    1366,       1365, 1073743201, 1361,  // NOLINT
-+    1414,       1365, 1073746080, 1369, 4293,       1373,
-+    4295,       1377, 4301,       1381, 7545,       1385,
-+    7549,       1389, 7680,       1393,  // NOLINT
-+    7681,       1393, 7682,       1397, 7683,       1397,
-+    7684,       1401, 7685,       1401, 7686,       1405,
-+    7687,       1405, 7688,       1409,  // NOLINT
-+    7689,       1409, 7690,       1413, 7691,       1413,
-+    7692,       1417, 7693,       1417, 7694,       1421,
-+    7695,       1421, 7696,       1425,  // NOLINT
-+    7697,       1425, 7698,       1429, 7699,       1429,
-+    7700,       1433, 7701,       1433, 7702,       1437,
-+    7703,       1437, 7704,       1441,  // NOLINT
-+    7705,       1441, 7706,       1445, 7707,       1445,
-+    7708,       1449, 7709,       1449, 7710,       1453,
-+    7711,       1453, 7712,       1457,  // NOLINT
-+    7713,       1457, 7714,       1461, 7715,       1461,
-+    7716,       1465, 7717,       1465, 7718,       1469,
-+    7719,       1469, 7720,       1473,  // NOLINT
-+    7721,       1473, 7722,       1477, 7723,       1477,
-+    7724,       1481, 7725,       1481, 7726,       1485,
-+    7727,       1485, 7728,       1489,  // NOLINT
-+    7729,       1489, 7730,       1493, 7731,       1493,
-+    7732,       1497, 7733,       1497, 7734,       1501,
-+    7735,       1501, 7736,       1505,  // NOLINT
-+    7737,       1505, 7738,       1509, 7739,       1509,
-+    7740,       1513, 7741,       1513, 7742,       1517,
-+    7743,       1517, 7744,       1521,  // NOLINT
-+    7745,       1521, 7746,       1525, 7747,       1525,
-+    7748,       1529, 7749,       1529, 7750,       1533,
-+    7751,       1533, 7752,       1537,  // NOLINT
-+    7753,       1537, 7754,       1541, 7755,       1541,
-+    7756,       1545, 7757,       1545, 7758,       1549,
-+    7759,       1549, 7760,       1553,  // NOLINT
-+    7761,       1553, 7762,       1557, 7763,       1557,
-+    7764,       1561, 7765,       1561, 7766,       1565,
-+    7767,       1565, 7768,       1569,  // NOLINT
-+    7769,       1569, 7770,       1573, 7771,       1573,
-+    7772,       1577, 7773,       1577, 7774,       1581,
-+    7775,       1581, 7776,       1585,  // NOLINT
-+    7777,       1585, 7778,       1589, 7779,       1589,
-+    7780,       1593, 7781,       1593, 7782,       1597,
-+    7783,       1597, 7784,       1601,  // NOLINT
-+    7785,       1601, 7786,       1605, 7787,       1605,
-+    7788,       1609, 7789,       1609, 7790,       1613,
-+    7791,       1613, 7792,       1617,  // NOLINT
-+    7793,       1617, 7794,       1621, 7795,       1621,
-+    7796,       1625, 7797,       1625, 7798,       1629,
-+    7799,       1629, 7800,       1633,  // NOLINT
-+    7801,       1633, 7802,       1637, 7803,       1637,
-+    7804,       1641, 7805,       1641, 7806,       1645,
-+    7807,       1645, 7808,       1649,  // NOLINT
-+    7809,       1649, 7810,       1653, 7811,       1653,
-+    7812,       1657, 7813,       1657, 7814,       1661,
-+    7815,       1661, 7816,       1665,  // NOLINT
-+    7817,       1665, 7818,       1669, 7819,       1669,
-+    7820,       1673, 7821,       1673, 7822,       1677,
-+    7823,       1677, 7824,       1681,  // NOLINT
-+    7825,       1681, 7826,       1685, 7827,       1685,
-+    7828,       1689, 7829,       1689, 7835,       1585,
-+    7840,       1693, 7841,       1693,  // NOLINT
-+    7842,       1697, 7843,       1697, 7844,       1701,
-+    7845,       1701, 7846,       1705, 7847,       1705,
-+    7848,       1709, 7849,       1709,  // NOLINT
-+    7850,       1713, 7851,       1713, 7852,       1717,
-+    7853,       1717, 7854,       1721, 7855,       1721,
-+    7856,       1725, 7857,       1725,  // NOLINT
-+    7858,       1729, 7859,       1729, 7860,       1733,
-+    7861,       1733, 7862,       1737, 7863,       1737,
-+    7864,       1741, 7865,       1741,  // NOLINT
-+    7866,       1745, 7867,       1745, 7868,       1749,
-+    7869,       1749, 7870,       1753, 7871,       1753,
-+    7872,       1757, 7873,       1757,  // NOLINT
-+    7874,       1761, 7875,       1761, 7876,       1765,
-+    7877,       1765, 7878,       1769, 7879,       1769,
-+    7880,       1773, 7881,       1773,  // NOLINT
-+    7882,       1777, 7883,       1777, 7884,       1781,
-+    7885,       1781, 7886,       1785, 7887,       1785,
-+    7888,       1789, 7889,       1789,  // NOLINT
-+    7890,       1793, 7891,       1793, 7892,       1797,
-+    7893,       1797, 7894,       1801, 7895,       1801,
-+    7896,       1805, 7897,       1805,  // NOLINT
-+    7898,       1809, 7899,       1809, 7900,       1813,
-+    7901,       1813, 7902,       1817, 7903,       1817,
-+    7904,       1821, 7905,       1821,  // NOLINT
-+    7906,       1825, 7907,       1825, 7908,       1829,
-+    7909,       1829, 7910,       1833, 7911,       1833,
-+    7912,       1837, 7913,       1837,  // NOLINT
-+    7914,       1841, 7915,       1841, 7916,       1845,
-+    7917,       1845, 7918,       1849, 7919,       1849,
-+    7920,       1853, 7921,       1853,  // NOLINT
-+    7922,       1857, 7923,       1857, 7924,       1861,
-+    7925,       1861, 7926,       1865, 7927,       1865,
-+    7928,       1869, 7929,       1869,  // NOLINT
-+    7930,       1873, 7931,       1873, 7932,       1877,
-+    7933,       1877, 7934,       1881, 7935,       1881,
-+    1073749760, 1885, 7943,       1889,  // NOLINT
-+    1073749768, 1885, 7951,       1889, 1073749776, 1893,
-+    7957,       1897, 1073749784, 1893, 7965,       1897,
-+    1073749792, 1901, 7975,       1905,  // NOLINT
-+    1073749800, 1901, 7983,       1905, 1073749808, 1909,
-+    7991,       1913, 1073749816, 1909, 7999,       1913,
-+    1073749824, 1917, 8005,       1921,  // NOLINT
-+    1073749832, 1917, 8013,       1921, 8017,       1925,
-+    8019,       1929, 8021,       1933, 8023,       1937,
-+    8025,       1925, 8027,       1929,  // NOLINT
-+    8029,       1933, 8031,       1937, 1073749856, 1941,
-+    8039,       1945, 1073749864, 1941, 8047,       1945,
-+    1073749872, 1949, 8049,       1953,  // NOLINT
-+    1073749874, 1957, 8053,       1961, 1073749878, 1965,
-+    8055,       1969, 1073749880, 1973, 8057,       1977,
-+    1073749882, 1981, 8059,       1985,  // NOLINT
-+    1073749884, 1989, 8061,       1993, 1073749936, 1997,
-+    8113,       2001, 1073749944, 1997, 8121,       2001,
-+    1073749946, 1949, 8123,       1953,  // NOLINT
-+    8126,       749,  1073749960, 1957, 8139,       1961,
-+    1073749968, 2005, 8145,       2009, 1073749976, 2005,
-+    8153,       2009, 1073749978, 1965,  // NOLINT
-+    8155,       1969, 1073749984, 2013, 8161,       2017,
-+    8165,       2021, 1073749992, 2013, 8169,       2017,
-+    1073749994, 1981, 8171,       1985,  // NOLINT
-+    8172,       2021, 1073750008, 1973, 8185,       1977,
-+    1073750010, 1989, 8187,       1993};  // NOLINT
-+static const MultiCharacterSpecialCase<2>
-+    kEcma262UnCanonicalizeMultiStrings1[83] = {  // NOLINT
-+        {{8498, 8526}},   {{8544, 8560}},   {{8559, 8575}},
-+        {{8579, 8580}},  // NOLINT
-+        {{9398, 9424}},   {{9423, 9449}},   {{11264, 11312}},
-+        {{11310, 11358}},  // NOLINT
-+        {{11360, 11361}}, {{619, 11362}},   {{7549, 11363}},
-+        {{637, 11364}},  // NOLINT
-+        {{570, 11365}},   {{574, 11366}},   {{11367, 11368}},
-+        {{11369, 11370}},  // NOLINT
-+        {{11371, 11372}}, {{593, 11373}},   {{625, 11374}},
-+        {{592, 11375}},  // NOLINT
-+        {{594, 11376}},   {{11378, 11379}}, {{11381, 11382}},
-+        {{575, 11390}},  // NOLINT
-+        {{576, 11391}},   {{11392, 11393}}, {{11394, 11395}},
-+        {{11396, 11397}},  // NOLINT
-+        {{11398, 11399}}, {{11400, 11401}}, {{11402, 11403}},
-+        {{11404, 11405}},  // NOLINT
-+        {{11406, 11407}}, {{11408, 11409}}, {{11410, 11411}},
-+        {{11412, 11413}},  // NOLINT
-+        {{11414, 11415}}, {{11416, 11417}}, {{11418, 11419}},
-+        {{11420, 11421}},  // NOLINT
-+        {{11422, 11423}}, {{11424, 11425}}, {{11426, 11427}},
-+        {{11428, 11429}},  // NOLINT
-+        {{11430, 11431}}, {{11432, 11433}}, {{11434, 11435}},
-+        {{11436, 11437}},  // NOLINT
-+        {{11438, 11439}}, {{11440, 11441}}, {{11442, 11443}},
-+        {{11444, 11445}},  // NOLINT
-+        {{11446, 11447}}, {{11448, 11449}}, {{11450, 11451}},
-+        {{11452, 11453}},  // NOLINT
-+        {{11454, 11455}}, {{11456, 11457}}, {{11458, 11459}},
-+        {{11460, 11461}},  // NOLINT
-+        {{11462, 11463}}, {{11464, 11465}}, {{11466, 11467}},
-+        {{11468, 11469}},  // NOLINT
-+        {{11470, 11471}}, {{11472, 11473}}, {{11474, 11475}},
-+        {{11476, 11477}},  // NOLINT
-+        {{11478, 11479}}, {{11480, 11481}}, {{11482, 11483}},
-+        {{11484, 11485}},  // NOLINT
-+        {{11486, 11487}}, {{11488, 11489}}, {{11490, 11491}},
-+        {{11499, 11500}},  // NOLINT
-+        {{11501, 11502}}, {{11506, 11507}}, {{4256, 11520}},
-+        {{4293, 11557}},                                       // NOLINT
-+        {{4295, 11559}},  {{4301, 11565}},  {{kSentinel}}};    // NOLINT
-+static const uint16_t kEcma262UnCanonicalizeTable1Size = 149;  // NOLINT
-+static const int32_t kEcma262UnCanonicalizeTable1[298] = {
-+    306,        1,   334,        1,   1073742176, 5,   367,  9,
-+    1073742192, 5,   383,        9,   387,        13,  388,  13,  // NOLINT
-+    1073743030, 17,  1231,       21,  1073743056, 17,  1257, 21,
-+    1073744896, 25,  3118,       29,  1073744944, 25,  3166, 29,  // NOLINT
-+    3168,       33,  3169,       33,  3170,       37,  3171, 41,
-+    3172,       45,  3173,       49,  3174,       53,  3175, 57,  // NOLINT
-+    3176,       57,  3177,       61,  3178,       61,  3179, 65,
-+    3180,       65,  3181,       69,  3182,       73,  3183, 77,  // NOLINT
-+    3184,       81,  3186,       85,  3187,       85,  3189, 89,
-+    3190,       89,  1073745022, 93,  3199,       97,  3200, 101,  // NOLINT
-+    3201,       101, 3202,       105, 3203,       105, 3204, 109,
-+    3205,       109, 3206,       113, 3207,       113, 3208, 117,  // NOLINT
-+    3209,       117, 3210,       121, 3211,       121, 3212, 125,
-+    3213,       125, 3214,       129, 3215,       129, 3216, 133,  // NOLINT
-+    3217,       133, 3218,       137, 3219,       137, 3220, 141,
-+    3221,       141, 3222,       145, 3223,       145, 3224, 149,  // NOLINT
-+    3225,       149, 3226,       153, 3227,       153, 3228, 157,
-+    3229,       157, 3230,       161, 3231,       161, 3232, 165,  // NOLINT
-+    3233,       165, 3234,       169, 3235,       169, 3236, 173,
-+    3237,       173, 3238,       177, 3239,       177, 3240, 181,  // NOLINT
-+    3241,       181, 3242,       185, 3243,       185, 3244, 189,
-+    3245,       189, 3246,       193, 3247,       193, 3248, 197,  // NOLINT
-+    3249,       197, 3250,       201, 3251,       201, 3252, 205,
-+    3253,       205, 3254,       209, 3255,       209, 3256, 213,  // NOLINT
-+    3257,       213, 3258,       217, 3259,       217, 3260, 221,
-+    3261,       221, 3262,       225, 3263,       225, 3264, 229,  // NOLINT
-+    3265,       229, 3266,       233, 3267,       233, 3268, 237,
-+    3269,       237, 3270,       241, 3271,       241, 3272, 245,  // NOLINT
-+    3273,       245, 3274,       249, 3275,       249, 3276, 253,
-+    3277,       253, 3278,       257, 3279,       257, 3280, 261,  // NOLINT
-+    3281,       261, 3282,       265, 3283,       265, 3284, 269,
-+    3285,       269, 3286,       273, 3287,       273, 3288, 277,  // NOLINT
-+    3289,       277, 3290,       281, 3291,       281, 3292, 285,
-+    3293,       285, 3294,       289, 3295,       289, 3296, 293,  // NOLINT
-+    3297,       293, 3298,       297, 3299,       297, 3307, 301,
-+    3308,       301, 3309,       305, 3310,       305, 3314, 309,  // NOLINT
-+    3315,       309, 1073745152, 313, 3365,       317, 3367, 321,
-+    3373,       325};  // NOLINT
-+static const MultiCharacterSpecialCase<2>
-+    kEcma262UnCanonicalizeMultiStrings5[104] = {  // NOLINT
-+        {{42560, 42561}}, {{42562, 42563}},
-+        {{42564, 42565}}, {{42566, 42567}},  // NOLINT
-+        {{42568, 42569}}, {{42570, 42571}},
-+        {{42572, 42573}}, {{42574, 42575}},  // NOLINT
-+        {{42576, 42577}}, {{42578, 42579}},
-+        {{42580, 42581}}, {{42582, 42583}},  // NOLINT
-+        {{42584, 42585}}, {{42586, 42587}},
-+        {{42588, 42589}}, {{42590, 42591}},  // NOLINT
-+        {{42592, 42593}}, {{42594, 42595}},
-+        {{42596, 42597}}, {{42598, 42599}},  // NOLINT
-+        {{42600, 42601}}, {{42602, 42603}},
-+        {{42604, 42605}}, {{42624, 42625}},  // NOLINT
-+        {{42626, 42627}}, {{42628, 42629}},
-+        {{42630, 42631}}, {{42632, 42633}},  // NOLINT
-+        {{42634, 42635}}, {{42636, 42637}},
-+        {{42638, 42639}}, {{42640, 42641}},  // NOLINT
-+        {{42642, 42643}}, {{42644, 42645}},
-+        {{42646, 42647}}, {{42648, 42649}},  // NOLINT
-+        {{42650, 42651}}, {{42786, 42787}},
-+        {{42788, 42789}}, {{42790, 42791}},  // NOLINT
-+        {{42792, 42793}}, {{42794, 42795}},
-+        {{42796, 42797}}, {{42798, 42799}},  // NOLINT
-+        {{42802, 42803}}, {{42804, 42805}},
-+        {{42806, 42807}}, {{42808, 42809}},  // NOLINT
-+        {{42810, 42811}}, {{42812, 42813}},
-+        {{42814, 42815}}, {{42816, 42817}},  // NOLINT
-+        {{42818, 42819}}, {{42820, 42821}},
-+        {{42822, 42823}}, {{42824, 42825}},  // NOLINT
-+        {{42826, 42827}}, {{42828, 42829}},
-+        {{42830, 42831}}, {{42832, 42833}},  // NOLINT
-+        {{42834, 42835}}, {{42836, 42837}},
-+        {{42838, 42839}}, {{42840, 42841}},  // NOLINT
-+        {{42842, 42843}}, {{42844, 42845}},
-+        {{42846, 42847}}, {{42848, 42849}},  // NOLINT
-+        {{42850, 42851}}, {{42852, 42853}},
-+        {{42854, 42855}}, {{42856, 42857}},  // NOLINT
-+        {{42858, 42859}}, {{42860, 42861}},
-+        {{42862, 42863}}, {{42873, 42874}},  // NOLINT
-+        {{42875, 42876}}, {{7545, 42877}},
-+        {{42878, 42879}}, {{42880, 42881}},  // NOLINT
-+        {{42882, 42883}}, {{42884, 42885}},
-+        {{42886, 42887}}, {{42891, 42892}},  // NOLINT
-+        {{613, 42893}},   {{42896, 42897}},
-+        {{42898, 42899}}, {{42902, 42903}},  // NOLINT
-+        {{42904, 42905}}, {{42906, 42907}},
-+        {{42908, 42909}}, {{42910, 42911}},  // NOLINT
-+        {{42912, 42913}}, {{42914, 42915}},
-+        {{42916, 42917}}, {{42918, 42919}},  // NOLINT
-+        {{42920, 42921}}, {{614, 42922}},
-+        {{604, 42923}},   {{609, 42924}},  // NOLINT
-+        {{620, 42925}},   {{670, 42928}},
-+        {{647, 42929}},   {{kSentinel}}};                      // NOLINT
-+static const uint16_t kEcma262UnCanonicalizeTable5Size = 198;  // NOLINT
-+static const int32_t
-+    kEcma262UnCanonicalizeTable5[396] =
-+        {1600, 1,   1601, 1,   1602, 5,   1603, 5,
-+         1604, 9,   1605, 9,   1606, 13,  1607, 13,  // NOLINT
-+         1608, 17,  1609, 17,  1610, 21,  1611, 21,
-+         1612, 25,  1613, 25,  1614, 29,  1615, 29,  // NOLINT
-+         1616, 33,  1617, 33,  1618, 37,  1619, 37,
-+         1620, 41,  1621, 41,  1622, 45,  1623, 45,  // NOLINT
-+         1624, 49,  1625, 49,  1626, 53,  1627, 53,
-+         1628, 57,  1629, 57,  1630, 61,  1631, 61,  // NOLINT
-+         1632, 65,  1633, 65,  1634, 69,  1635, 69,
-+         1636, 73,  1637, 73,  1638, 77,  1639, 77,  // NOLINT
-+         1640, 81,  1641, 81,  1642, 85,  1643, 85,
-+         1644, 89,  1645, 89,  1664, 93,  1665, 93,  // NOLINT
-+         1666, 97,  1667, 97,  1668, 101, 1669, 101,
-+         1670, 105, 1671, 105, 1672, 109, 1673, 109,  // NOLINT
-+         1674, 113, 1675, 113, 1676, 117, 1677, 117,
-+         1678, 121, 1679, 121, 1680, 125, 1681, 125,  // NOLINT
-+         1682, 129, 1683, 129, 1684, 133, 1685, 133,
-+         1686, 137, 1687, 137, 1688, 141, 1689, 141,  // NOLINT
-+         1690, 145, 1691, 145, 1826, 149, 1827, 149,
-+         1828, 153, 1829, 153, 1830, 157, 1831, 157,  // NOLINT
-+         1832, 161, 1833, 161, 1834, 165, 1835, 165,
-+         1836, 169, 1837, 169, 1838, 173, 1839, 173,  // NOLINT
-+         1842, 177, 1843, 177, 1844, 181, 1845, 181,
-+         1846, 185, 1847, 185, 1848, 189, 1849, 189,  // NOLINT
-+         1850, 193, 1851, 193, 1852, 197, 1853, 197,
-+         1854, 201, 1855, 201, 1856, 205, 1857, 205,  // NOLINT
-+         1858, 209, 1859, 209, 1860, 213, 1861, 213,
-+         1862, 217, 1863, 217, 1864, 221, 1865, 221,  // NOLINT
-+         1866, 225, 1867, 225, 1868, 229, 1869, 229,
-+         1870, 233, 1871, 233, 1872, 237, 1873, 237,  // NOLINT
-+         1874, 241, 1875, 241, 1876, 245, 1877, 245,
-+         1878, 249, 1879, 249, 1880, 253, 1881, 253,  // NOLINT
-+         1882, 257, 1883, 257, 1884, 261, 1885, 261,
-+         1886, 265, 1887, 265, 1888, 269, 1889, 269,  // NOLINT
-+         1890, 273, 1891, 273, 1892, 277, 1893, 277,
-+         1894, 281, 1895, 281, 1896, 285, 1897, 285,  // NOLINT
-+         1898, 289, 1899, 289, 1900, 293, 1901, 293,
-+         1902, 297, 1903, 297, 1913, 301, 1914, 301,  // NOLINT
-+         1915, 305, 1916, 305, 1917, 309, 1918, 313,
-+         1919, 313, 1920, 317, 1921, 317, 1922, 321,  // NOLINT
-+         1923, 321, 1924, 325, 1925, 325, 1926, 329,
-+         1927, 329, 1931, 333, 1932, 333, 1933, 337,  // NOLINT
-+         1936, 341, 1937, 341, 1938, 345, 1939, 345,
-+         1942, 349, 1943, 349, 1944, 353, 1945, 353,  // NOLINT
-+         1946, 357, 1947, 357, 1948, 361, 1949, 361,
-+         1950, 365, 1951, 365, 1952, 369, 1953, 369,  // NOLINT
-+         1954, 373, 1955, 373, 1956, 377, 1957, 377,
-+         1958, 381, 1959, 381, 1960, 385, 1961, 385,  // NOLINT
-+         1962, 389, 1963, 393, 1964, 397, 1965, 401,
-+         1968, 405, 1969, 409};  // NOLINT
-+static const MultiCharacterSpecialCase<2>
-+    kEcma262UnCanonicalizeMultiStrings7[3] = {  // NOLINT
-+        {{65313, 65345}},
-+        {{65338, 65370}},
-+        {{kSentinel}}};                                      // NOLINT
-+static const uint16_t kEcma262UnCanonicalizeTable7Size = 4;  // NOLINT
-+static const int32_t kEcma262UnCanonicalizeTable7[8] = {
-+    1073749793, 1, 7994, 5, 1073749825, 1, 8026, 5};  // NOLINT
-+int Ecma262UnCanonicalize::Convert(uchar c, uchar n, uchar* result,
-+                                   bool* allow_caching_ptr) {
-+  int chunk_index = c >> 13;
-+  switch (chunk_index) {
-+    case 0:
-+      return LookupMapping<true>(
-+          kEcma262UnCanonicalizeTable0, kEcma262UnCanonicalizeTable0Size,
-+          kEcma262UnCanonicalizeMultiStrings0, c, n, result, allow_caching_ptr);
-+    case 1:
-+      return LookupMapping<true>(
-+          kEcma262UnCanonicalizeTable1, kEcma262UnCanonicalizeTable1Size,
-+          kEcma262UnCanonicalizeMultiStrings1, c, n, result, allow_caching_ptr);
-+    case 5:
-+      return LookupMapping<true>(
-+          kEcma262UnCanonicalizeTable5, kEcma262UnCanonicalizeTable5Size,
-+          kEcma262UnCanonicalizeMultiStrings5, c, n, result, allow_caching_ptr);
-+    case 7:
-+      return LookupMapping<true>(
-+          kEcma262UnCanonicalizeTable7, kEcma262UnCanonicalizeTable7Size,
-+          kEcma262UnCanonicalizeMultiStrings7, c, n, result, allow_caching_ptr);
-+    default:
-+      return 0;
-+  }
-+}
-+
-+static const MultiCharacterSpecialCase<1>
-+    kCanonicalizationRangeMultiStrings0[1] = {                // NOLINT
-+        {{kSentinel}}};                                       // NOLINT
-+static const uint16_t kCanonicalizationRangeTable0Size = 70;  // NOLINT
-+static const int32_t kCanonicalizationRangeTable0[140] = {
-+    1073741889, 100, 90,   0, 1073741921, 100, 122,  0,
-+    1073742016, 88,  214,  0, 1073742040, 24,  222,  0,  // NOLINT
-+    1073742048, 88,  246,  0, 1073742072, 24,  254,  0,
-+    1073742715, 8,   893,  0, 1073742728, 8,   906,  0,  // NOLINT
-+    1073742749, 8,   927,  0, 1073742759, 16,  939,  0,
-+    1073742765, 8,   943,  0, 1073742781, 8,   959,  0,  // NOLINT
-+    1073742791, 16,  971,  0, 1073742845, 8,   1023, 0,
-+    1073742848, 60,  1039, 0, 1073742864, 124, 1071, 0,  // NOLINT
-+    1073742896, 124, 1103, 0, 1073742928, 60,  1119, 0,
-+    1073743153, 148, 1366, 0, 1073743201, 148, 1414, 0,  // NOLINT
-+    1073746080, 148, 4293, 0, 1073749760, 28,  7943, 0,
-+    1073749768, 28,  7951, 0, 1073749776, 20,  7957, 0,  // NOLINT
-+    1073749784, 20,  7965, 0, 1073749792, 28,  7975, 0,
-+    1073749800, 28,  7983, 0, 1073749808, 28,  7991, 0,  // NOLINT
-+    1073749816, 28,  7999, 0, 1073749824, 20,  8005, 0,
-+    1073749832, 20,  8013, 0, 1073749856, 28,  8039, 0,  // NOLINT
-+    1073749864, 28,  8047, 0, 1073749874, 12,  8053, 0,
-+    1073749960, 12,  8139, 0};  // NOLINT
-+static const MultiCharacterSpecialCase<1>
-+    kCanonicalizationRangeMultiStrings1[1] = {                // NOLINT
-+        {{kSentinel}}};                                       // NOLINT
-+static const uint16_t kCanonicalizationRangeTable1Size = 14;  // NOLINT
-+static const int32_t kCanonicalizationRangeTable1[28] = {
-+    1073742176, 60,  367,  0, 1073742192, 60,  383,  0,
-+    1073743030, 100, 1231, 0, 1073743056, 100, 1257, 0,  // NOLINT
-+    1073744896, 184, 3118, 0, 1073744944, 184, 3166, 0,
-+    1073745152, 148, 3365, 0};  // NOLINT
-+static const MultiCharacterSpecialCase<1>
-+    kCanonicalizationRangeMultiStrings7[1] = {               // NOLINT
-+        {{kSentinel}}};                                      // NOLINT
-+static const uint16_t kCanonicalizationRangeTable7Size = 4;  // NOLINT
-+static const int32_t kCanonicalizationRangeTable7[8] = {
-+    1073749793, 100, 7994, 0, 1073749825, 100, 8026, 0};  // NOLINT
-+int CanonicalizationRange::Convert(uchar c, uchar n, uchar* result,
-+                                   bool* allow_caching_ptr) {
-+  int chunk_index = c >> 13;
-+  switch (chunk_index) {
-+    case 0:
-+      return LookupMapping<false>(
-+          kCanonicalizationRangeTable0, kCanonicalizationRangeTable0Size,
-+          kCanonicalizationRangeMultiStrings0, c, n, result, allow_caching_ptr);
-+    case 1:
-+      return LookupMapping<false>(
-+          kCanonicalizationRangeTable1, kCanonicalizationRangeTable1Size,
-+          kCanonicalizationRangeMultiStrings1, c, n, result, allow_caching_ptr);
-+    case 7:
-+      return LookupMapping<false>(
-+          kCanonicalizationRangeTable7, kCanonicalizationRangeTable7Size,
-+          kCanonicalizationRangeMultiStrings7, c, n, result, allow_caching_ptr);
-+    default:
-+      return 0;
-+  }
-+}
-+
-+#endif  // !V8_INTL_SUPPORT
-+
-+}  // namespace unibrow
-+}  // namespace v8
-diff --git a/js/src/irregexp/util/VectorShim.h b/js/src/irregexp/util/VectorShim.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/util/VectorShim.h
-@@ -0,0 +1,215 @@
-+// Copyright 2014 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#ifndef V8_UTIL_VECTOR_H_
-+#define V8_UTIL_VECTOR_H_
-+
-+#include <algorithm>
-+#include <cstring>
-+#include <iterator>
-+#include <memory>
-+
-+#include "jsalloc.h"
-+#include "js/Utility.h"
-+#include "js/Vector.h"
-+
-+namespace v8 {
-+namespace internal {
-+
-+//////////////////////////////////////////////////
-+
-+// Adapted from:
-+// https://github.com/v8/v8/blob/5f69bbc233c2d1baf149faf869a7901603929914/src/utils/allocation.h#L36-L58
-+
-+template <typename T>
-+T* NewArray(size_t size) {
-+  static_assert(std::is_pod<T>::value, "");
-+  js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+  T* result = static_cast<T*>(js_malloc(size * sizeof(T)));
-+  if (!result) {
-+    oomUnsafe.crash("Irregexp NewArray");
-+  }
-+  return result;
-+}
-+
-+template <typename T>
-+void DeleteArray(T* array) {
-+  js_free(array);
-+}
-+
-+//////////////////////////////////////////////////
-+
-+// A non-resizable vector containing a pointer and a length.
-+// The Vector may or may not own the pointer, depending on context.
-+// Origin:
-+// https://github.com/v8/v8/blob/5f69bbc233c2d1baf149faf869a7901603929914/src/utils/vector.h#L20-L134
-+
-+template <typename T>
-+class Vector {
-+ public:
-+  Vector() : start_(nullptr), length_(0) {}
-+
-+  Vector(T* data, size_t length) : start_(data), length_(length) {
-+    MOZ_ASSERT_IF(length != 0, data != nullptr);
-+  }
-+
-+  static Vector<T> New(size_t length) {
-+    return Vector<T>(NewArray<T>(length), length);
-+  }
-+
-+  // Returns a vector using the same backing storage as this one,
-+  // spanning from and including 'from', to but not including 'to'.
-+  Vector<T> SubVector(size_t from, size_t to) const {
-+    MOZ_ASSERT(from <= to);
-+    MOZ_ASSERT(to <= length_);
-+    return Vector<T>(begin() + from, to - from);
-+  }
-+
-+  // Returns the length of the vector. Only use this if you really need an
-+  // integer return value. Use {size()} otherwise.
-+  int length() const {
-+    MOZ_ASSERT(length_ <= static_cast<size_t>(std::numeric_limits<int>::max()));
-+    return static_cast<int>(length_);
-+  }
-+
-+  // Returns the length of the vector as a size_t.
-+  constexpr size_t size() const { return length_; }
-+
-+  // Returns whether or not the vector is empty.
-+  constexpr bool empty() const { return length_ == 0; }
-+
-+  // Access individual vector elements - checks bounds in debug mode.
-+  T& operator[](size_t index) const {
-+    MOZ_ASSERT(index < length_);
-+    return start_[index];
-+  }
-+
-+  const T& at(size_t index) const { return operator[](index); }
-+
-+  T& first() { return start_[0]; }
-+
-+  T& last() {
-+    MOZ_ASSERT(length_ > 0);
-+    return start_[length_ - 1];
-+  }
-+
-+  // Returns a pointer to the start of the data in the vector.
-+  constexpr T* begin() const { return start_; }
-+
-+  // Returns a pointer past the end of the data in the vector.
-+  constexpr T* end() const { return start_ + length_; }
-+
-+  // Returns a clone of this vector with a new backing store.
-+  Vector<T> Clone() const {
-+    T* result = NewArray<T>(length_);
-+    for (size_t i = 0; i < length_; i++) result[i] = start_[i];
-+    return Vector<T>(result, length_);
-+  }
-+
-+  void Truncate(size_t length) {
-+    MOZ_ASSERT(length <= length_);
-+    length_ = length;
-+  }
-+
-+  // Releases the array underlying this vector. Once disposed the
-+  // vector is empty.
-+  void Dispose() {
-+    DeleteArray(start_);
-+    start_ = nullptr;
-+    length_ = 0;
-+  }
-+
-+  Vector<T> operator+(size_t offset) {
-+    MOZ_ASSERT(offset <= length_);
-+    return Vector<T>(start_ + offset, length_ - offset);
-+  }
-+
-+  Vector<T> operator+=(size_t offset) {
-+    MOZ_ASSERT(offset <= length_);
-+    start_ += offset;
-+    length_ -= offset;
-+    return *this;
-+  }
-+
-+  // Implicit conversion from Vector<T> to Vector<const T>.
-+  inline operator Vector<const T>() const {
-+    return Vector<const T>::cast(*this);
-+  }
-+
-+  template <typename S>
-+  static constexpr Vector<T> cast(Vector<S> input) {
-+    return Vector<T>(reinterpret_cast<T*>(input.begin()),
-+                     input.length() * sizeof(S) / sizeof(T));
-+  }
-+
-+  bool operator==(const Vector<const T> other) const {
-+    if (length_ != other.length_) return false;
-+    if (start_ == other.start_) return true;
-+    for (size_t i = 0; i < length_; ++i) {
-+      if (start_[i] != other.start_[i]) {
-+        return false;
-+      }
-+    }
-+    return true;
-+  }
-+
-+ private:
-+  T* start_;
-+  size_t length_;
-+};
-+
-+// The resulting vector does not contain a null-termination byte. If you want
-+// the null byte, use ArrayVector("foo").
-+inline Vector<const char> CStrVector(const char* data) {
-+  return Vector<const char>(data, strlen(data));
-+}
-+
-+}  // namespace internal
-+
-+namespace base {
-+
-+// SmallVector uses inline storage first, and reallocates when full.
-+// It is basically equivalent to js::Vector, and is implemented
-+// as a thin wrapper.
-+// V8's implementation:
-+// https://github.com/v8/v8/blob/master/src/base/small-vector.h
-+template <typename T, size_t kSize>
-+class SmallVector {
-+ public:
-+  SmallVector() = default;
-+  SmallVector(size_t size) { resize_no_init(size); }
-+
-+  inline bool empty() const { return inner_.empty(); }
-+  inline const T& back() const { return inner_.back(); }
-+  inline void pop_back() { inner_.popBack(); };
-+  template <typename... Args>
-+  inline void emplace_back(Args&&... args) {
-+    js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+    if (!inner_.emplaceBack(args...)) {
-+      oomUnsafe.crash("Irregexp SmallVector emplace_back");
-+    }
-+  };
-+  inline size_t size() const { return inner_.length(); }
-+  inline const T& at(size_t index) const { return inner_[index]; }
-+  T* data() { return inner_.begin(); }
-+
-+  T& operator[](size_t index) { return inner_[index]; }
-+  const T& operator[](size_t index) const { return inner_[index]; }
-+
-+  void resize_no_init(size_t new_size) {
-+    js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+    if (!inner_.resizeUninitialized(new_size)) {
-+      oomUnsafe.crash("Irregexp SmallVector resize");
-+    }
-+  }
-+
-+ private:
-+  js::Vector<T, kSize, js::SystemAllocPolicy> inner_;
-+};
-+
-+}  // namespace base
-+
-+}  // namespace v8
-+
-+#endif  // V8_UTIL_VECTOR_H_
-diff --git a/js/src/irregexp/util/ZoneShim.h b/js/src/irregexp/util/ZoneShim.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/irregexp/util/ZoneShim.h
-@@ -0,0 +1,377 @@
-+// Copyright 2019 the V8 project authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#ifndef V8_UTIL_ZONE_H_
-+#define V8_UTIL_ZONE_H_
-+
-+#include <list>
-+#include <map>
-+#include <set>
-+#include <unordered_map>
-+#include <vector>
-+
-+#include "ds/LifoAlloc.h"
-+#include "ds/Sort.h"
-+#include "irregexp/util/VectorShim.h"
-+
-+namespace v8 {
-+namespace internal {
-+
-+// V8::Zone ~= LifoAlloc
-+class Zone {
-+ public:
-+  Zone(js::LifoAlloc& alloc) : lifoAlloc_(alloc) {}
-+
-+  template <typename T, typename... Args>
-+  T* New(Args&&... args) {
-+    js::LifoAlloc::AutoFallibleScope fallible(&lifoAlloc_);
-+    js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+    void* memory = lifoAlloc_.alloc(sizeof(T));
-+    if (!memory) {
-+      oomUnsafe.crash("Irregexp Zone::New");
-+    }
-+    return new (memory) T(std::forward<Args>(args)...);
-+  }
-+
-+  // Allocates uninitialized memory for 'length' number of T instances.
-+  template <typename T>
-+  T* NewArray(size_t length) {
-+    js::LifoAlloc::AutoFallibleScope fallible(&lifoAlloc_);
-+    js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+    void* memory = lifoAlloc_.alloc(length * sizeof(T));
-+    if (!memory) {
-+      oomUnsafe.crash("Irregexp Zone::New");
-+    }
-+    return static_cast<T*>(memory);
-+  }
-+
-+  void DeleteAll() { lifoAlloc_.freeAll(); }
-+
-+  // Returns true if the total memory allocated exceeds a threshold.
-+  static const size_t kExcessLimit = 256 * 1024 * 1024;
-+  bool excess_allocation() const {
-+    return lifoAlloc_.computedSizeOfExcludingThis() > kExcessLimit;
-+  }
-+
-+ private:
-+  js::LifoAlloc& lifoAlloc_;
-+};
-+
-+// Superclass for classes allocated in a Zone.
-+// Based on: https://github.com/v8/v8/blob/master/src/zone/zone.h
-+class ZoneObject {
-+ public:
-+  // new (zone) SomeObject(...) was the old pattern.
-+  // Delete the constructor to avoid using it accidentally.
-+  void* operator new(size_t size, Zone* zone) = delete;
-+
-+  // Allow non-allocating placement new
-+  void* operator new(size_t size, void* ptr) { return ptr; }
-+
-+  // Ideally, the delete operator should be private instead of
-+  // public, but unfortunately the compiler sometimes synthesizes
-+  // (unused) destructors for classes derived from ZoneObject, which
-+  // require the operator to be visible. MSVC requires the delete
-+  // operator to be public.
-+
-+  // ZoneObjects should never be deleted individually; use
-+  // Zone::DeleteAll() to delete all zone objects in one go.
-+  void operator delete(void*, size_t) { MOZ_CRASH("unreachable"); }
-+  void operator delete(void* pointer, Zone* zone) { MOZ_CRASH("unreachable"); }
-+};
-+
-+// ZoneLists are growable lists with constant-time access to the
-+// elements. The list itself and all its elements are allocated in the
-+// Zone. ZoneLists cannot be deleted individually; you can delete all
-+// objects in the Zone by calling Zone::DeleteAll().
-+// Used throughout irregexp.
-+// Based on: https://github.com/v8/v8/blob/master/src/zone/zone-list.h
-+template <typename T>
-+class ZoneList final : public ZoneObject {
-+ public:
-+  // Construct a new ZoneList with the given capacity; the length is
-+  // always zero. The capacity must be non-negative.
-+  ZoneList(int capacity, Zone* zone) : capacity_(capacity) {
-+    data_ = (capacity_ > 0) ? zone->NewArray<T>(capacity_) : nullptr;
-+  }
-+  // Construct a new ZoneList by copying the elements of the given ZoneList.
-+  ZoneList(const ZoneList<T>& other, Zone* zone)
-+      : ZoneList(other.length(), zone) {
-+    AddAll(other, zone);
-+  }
-+
-+  // Returns a reference to the element at index i. This reference is not safe
-+  // to use after operations that can change the list's backing store
-+  // (e.g. Add).
-+  inline T& operator[](int i) const {
-+    MOZ_ASSERT(i >= 0);
-+    MOZ_ASSERT(static_cast<unsigned>(i) < static_cast<unsigned>(length_));
-+    return data_[i];
-+  }
-+  inline T& at(int i) const { return operator[](i); }
-+  inline T& last() const { return at(length_ - 1); }
-+  inline T& first() const { return at(0); }
-+
-+  using iterator = T*;
-+  inline iterator begin() const { return &data_[0]; }
-+  inline iterator end() const { return &data_[length_]; }
-+
-+  inline bool is_empty() const { return length_ == 0; }
-+  inline int length() const { return length_; }
-+  inline int capacity() const { return capacity_; }
-+
-+  Vector<T> ToVector() const { return Vector<T>(data_, length_); }
-+  Vector<T> ToVector(int start, int length) const {
-+    return Vector<T>(data_ + start, std::min(length_ - start, length));
-+  }
-+
-+  Vector<const T> ToConstVector() const {
-+    return Vector<const T>(data_, length_);
-+  }
-+
-+  // Adds a copy of the given 'element' to the end of the list,
-+  // expanding the list if necessary.
-+  void Add(const T& element, Zone* zone) {
-+    if (length_ < capacity_) {
-+      data_[length_++] = element;
-+    } else {
-+      ZoneList<T>::ResizeAdd(element, zone);
-+    }
-+  }
-+  // Add all the elements from the argument list to this list.
-+  void AddAll(const ZoneList<T>& other, Zone* zone) {
-+    AddAll(other.ToVector(), zone);
-+  }
-+  // Add all the elements from the vector to this list.
-+  void AddAll(const Vector<T>& other, Zone* zone) {
-+    int result_length = length_ + other.length();
-+    if (capacity_ < result_length) {
-+      Resize(result_length, zone);
-+    }
-+    if (std::is_fundamental<T>()) {
-+      memcpy(data_ + length_, other.begin(), sizeof(*data_) * other.length());
-+    } else {
-+      for (int i = 0; i < other.length(); i++) {
-+        data_[length_ + i] = other.at(i);
-+      }
-+    }
-+    length_ = result_length;
-+  }
-+
-+  // Overwrites the element at the specific index.
-+  void Set(int index, const T& element) {
-+    MOZ_ASSERT(index >= 0 && index <= length_);
-+    data_[index] = element;
-+  }
-+
-+  // Removes the i'th element without deleting it even if T is a
-+  // pointer type; moves all elements above i "down". Returns the
-+  // removed element.  This function's complexity is linear in the
-+  // size of the list.
-+  T Remove(int i) {
-+    T element = at(i);
-+    length_--;
-+    while (i < length_) {
-+      data_[i] = data_[i + 1];
-+      i++;
-+    }
-+    return element;
-+  }
-+
-+  // Removes the last element without deleting it even if T is a
-+  // pointer type. Returns the removed element.
-+  inline T RemoveLast() { return Remove(length_ - 1); }
-+
-+  // Clears the list by freeing the storage memory. If you want to keep the
-+  // memory, use Rewind(0) instead. Be aware, that even if T is a
-+  // pointer type, clearing the list doesn't delete the entries.
-+  inline void Clear() {
-+    data_ = nullptr;
-+    capacity_ = 0;
-+    length_ = 0;
-+  }
-+
-+  // Drops all but the first 'pos' elements from the list.
-+  inline void Rewind(int pos) {
-+    MOZ_ASSERT(0 <= pos && pos <= length_);
-+    length_ = pos;
-+  }
-+
-+  inline bool Contains(const T& elm) const {
-+    for (int i = 0; i < length_; i++) {
-+      if (data_[i] == elm) return true;
-+    }
-+    return false;
-+  }
-+
-+  template <typename CompareFunction>
-+  void StableSort(CompareFunction cmp, size_t start, size_t length) {
-+    js::AutoEnterOOMUnsafeRegion oomUnsafe;
-+    T* scratch = static_cast<T*>(js_malloc(length * sizeof(T)));
-+    if (!scratch) {
-+      oomUnsafe.crash("Irregexp stable sort scratch space");
-+    }
-+    auto comparator = [cmp](const T& a, const T& b, bool* lessOrEqual) {
-+      *lessOrEqual = cmp(&a, &b) <= 0;
-+      return true;
-+    };
-+    MOZ_ALWAYS_TRUE(
-+        js::MergeSort(begin() + start, length, scratch, comparator));
-+    js_free(scratch);
-+  }
-+
-+  void operator delete(void* pointer) { MOZ_CRASH("unreachable"); }
-+  void operator delete(void* pointer, Zone* zone) { MOZ_CRASH("unreachable"); }
-+
-+ private:
-+  T* data_ = nullptr;
-+  int capacity_ = 0;
-+  int length_ = 0;
-+
-+  // Increase the capacity of a full list, and add an element.
-+  // List must be full already.
-+  void ResizeAdd(const T& element, Zone* zone) {
-+    MOZ_ASSERT(length_ >= capacity_);
-+    // Grow the list capacity by 100%, but make sure to let it grow
-+    // even when the capacity is zero (possible initial case).
-+    int new_capacity = 1 + 2 * capacity_;
-+    // Since the element reference could be an element of the list, copy
-+    // it out of the old backing storage before resizing.
-+    T temp = element;
-+    Resize(new_capacity, zone);
-+    data_[length_++] = temp;
-+  }
-+
-+  // Resize the list.
-+  void Resize(int new_capacity, Zone* zone) {
-+    MOZ_ASSERT(length_ <= new_capacity);
-+    static_assert(std::is_trivially_copyable<T>::value,
-+                  "std::is_trivially_copyable<T>::value");
-+    T* new_data = zone->NewArray<T>(new_capacity);
-+    if (length_ > 0) {
-+      memcpy(new_data, data_, length_ * sizeof(T));
-+    }
-+    data_ = new_data;
-+    capacity_ = new_capacity;
-+  }
-+
-+  ZoneList& operator=(const ZoneList&) = delete;
-+  ZoneList() = delete;
-+  ZoneList(const ZoneList&) = delete;
-+};
-+
-+// Based on: https://github.com/v8/v8/blob/master/src/zone/zone-allocator.h
-+template <typename T>
-+class ZoneAllocator {
-+ public:
-+  using pointer = T*;
-+  using const_pointer = const T*;
-+  using reference = T&;
-+  using const_reference = const T&;
-+  using value_type = T;
-+  using size_type = size_t;
-+  using difference_type = ptrdiff_t;
-+  template <class O>
-+  struct rebind {
-+    using other = ZoneAllocator<O>;
-+  };
-+
-+  explicit ZoneAllocator(Zone* zone) : zone_(zone) {}
-+  template <typename U>
-+  ZoneAllocator(const ZoneAllocator<U>& other)
-+      : ZoneAllocator<T>(other.zone_) {}
-+  template <typename U>
-+  friend class ZoneAllocator;
-+
-+  T* allocate(size_t n) { return zone_->NewArray<T>(n); }
-+  void deallocate(T* p, size_t) {}  // noop for zones
-+
-+  bool operator==(ZoneAllocator const& other) const {
-+    return zone_ == other.zone_;
-+  }
-+  bool operator!=(ZoneAllocator const& other) const {
-+    return zone_ != other.zone_;
-+  }
-+
-+ private:
-+  Zone* zone_;
-+};
-+
-+// Zone wrappers for std containers:
-+// Origin:
-+// https://github.com/v8/v8/blob/5e514a969376dc63517d575b062758efd36cd757/src/zone/zone-containers.h#L25-L169
-+
-+// A wrapper subclass for std::vector to make it easy to construct one
-+// that uses a zone allocator.
-+// Used throughout irregexp
-+template <typename T>
-+class ZoneVector : public std::vector<T, ZoneAllocator<T>> {
-+ public:
-+  ZoneVector(Zone* zone)
-+      : std::vector<T, ZoneAllocator<T>>(ZoneAllocator<T>(zone)) {}
-+
-+  // Constructs a new vector and fills it with the contents of the range
-+  // [first, last).
-+  template <class Iter>
-+  ZoneVector(Iter first, Iter last, Zone* zone)
-+      : std::vector<T, ZoneAllocator<T>>(first, last, ZoneAllocator<T>(zone)) {}
-+};
-+
-+// A wrapper subclass for std::list to make it easy to construct one
-+// that uses a zone allocator.
-+// Used in regexp-bytecode-peephole.cc
-+template <typename T>
-+class ZoneLinkedList : public std::list<T, ZoneAllocator<T>> {
-+ public:
-+  // Constructs an empty list.
-+  explicit ZoneLinkedList(Zone* zone)
-+      : std::list<T, ZoneAllocator<T>>(ZoneAllocator<T>(zone)) {}
-+};
-+
-+// A wrapper subclass for std::set to make it easy to construct one that uses
-+// a zone allocator.
-+// Used in regexp-parser.cc
-+template <typename K, typename Compare = std::less<K>>
-+class ZoneSet : public std::set<K, Compare, ZoneAllocator<K>> {
-+ public:
-+  // Constructs an empty set.
-+  explicit ZoneSet(Zone* zone)
-+      : std::set<K, Compare, ZoneAllocator<K>>(Compare(),
-+                                               ZoneAllocator<K>(zone)) {}
-+};
-+
-+// A wrapper subclass for std::map to make it easy to construct one that uses
-+// a zone allocator.
-+// Used in regexp-bytecode-peephole.cc
-+template <typename K, typename V, typename Compare = std::less<K>>
-+class ZoneMap
-+    : public std::map<K, V, Compare, ZoneAllocator<std::pair<const K, V>>> {
-+ public:
-+  // Constructs an empty map.
-+  explicit ZoneMap(Zone* zone)
-+      : std::map<K, V, Compare, ZoneAllocator<std::pair<const K, V>>>(
-+            Compare(), ZoneAllocator<std::pair<const K, V>>(zone)) {}
-+};
-+
-+// A wrapper subclass for std::unordered_map to make it easy to construct one
-+// that uses a zone allocator.
-+// Used in regexp-bytecode-peephole.cc
-+template <typename K, typename V, typename Hash = std::hash<K>,
-+          typename KeyEqual = std::equal_to<K>>
-+class ZoneUnorderedMap
-+    : public std::unordered_map<K, V, Hash, KeyEqual,
-+                                ZoneAllocator<std::pair<const K, V>>> {
-+ public:
-+  // Constructs an empty map.
-+  explicit ZoneUnorderedMap(Zone* zone, size_t bucket_count = 100)
-+      : std::unordered_map<K, V, Hash, KeyEqual,
-+                           ZoneAllocator<std::pair<const K, V>>>(
-+            bucket_count, Hash(), KeyEqual(),
-+            ZoneAllocator<std::pair<const K, V>>(zone)) {}
-+};
-+
-+}  // namespace internal
-+}  // namespace v8
-+
-+#endif  // V8_UTIL_FLAG_H_
-diff --git a/js/src/jit-test/lib/regexp_parse.js b/js/src/jit-test/lib/regexp_parse.js
---- a/js/src/jit-test/lib/regexp_parse.js
-+++ b/js/src/jit-test/lib/regexp_parse.js
-@@ -1,205 +0,0 @@
--load(libdir + "asserts.js");
--
--// helper functions
--
--function Disjunction(alternatives) {
--  return{
--    type: "Disjunction",
--    alternatives: alternatives
--  };
--}
--
--function Alternative(nodes) {
--  return {
--    type: "Alternative",
--    nodes: nodes
--  };
--}
--
--function Empty() {
--  return {
--    type: "Empty"
--  };
--}
--
--function Text(elements) {
--  return {
--    type: "Text",
--    elements: elements
--  };
--}
--
--function Assertion(type) {
--  return {
--    type: "Assertion",
--    assertion_type: type
--  };
--}
--
--function Atom(data) {
--  return {
--    type: "Atom",
--    data: data
--  };
--}
--
--const kInfinity = 0x7FFFFFFF;
--function Quantifier(min, max, type, body) {
--  return {
--    type: "Quantifier",
--    min: min,
--    max: max,
--    quantifier_type: type,
--    body: body
--  };
--}
--
--function Lookahead(body) {
--  return {
--    type: "Lookahead",
--    is_positive: true,
--    body: body
--  };
--}
--
--function NegativeLookahead(body) {
--  return {
--    type: "Lookahead",
--    is_positive: false,
--    body: body
--  };
--}
--
--function BackReference(index) {
--  return {
--    type: "BackReference",
--    index: index
--  };
--}
--
--function CharacterClass(ranges) {
--  return {
--    type: "CharacterClass",
--    is_negated: false,
--    ranges: ranges.map(([from, to]) => ({ from ,to }))
--  };
--}
--
--function NegativeCharacterClass(ranges) {
--  return {
--    type: "CharacterClass",
--    is_negated: true,
--    ranges: ranges.map(([from, to]) => ({ from ,to }))
--  };
--}
--
--function Capture(index, body) {
--  return {
--    type: "Capture",
--    index: index,
--    body: body
--  };
--}
--
--function AllSurrogateAndCharacterClass(ranges) {
--  return Disjunction([
--    CharacterClass(ranges),
--    Alternative([
--      CharacterClass([["\uD800", "\uDBFF"]]),
--      NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--    ]),
--    Alternative([
--      Assertion("NOT_AFTER_LEAD_SURROGATE"),
--      CharacterClass([["\uDC00", "\uDFFF"]])
--    ]),
--    Text([
--      CharacterClass([["\uD800", "\uDBFF"]]),
--      CharacterClass([["\uDC00", "\uDFFF"]])
--    ])
--  ]);
--}
--
--// testing functions
--
--var all_flags = [
--  "",
--  "i",
--  "m",
--  "u",
--  "im",
--  "iu",
--  "mu",
--  "imu",
--];
--
--var no_unicode_flags = [
--  "",
--  "i",
--  "m",
--  "im",
--];
--
--var unicode_flags = [
--  "u",
--  "iu",
--  "mu",
--  "imu",
--];
--
--var no_multiline_flags = [
--  "",
--  "i",
--  "u",
--  "iu",
--];
--
--var multiline_flags = [
--  "m",
--  "im",
--  "mu",
--  "imu",
--];
--
--function test_flags(pattern, flags, match_only, expected) {
--  for (var flag of flags) {
--    assertDeepEq(parseRegExp(pattern, flag, match_only), expected);
--  }
--}
--
--function make_mix(tree) {
--  if (tree.type == "Atom") {
--    return Atom("X" + tree.data + "Y");
--  }
--  if (tree.type == "CharacterClass") {
--    return Text([
--      Atom("X"),
--      tree,
--      Atom("Y")
--    ]);
--  }
--  if (tree.type == "Alternative") {
--    return Alternative([
--      Atom("X"),
--      ...tree.nodes,
--      Atom("Y")
--    ]);
--  }
--  return Alternative([
--    Atom("X"),
--    tree,
--    Atom("Y")
--  ]);
--}
--
--function test_mix(pattern, flags, expected) {
--  test_flags(pattern, flags, false, expected);
--  test_flags("X" + pattern + "Y", flags, false, make_mix(expected));
--}
--
--function test(pattern, flags, expected) {
--  test_flags(pattern, flags, false, expected);
--}
--
--function test_match_only(pattern, flags, expected) {
--  test_flags(pattern, flags, true, expected);
--}
-diff --git a/js/src/jit-test/tests/regexp/bug1640479.js b/js/src/jit-test/tests/regexp/bug1640479.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit-test/tests/regexp/bug1640479.js
-@@ -0,0 +1,15 @@
-+// |jit-test| skip-if: !('oomTest' in this)
-+
-+var failures = 0;
-+var i = 0;
-+
-+function foo() {
-+    var e;
-+    var r = RegExp("(?<_" + (i++) + "a>)");
-+    try { e = r.exec("a"); } catch {}
-+    e = r.exec("a");
-+    if (e.groups === undefined) failures++;
-+}
-+
-+oomTest(foo);
-+assertEq(failures, 0);
-diff --git a/js/src/jit-test/tests/regexp/huge-02.js b/js/src/jit-test/tests/regexp/huge-02.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit-test/tests/regexp/huge-02.js
-@@ -0,0 +1,13 @@
-+var interestingCaptureNums = [(1 << 14),
-+                              (1 << 15) - 1,
-+                              (1 << 15),
-+                              (1 << 15) + 1,
-+                              (1 << 16)]
-+
-+for (let i of interestingCaptureNums) {
-+    print(i);
-+    try {
-+        var source = Array(i).join("(") + "a" + Array(i).join(")");
-+        RegExp(source).exec("a");
-+    } catch {}
-+}
-diff --git a/js/src/jit-test/tests/regexp_parse/Assertion.js b/js/src/jit-test/tests/regexp_parse/Assertion.js
---- a/js/src/jit-test/tests/regexp_parse/Assertion.js
-+++ b/js/src/jit-test/tests/regexp_parse/Assertion.js
-@@ -1,20 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("^", no_multiline_flags,
--         Assertion("START_OF_INPUT"));
--test_mix("^", multiline_flags,
--         Assertion("START_OF_LINE"));
--
--test_mix("$", no_multiline_flags,
--         Assertion("END_OF_INPUT"));
--test_mix("$", multiline_flags,
--         Assertion("END_OF_LINE"));
--
--test_mix("\\b", all_flags,
--         Assertion("BOUNDARY"));
--
--test_mix("\\B", all_flags,
--         Assertion("NON_BOUNDARY"));
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom.js b/js/src/jit-test/tests/regexp_parse/Atom.js
---- a/js/src/jit-test/tests/regexp_parse/Atom.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom.js
-@@ -1,54 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("a", all_flags,
--         Atom("a"));
--test_mix("abc\u3042\u3044\u3046", all_flags,
--         Atom("abc\u3042\u3044\u3046"));
--
--// raw brace
--
--test("{", no_unicode_flags,
--     Atom("{"));
--test("{a", no_unicode_flags,
--     Atom("{a"));
--test("a{b", no_unicode_flags,
--     Atom("a{b"));
--
--test("}", no_unicode_flags,
--     Atom("}"));
--test("}a", no_unicode_flags,
--     Atom("}a"));
--test("a}b", no_unicode_flags,
--     Atom("a}b"));
--
--// raw surrogate pair
--
--test("X\uD83D\uDC38Y", unicode_flags,
--     Text([
--         Atom("X"),
--         Atom("\uD83D\uDC38"),
--         Atom("Y")
--     ]));
--
--test("X\uD83DY", unicode_flags,
--     Alternative([
--         Atom("X"),
--         Alternative([
--             Atom("\uD83D"),
--             NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--         ]),
--         Atom("Y")
--     ]));
--
--test("X\uDC38Y", unicode_flags,
--     Alternative([
--         Atom("X"),
--         Alternative([
--             Assertion("NOT_AFTER_LEAD_SURROGATE"),
--             Atom("\uDC38"),
--         ]),
--         Atom("Y")
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom_CharacterClassEscape.js b/js/src/jit-test/tests/regexp_parse/Atom_CharacterClassEscape.js
---- a/js/src/jit-test/tests/regexp_parse/Atom_CharacterClassEscape.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom_CharacterClassEscape.js
-@@ -1,115 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("\\d", all_flags,
--         CharacterClass([["0", "9"]]));
--
--test_mix("\\D", no_unicode_flags,
--         CharacterClass([
--             ["\u0000", "/"],
--             [":", "\uFFFF"]
--         ]));
--test_mix("\\D", unicode_flags,
--         AllSurrogateAndCharacterClass([
--             ["\u0000", "/"],
--             [":", "\uD7FF"],
--             ["\uE000", "\uFFFF"]
--         ]));
--
--test_mix("\\s", all_flags,
--         CharacterClass([
--             ["\t", "\r"],
--             [" ", " "],
--             ["\u00A0", "\u00A0"],
--             ["\u1680", "\u1680"],
--             ["\u2000", "\u200A"],
--             ["\u2028", "\u2029"],
--             ["\u202F", "\u202F"],
--             ["\u205F", "\u205F"],
--             ["\u3000", "\u3000"],
--             ["\uFEFF", "\uFEFF"]
--         ]));
--test_mix("\\S", no_unicode_flags,
--         CharacterClass([
--             ["\u0000", "\u0008"],
--             ["\u000E", "\u001F"],
--             ["!", "\u009F"],
--             ["\u00A1", "\u167F"],
--             ["\u1681", "\u1FFF"],
--             ["\u200B", "\u2027"],
--             ["\u202A", "\u202E"],
--             ["\u2030", "\u205E"],
--             ["\u2060", "\u2FFF"],
--             ["\u3001", "\uFEFE"],
--             ["\uFF00", "\uFFFF"]
--         ]));
--test_mix("\\S", unicode_flags,
--         AllSurrogateAndCharacterClass([
--             ["\u0000", "\u0008"],
--             ["\u000E", "\u001F"],
--             ["!", "\u009F"],
--             ["\u00A1", "\u167F"],
--             ["\u1681", "\u1FFF"],
--             ["\u200B", "\u2027"],
--             ["\u202A", "\u202E"],
--             ["\u2030", "\u205E"],
--             ["\u2060", "\u2FFF"],
--             ["\u3001", "\uD7FF"],
--             ["\uE000", "\uFEFE"],
--             ["\uFF00", "\uFFFF"]
--         ]));
--
--test_mix("\\w", no_unicode_flags,
--         CharacterClass([
--             ["0", "9"],
--             ["A", "Z"],
--             ["_", "_"],
--             ["a", "z"]
--         ]));
--test_mix("\\w", ["u", "mu"],
--         CharacterClass([
--             ["0", "9"],
--             ["A", "Z"],
--             ["_", "_"],
--             ["a", "z"]
--         ]));
--test_mix("\\w", ["iu", "imu"],
--         CharacterClass([
--             ["0", "9"],
--             ["A", "Z"],
--             ["_", "_"],
--             ["a", "z"],
--             ["\u017F", "\u017F"],
--             ["\u212A", "\u212A"]
--         ]));
--
--test_mix("\\W", no_unicode_flags,
--         CharacterClass([
--             ["\u0000", "/"],
--             [":", "@"],
--             ["[", "^"],
--             ["`", "`"],
--             ["{", "\uFFFF"]
--         ]));
--test_mix("\\W", ["u", "mu"],
--         AllSurrogateAndCharacterClass([
--             ["\u0000", "/"],
--             [":", "@"],
--             ["[", "^"],
--             ["`", "`"],
--             ["{", "\uD7FF"],
--             ["\uE000", "\uFFFF"]
--         ]));
--test_mix("\\W", ["iu", "imu"],
--         AllSurrogateAndCharacterClass([
--             ["\u0000", "/"],
--             [":", "@"],
--             ["[", "^"],
--             ["`", "`"],
--             ["{", "\u017E"],
--             ["\u0180", "\u2129"],
--             ["\u212B", "\uD7FF"],
--             ["\uE000", "\uFFFF"]
--         ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom_ControlEscape.js b/js/src/jit-test/tests/regexp_parse/Atom_ControlEscape.js
---- a/js/src/jit-test/tests/regexp_parse/Atom_ControlEscape.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom_ControlEscape.js
-@@ -1,19 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("\\f", all_flags,
--         Atom("\u000c"));
--
--test_mix("\\n", all_flags,
--         Atom("\u000a"));
--
--test_mix("\\r", all_flags,
--         Atom("\u000d"));
--
--test_mix("\\t", all_flags,
--         Atom("\u0009"));
--
--test_mix("\\v", all_flags,
--         Atom("\u000b"));
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom_ControlLetter.js b/js/src/jit-test/tests/regexp_parse/Atom_ControlLetter.js
---- a/js/src/jit-test/tests/regexp_parse/Atom_ControlLetter.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom_ControlLetter.js
-@@ -1,13 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("\\ca", all_flags,
--         Atom("\u0001"));
--test_mix("\\cz", all_flags,
--         Atom("\u001a"));
--test_mix("\\cA", all_flags,
--         Atom("\u0001"));
--test_mix("\\cZ", all_flags,
--         Atom("\u001a"));
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom_DecimalEscape.js b/js/src/jit-test/tests/regexp_parse/Atom_DecimalEscape.js
---- a/js/src/jit-test/tests/regexp_parse/Atom_DecimalEscape.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom_DecimalEscape.js
-@@ -1,87 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--// LegacyOctalEscapeSequence
--
--test_mix("\\1", no_unicode_flags,
--         Atom("\u0001"));
--test_mix("\\2", no_unicode_flags,
--         Atom("\u0002"));
--test_mix("\\3", no_unicode_flags,
--         Atom("\u0003"));
--test_mix("\\4", no_unicode_flags,
--         Atom("\u0004"));
--test_mix("\\5", no_unicode_flags,
--         Atom("\u0005"));
--test_mix("\\6", no_unicode_flags,
--         Atom("\u0006"));
--test_mix("\\7", no_unicode_flags,
--         Atom("\u0007"));
--test_mix("\\8", no_unicode_flags,
--         Atom("8"));
--test_mix("\\9", no_unicode_flags,
--         Atom("9"));
--
--test_mix("\\10", no_unicode_flags,
--         Atom("\u0008"));
--test_mix("\\11", no_unicode_flags,
--         Atom("\u0009"));
--
--test_mix("\\189", no_unicode_flags,
--         Atom("\u{0001}89"));
--test_mix("\\1089", no_unicode_flags,
--         Atom("\u{0008}89"));
--test_mix("\\10189", no_unicode_flags,
--         Atom("A89"));
--test_mix("\\101189", no_unicode_flags,
--         Atom("A189"));
--
--// BackReference
--
--test_mix("()\\1", no_unicode_flags,
--         Alternative([
--             Capture(1, Empty()),
--             BackReference(1)
--         ]));
--test_mix("()\\1", unicode_flags,
--         Alternative([
--             Capture(1, Empty()),
--             Alternative([
--                 BackReference(1),
--                 Assertion("NOT_IN_SURROGATE_PAIR")
--             ])
--         ]));
--
--test_mix("()()()()()()()()()()\\10", no_unicode_flags,
--         Alternative([
--             Capture(1, Empty()),
--             Capture(2, Empty()),
--             Capture(3, Empty()),
--             Capture(4, Empty()),
--             Capture(5, Empty()),
--             Capture(6, Empty()),
--             Capture(7, Empty()),
--             Capture(8, Empty()),
--             Capture(9, Empty()),
--             Capture(10, Empty()),
--             BackReference(10)
--         ]));
--test_mix("()()()()()()()()()()\\10", unicode_flags,
--         Alternative([
--             Capture(1, Empty()),
--             Capture(2, Empty()),
--             Capture(3, Empty()),
--             Capture(4, Empty()),
--             Capture(5, Empty()),
--             Capture(6, Empty()),
--             Capture(7, Empty()),
--             Capture(8, Empty()),
--             Capture(9, Empty()),
--             Capture(10, Empty()),
--             Alternative([
--                 BackReference(10),
--                 Assertion("NOT_IN_SURROGATE_PAIR")
--             ])
--         ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom_HexEscapeSequence.js b/js/src/jit-test/tests/regexp_parse/Atom_HexEscapeSequence.js
---- a/js/src/jit-test/tests/regexp_parse/Atom_HexEscapeSequence.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom_HexEscapeSequence.js
-@@ -1,19 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("\\x00", all_flags,
--         Atom("\u0000"));
--test_mix("\\xFF", all_flags,
--         Atom("\u00FF"));
--
--test_mix("\\x0", no_unicode_flags,
--         Atom("x0"));
--test_mix("\\x000", all_flags,
--         Atom("\u{0000}0"));
--
--test_mix("\\xG", no_unicode_flags,
--         Atom("xG"));
--test_mix("\\x0G", no_unicode_flags,
--         Atom("x0G"));
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom_IdentityEscape.js b/js/src/jit-test/tests/regexp_parse/Atom_IdentityEscape.js
---- a/js/src/jit-test/tests/regexp_parse/Atom_IdentityEscape.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom_IdentityEscape.js
-@@ -1,55 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--// SyntaxCharacter
--
--test("\\^", all_flags,
--     Atom("^"));
--test("\\$", all_flags,
--     Atom("$"));
--test("\\\\", all_flags,
--     Atom("\\"));
--test("\\.", all_flags,
--     Atom("."));
--test("\\*", all_flags,
--     Atom("*"));
--test("\\+", all_flags,
--     Atom("+"));
--test("\\?", all_flags,
--     Atom("?"));
--test("\\(", all_flags,
--     Atom("("));
--test("\\)", all_flags,
--     Atom(")"));
--test("\\[", all_flags,
--     Atom("["));
--test("\\]", all_flags,
--     Atom("]"));
--test("\\{", all_flags,
--     Atom("{"));
--test("\\}", all_flags,
--     Atom("}"));
--test("\\|", all_flags,
--     Atom("|"));
--
--// Slash
--
--test("\\/", all_flags,
--     Atom("/"));
--
--// SourceCharacter
--
--test("\\P", no_unicode_flags,
--     Atom("P"));
--
--test("\\uX", no_unicode_flags,
--     Atom("uX"));
--
--test("\\u{0000}", no_unicode_flags,
--     Quantifier(0, 0, "GREEDY", Atom("u")));
--
--test("\\c_", no_unicode_flags,
--     Atom("\\c_"));
--
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom_Null.js b/js/src/jit-test/tests/regexp_parse/Atom_Null.js
---- a/js/src/jit-test/tests/regexp_parse/Atom_Null.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom_Null.js
-@@ -1,7 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("\\0", all_flags,
--         Atom("\u0000"));
-diff --git a/js/src/jit-test/tests/regexp_parse/Atom_RegExpUnicodeEscapeSequence.js b/js/src/jit-test/tests/regexp_parse/Atom_RegExpUnicodeEscapeSequence.js
---- a/js/src/jit-test/tests/regexp_parse/Atom_RegExpUnicodeEscapeSequence.js
-+++ b/js/src/jit-test/tests/regexp_parse/Atom_RegExpUnicodeEscapeSequence.js
-@@ -1,108 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--// LeadSurrogate TrailSurrogate
--
--test("\\uD83D\\uDC38", all_flags,
--     Atom("\uD83D\uDC38"));
--test("X\\uD83D\\uDC38Y", no_unicode_flags,
--     Atom("X\uD83D\uDC38Y"));
--test("X\\uD83D\\uDC38Y", unicode_flags,
--     Text([
--         Atom("X"),
--         Atom("\uD83D\uDC38"),
--         Atom("Y")
--     ]));
--
--// LeadSurrogate
--
--test_mix("\\uD83D", no_unicode_flags,
--         Atom("\uD83D"));
--test("\\uD83D", unicode_flags,
--     Alternative([
--         Atom("\uD83D"),
--         NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--     ]));
--test("X\\uD83DY", unicode_flags,
--     Alternative([
--         Atom("X"),
--         Alternative([
--             Atom("\uD83D"),
--             NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--         ]),
--         Atom("Y")
--     ]));
--
--// TrailSurrogate
--
--test_mix("\\uDC38", no_unicode_flags,
--         Atom("\uDC38"));
--test("\\uDC38", unicode_flags,
--     Alternative([
--         Assertion("NOT_AFTER_LEAD_SURROGATE"),
--         Atom("\uDC38"),
--     ]));
--test("X\\uDC38Y", unicode_flags,
--     Alternative([
--         Atom("X"),
--         Alternative([
--             Assertion("NOT_AFTER_LEAD_SURROGATE"),
--             Atom("\uDC38"),
--         ]),
--         Atom("Y")
--     ]));
--
--// NonSurrogate / Hex4Digits
--
--test_mix("\\u0000", all_flags,
--         Atom("\u0000"));
--test_mix("\\uFFFF", all_flags,
--         Atom("\uFFFF"));
--
--// braced HexDigits
--
--test_mix("\\u{0000}", unicode_flags,
--         Atom("\u0000"));
--test_mix("\\u{FFFF}", unicode_flags,
--         Atom("\uFFFF"));
--
--test("\\u{1F438}", unicode_flags,
--     Atom("\uD83D\uDC38"));
--test("X\\u{1F438}Y", unicode_flags,
--     Text([
--         Atom("X"),
--         Atom("\uD83D\uDC38"),
--         Atom("Y")
--     ]));
--
--test("\\u{D83D}", unicode_flags,
--     Alternative([
--         Atom("\uD83D"),
--         NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--     ]));
--test("X\\u{D83D}Y", unicode_flags,
--     Alternative([
--         Atom("X"),
--         Alternative([
--             Atom("\uD83D"),
--             NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--         ]),
--         Atom("Y")
--     ]));
--
--test("\\u{DC38}", unicode_flags,
--     Alternative([
--         Assertion("NOT_AFTER_LEAD_SURROGATE"),
--         Atom("\uDC38"),
--     ]));
--test("X\\u{DC38}Y", unicode_flags,
--     Alternative([
--         Atom("X"),
--         Alternative([
--             Assertion("NOT_AFTER_LEAD_SURROGATE"),
--             Atom("\uDC38"),
--         ]),
--         Atom("Y")
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Capture.js b/js/src/jit-test/tests/regexp_parse/Capture.js
---- a/js/src/jit-test/tests/regexp_parse/Capture.js
-+++ b/js/src/jit-test/tests/regexp_parse/Capture.js
-@@ -1,21 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("()", all_flags,
--     Capture(1, Empty()));
--
--test("(a)", all_flags,
--     Capture(1, Atom("a")));
--
--test("((a()b))c(d)", all_flags,
--     Alternative([
--         Capture(1, Capture(2, Alternative([
--             Atom("a"),
--             Capture(3, Empty()),
--             Atom("b")
--         ]))),
--         Atom("c"),
--         Capture(4, Atom("d"))
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/CharacterClass.js b/js/src/jit-test/tests/regexp_parse/CharacterClass.js
---- a/js/src/jit-test/tests/regexp_parse/CharacterClass.js
-+++ b/js/src/jit-test/tests/regexp_parse/CharacterClass.js
-@@ -1,74 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("[]", all_flags,
--         NegativeCharacterClass([
--             ["\u0000", "\uFFFF"]
--         ]));
--
--test("[a]", all_flags,
--     CharacterClass([
--         ["a", "a"]
--     ]));
--
--test("[abc\u3042\u3044\u3046]", all_flags,
--     CharacterClass([
--         ["a", "a"],
--         ["b", "b"],
--         ["c", "c"],
--         ["\u3042", "\u3042"],
--         ["\u3044", "\u3044"],
--         ["\u3046", "\u3046"],
--     ]));
--
--test("[a-c\u3042-\u3046]", all_flags,
--     CharacterClass([
--         ["a", "c"],
--         ["\u3042", "\u3046"]
--     ]));
--
--test("[-]", all_flags,
--     CharacterClass([
--         ["-", "-"]
--     ]));
--
--// raw surrogate pair
--
--test("[X\uD83D\uDC38Y]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"],
--         ]),
--         Atom("\uD83D\uDC38")
--     ]));
--
--test("[X\uD83DY]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"]
--         ]),
--         Alternative([
--             CharacterClass([
--                 ["\uD83D", "\uD83D"]
--             ]),
--             NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--         ])
--     ]));
--
--test("[X\uDC38Y]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"]
--         ]),
--         Alternative([
--             Assertion("NOT_AFTER_LEAD_SURROGATE"),
--             CharacterClass([
--                 ["\uDC38", "\uDC38"]
--             ])
--         ])
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/CharacterClass_CharacterClassEscape.js b/js/src/jit-test/tests/regexp_parse/CharacterClass_CharacterClassEscape.js
---- a/js/src/jit-test/tests/regexp_parse/CharacterClass_CharacterClassEscape.js
-+++ b/js/src/jit-test/tests/regexp_parse/CharacterClass_CharacterClassEscape.js
-@@ -1,115 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("[\\d]", all_flags,
--     CharacterClass([["0", "9"]]));
--
--test("[\\D]", no_unicode_flags,
--     CharacterClass([
--         ["\u0000", "/"],
--         [":", "\uFFFF"]
--     ]));
--test("[\\D]", unicode_flags,
--     AllSurrogateAndCharacterClass([
--         ["\u0000", "/"],
--         [":", "\uD7FF"],
--         ["\uE000", "\uFFFF"]
--     ]));
--
--test("[\\s]", all_flags,
--     CharacterClass([
--         ["\t", "\r"],
--         [" ", " "],
--         ["\u00A0", "\u00A0"],
--         ["\u1680", "\u1680"],
--         ["\u2000", "\u200A"],
--         ["\u2028", "\u2029"],
--         ["\u202F", "\u202F"],
--         ["\u205F", "\u205F"],
--         ["\u3000", "\u3000"],
--         ["\uFEFF", "\uFEFF"]
--     ]));
--test("[\\S]", no_unicode_flags,
--     CharacterClass([
--         ["\u0000", "\u0008"],
--         ["\u000E", "\u001F"],
--         ["!", "\u009F"],
--         ["\u00A1", "\u167F"],
--         ["\u1681", "\u1FFF"],
--         ["\u200B", "\u2027"],
--         ["\u202A", "\u202E"],
--         ["\u2030", "\u205E"],
--         ["\u2060", "\u2FFF"],
--         ["\u3001", "\uFEFE"],
--         ["\uFF00", "\uFFFF"]
--     ]));
--test("[\\S]", unicode_flags,
--     AllSurrogateAndCharacterClass([
--         ["\u0000", "\u0008"],
--         ["\u000E", "\u001F"],
--         ["!", "\u009F"],
--         ["\u00A1", "\u167F"],
--         ["\u1681", "\u1FFF"],
--         ["\u200B", "\u2027"],
--         ["\u202A", "\u202E"],
--         ["\u2030", "\u205E"],
--         ["\u2060", "\u2FFF"],
--         ["\u3001", "\uD7FF"],
--         ["\uE000", "\uFEFE"],
--         ["\uFF00", "\uFFFF"]
--     ]));
--
--test("[\\w]", no_unicode_flags,
--     CharacterClass([
--         ["0", "9"],
--         ["A", "Z"],
--         ["_", "_"],
--         ["a", "z"]
--     ]));
--test("[\\w]", ["u", "mu"],
--     CharacterClass([
--         ["0", "9"],
--         ["A", "Z"],
--         ["_", "_"],
--         ["a", "z"]
--     ]));
--test("[\\w]", ["iu", "imu"],
--     CharacterClass([
--         ["0", "9"],
--         ["A", "Z"],
--         ["_", "_"],
--         ["a", "z"],
--         ["\u017F", "\u017F"],
--         ["\u212A", "\u212A"]
--     ]));
--
--test("[\\W]", no_unicode_flags,
--     CharacterClass([
--         ["\u0000", "/"],
--         [":", "@"],
--         ["[", "^"],
--         ["`", "`"],
--         ["{", "\uFFFF"]
--     ]));
--test("[\\W]", ["u", "mu"],
--     AllSurrogateAndCharacterClass([
--         ["\u0000", "/"],
--         [":", "@"],
--         ["[", "^"],
--         ["`", "`"],
--         ["{", "\uD7FF"],
--         ["\uE000", "\uFFFF"]
--     ]));
--test("[\\W]", ["iu", "imu"],
--     AllSurrogateAndCharacterClass([
--         ["\u0000", "/"],
--         [":", "@"],
--         ["[", "^"],
--         ["`", "`"],
--         ["{", "\u017E"],
--         ["\u0180", "\u2129"],
--         ["\u212B", "\uD7FF"],
--         ["\uE000", "\uFFFF"]
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/CharacterClass_ClassEscape.js b/js/src/jit-test/tests/regexp_parse/CharacterClass_ClassEscape.js
---- a/js/src/jit-test/tests/regexp_parse/CharacterClass_ClassEscape.js
-+++ b/js/src/jit-test/tests/regexp_parse/CharacterClass_ClassEscape.js
-@@ -1,13 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("[\b]", all_flags,
--     CharacterClass([
--         ["\u0008", "\u0008"]
--     ]));
--test("[\-]", all_flags,
--     CharacterClass([
--         ["-", "-"]
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/CharacterClass_ControlEscape.js b/js/src/jit-test/tests/regexp_parse/CharacterClass_ControlEscape.js
---- a/js/src/jit-test/tests/regexp_parse/CharacterClass_ControlEscape.js
-+++ b/js/src/jit-test/tests/regexp_parse/CharacterClass_ControlEscape.js
-@@ -1,29 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("[\\f]", all_flags,
--     CharacterClass([
--         ["\u000c", "\u000c"]
--     ]));
--
--test("[\\n]", all_flags,
--     CharacterClass([
--         ["\u000a", "\u000a"]
--     ]));
--
--test("[\\r]", all_flags,
--     CharacterClass([
--         ["\u000d", "\u000d"]
--     ]));
--
--test("[\\t]", all_flags,
--     CharacterClass([
--         ["\u0009", "\u0009"]
--     ]));
--
--test("[\\v]", all_flags,
--     CharacterClass([
--         ["\u000b", "\u000b"]
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/CharacterClass_ControlLetter.js b/js/src/jit-test/tests/regexp_parse/CharacterClass_ControlLetter.js
---- a/js/src/jit-test/tests/regexp_parse/CharacterClass_ControlLetter.js
-+++ b/js/src/jit-test/tests/regexp_parse/CharacterClass_ControlLetter.js
-@@ -1,35 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("[\\ca]", all_flags,
--     CharacterClass([
--         ["\u0001", "\u0001"]
--     ]));
--test("[\\cz]", all_flags,
--     CharacterClass([
--         ["\u001a", "\u001a"]
--     ]));
--test("[\\cA]", all_flags,
--     CharacterClass([
--         ["\u0001", "\u0001"]
--     ]));
--test("[\\cZ]", all_flags,
--     CharacterClass([
--         ["\u001a", "\u001a"]
--     ]));
--
--// Invalid
--
--test("[\\c]", no_unicode_flags,
--     CharacterClass([
--         ["\\", "\\"],
--         ["c", "c"]
--     ]));
--test("[\\c=]", no_unicode_flags,
--     CharacterClass([
--         ["\\", "\\"],
--         ["c", "c"],
--         ["=", "="]
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/CharacterClass_HexEscapeSequence.js b/js/src/jit-test/tests/regexp_parse/CharacterClass_HexEscapeSequence.js
---- a/js/src/jit-test/tests/regexp_parse/CharacterClass_HexEscapeSequence.js
-+++ b/js/src/jit-test/tests/regexp_parse/CharacterClass_HexEscapeSequence.js
-@@ -1,39 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("[\\x00]", all_flags,
--     CharacterClass([
--         ["\u0000", "\u0000"]
--     ]));
--test("[\\xff]", all_flags,
--     CharacterClass([
--         ["\u00FF", "\u00FF"]
--     ]));
--
--// Invalid
--
--test("[\\x]", no_unicode_flags,
--     CharacterClass([
--         ["x", "x"]
--     ]));
--
--test("[\\xG]", no_unicode_flags,
--     CharacterClass([
--         ["x", "x"],
--         ["G", "G"]
--     ]));
--
--test("[\\x0]", no_unicode_flags,
--     CharacterClass([
--         ["x", "x"],
--         ["0", "0"]
--     ]));
--
--test("[\\x0G]", no_unicode_flags,
--     CharacterClass([
--         ["x", "x"],
--         ["0", "0"],
--         ["G", "G"],
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/CharacterClass_Null.js b/js/src/jit-test/tests/regexp_parse/CharacterClass_Null.js
---- a/js/src/jit-test/tests/regexp_parse/CharacterClass_Null.js
-+++ b/js/src/jit-test/tests/regexp_parse/CharacterClass_Null.js
-@@ -1,9 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("[\\0]", all_flags,
--     CharacterClass([
--         ["\u0000", "\u0000"]
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/CharacterClass_RegExpUnicodeEscapeSequence.js b/js/src/jit-test/tests/regexp_parse/CharacterClass_RegExpUnicodeEscapeSequence.js
---- a/js/src/jit-test/tests/regexp_parse/CharacterClass_RegExpUnicodeEscapeSequence.js
-+++ b/js/src/jit-test/tests/regexp_parse/CharacterClass_RegExpUnicodeEscapeSequence.js
-@@ -1,162 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--// LeadSurrogate TrailSurrogate
--
--test("[X\\uD83D\\uDC38Y]", no_unicode_flags,
--     CharacterClass([
--         ["X", "X"],
--         ["\uD83D", "\uD83D"],
--         ["\uDC38", "\uDC38"],
--         ["Y", "Y"]
--     ]));
--test("[X\\uD83D\\uDC38Y]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"],
--         ]),
--         Atom("\uD83D\uDC38")
--     ]));
--
--// LeadSurrogate
--
--test("[X\\uD83DY]", no_unicode_flags,
--     CharacterClass([
--         ["X", "X"],
--         ["\uD83D", "\uD83D"],
--         ["Y", "Y"]
--     ]));
--test("[X\\uD83DY]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"]
--         ]),
--         Alternative([
--             CharacterClass([
--                 ["\uD83D", "\uD83D"]
--             ]),
--             NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--         ])
--     ]));
--
--// TrailSurrogate
--
--test("[X\\uDC38Y]", no_unicode_flags,
--     CharacterClass([
--         ["X", "X"],
--         ["\uDC38", "\uDC38"],
--         ["Y", "Y"]
--     ]));
--test("[X\\uDC38Y]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"]
--         ]),
--         Alternative([
--             Assertion("NOT_AFTER_LEAD_SURROGATE"),
--             CharacterClass([
--                 ["\uDC38", "\uDC38"]
--             ])
--         ])
--     ]));
--
--// NonSurrogate / Hex4Digits
--
--test("[X\\u0000Y]", all_flags,
--     CharacterClass([
--         ["X", "X"],
--         ["\u0000", "\u0000"],
--         ["Y", "Y"]
--     ]));
--test("[X\\uFFFFY]", all_flags,
--     CharacterClass([
--         ["X", "X"],
--         ["\uFFFF", "\uFFFF"],
--         ["Y", "Y"]
--     ]));
--
--// braced HexDigits
--
--test("[X\\u{0000}Y]", unicode_flags,
--     CharacterClass([
--         ["X", "X"],
--         ["\u0000", "\u0000"],
--         ["Y", "Y"]
--     ]));
--test("[X\\uFFFFY]", unicode_flags,
--     CharacterClass([
--         ["X", "X"],
--         ["\uFFFF", "\uFFFF"],
--         ["Y", "Y"]
--     ]));
--
--test("[X\\u{1F438}Y]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"],
--         ]),
--         Atom("\uD83D\uDC38")
--     ]));
--
--test("[X\\u{D83D}Y]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"]
--         ]),
--         Alternative([
--             CharacterClass([
--                 ["\uD83D", "\uD83D"]
--             ]),
--             NegativeLookahead(CharacterClass([["\uDC00", "\uDFFF"]]))
--         ])
--     ]));
--test("[X\\u{DC38}Y]", unicode_flags,
--     Disjunction([
--         CharacterClass([
--             ["X", "X"],
--             ["Y", "Y"]
--         ]),
--         Alternative([
--             Assertion("NOT_AFTER_LEAD_SURROGATE"),
--             CharacterClass([
--                 ["\uDC38", "\uDC38"]
--             ])
--         ])
--     ]));
--
--// Invalid
--
--test("[\\u]", no_unicode_flags,
--     CharacterClass([
--         ["u", "u"]
--     ]));
--
--test("[\\uG]", no_unicode_flags,
--     CharacterClass([
--         ["u", "u"],
--         ["G", "G"]
--     ]));
--
--test("[\\uD83]", no_unicode_flags,
--     CharacterClass([
--         ["u", "u"],
--         ["D", "D"],
--         ["8", "8"],
--         ["3", "3"]
--     ]));
--
--test("[\\uD83G]", no_unicode_flags,
--     CharacterClass([
--         ["u", "u"],
--         ["D", "D"],
--         ["8", "8"],
--         ["3", "3"],
--         ["G", "G"]
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Disjunction.js b/js/src/jit-test/tests/regexp_parse/Disjunction.js
---- a/js/src/jit-test/tests/regexp_parse/Disjunction.js
-+++ b/js/src/jit-test/tests/regexp_parse/Disjunction.js
-@@ -1,42 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("a|\u3042", all_flags,
--     Disjunction([
--         Atom("a"),
--         Atom("\u3042")
--     ]));
--
--test("a|\u3042|abc", all_flags,
--     Disjunction([
--         Atom("a"),
--         Atom("\u3042"),
--         Atom("abc")
--     ]));
--
--test("|", all_flags,
--     Disjunction([
--         Empty(),
--         Empty()
--     ]));
--
--test("||", all_flags,
--     Disjunction([
--         Empty(),
--         Empty(),
--         Empty()
--     ]));
--
--test("abc|", all_flags,
--     Disjunction([
--         Atom("abc"),
--         Empty()
--     ]));
--
--test("|abc", all_flags,
--     Disjunction([
--         Empty(),
--         Atom("abc")
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Empty.js b/js/src/jit-test/tests/regexp_parse/Empty.js
---- a/js/src/jit-test/tests/regexp_parse/Empty.js
-+++ b/js/src/jit-test/tests/regexp_parse/Empty.js
-@@ -1,7 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("", all_flags,
--     Empty());
-diff --git a/js/src/jit-test/tests/regexp_parse/Everything.js b/js/src/jit-test/tests/regexp_parse/Everything.js
---- a/js/src/jit-test/tests/regexp_parse/Everything.js
-+++ b/js/src/jit-test/tests/regexp_parse/Everything.js
-@@ -1,21 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix(".", no_unicode_flags,
--         CharacterClass([
--             ["\u0000", "\u0009"],
--             ["\u000b", "\u000c"],
--             ["\u000e", "\u2027"],
--             ["\u202A", "\uFFFF"]
--         ]));
--
--test_mix(".", unicode_flags,
--         AllSurrogateAndCharacterClass([
--             ["\u0000", "\u0009"],
--             ["\u000b", "\u000c"],
--             ["\u000e", "\u2027"],
--             ["\u202A", "\uD7FF"],
--             ["\uE000", "\uFFFF"]
--         ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Group.js b/js/src/jit-test/tests/regexp_parse/Group.js
---- a/js/src/jit-test/tests/regexp_parse/Group.js
-+++ b/js/src/jit-test/tests/regexp_parse/Group.js
-@@ -1,15 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test("(?:)", all_flags,
--     Empty());
--test("(?:a)", all_flags,
--     Atom("a"));
--test("X(?:a)Y", all_flags,
--     Text([
--         Atom("X"),
--         Atom("a"),
--         Atom("Y")
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Lookahead.js b/js/src/jit-test/tests/regexp_parse/Lookahead.js
---- a/js/src/jit-test/tests/regexp_parse/Lookahead.js
-+++ b/js/src/jit-test/tests/regexp_parse/Lookahead.js
-@@ -1,31 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("(?=abc)", all_flags,
--         Lookahead(Atom("abc")));
--
--test_mix("(?!abc)", all_flags,
--         NegativeLookahead(Atom("abc")));
--
--test_mix("(?=abc)+", no_unicode_flags,
--         Lookahead(Atom("abc")));
--
--// Lookahead becomes Empty because max_match of Lookahead is 0 and the min vaue
--// of Quantifier is also 0.
--test("(?=abc)*", no_unicode_flags,
--     Empty());
--test("X(?=abc)*Y", no_unicode_flags,
--     Alternative([
--         Atom("X"),
--         Atom("Y"),
--     ]));
--
--test("(?=abc)?", no_unicode_flags,
--     Empty());
--test("X(?=abc)?Y", no_unicode_flags,
--     Alternative([
--         Atom("X"),
--         Atom("Y"),
--     ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/MatchOnly.js b/js/src/jit-test/tests/regexp_parse/MatchOnly.js
---- a/js/src/jit-test/tests/regexp_parse/MatchOnly.js
-+++ b/js/src/jit-test/tests/regexp_parse/MatchOnly.js
-@@ -1,35 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--// Leading and trailing .* are ignored if match_only==true.
--
--test_match_only(".*abc", all_flags,
--                Atom("abc"));
--test_match_only("abc.*", all_flags,
--                Atom("abc"));
--
--test_match_only(".*?abc", no_unicode_flags,
--                Alternative([
--                    Quantifier(0, kInfinity, "NON_GREEDY",
--                               CharacterClass([
--                                   ["\u0000", "\u0009"],
--                                   ["\u000b", "\u000c"],
--                                   ["\u000e", "\u2027"],
--                                   ["\u202A", "\uFFFF"]
--                               ])),
--                    Atom("abc")
--                ]));
--test_match_only(".*?abc", unicode_flags,
--                Alternative([
--                    Quantifier(0, kInfinity, "NON_GREEDY",
--                               AllSurrogateAndCharacterClass([
--                                   ["\u0000", "\u0009"],
--                                   ["\u000b", "\u000c"],
--                                   ["\u000e", "\u2027"],
--                                   ["\u202A", "\uD7FF"],
--                                   ["\uE000", "\uFFFF"]
--                               ])),
--                    Atom("abc")
--                ]));
-diff --git a/js/src/jit-test/tests/regexp_parse/Quantifier.js b/js/src/jit-test/tests/regexp_parse/Quantifier.js
---- a/js/src/jit-test/tests/regexp_parse/Quantifier.js
-+++ b/js/src/jit-test/tests/regexp_parse/Quantifier.js
-@@ -1,58 +0,0 @@
--if (typeof parseRegExp === 'undefined')
--    quit();
--
--load(libdir + "regexp_parse.js");
--
--test_mix("a*", all_flags,
--         Quantifier(0, kInfinity, "GREEDY", Atom("a")));
--test_mix("a*?", all_flags,
--         Quantifier(0, kInfinity, "NON_GREEDY", Atom("a")));
--
--test_mix("a+", all_flags,
--         Quantifier(1, kInfinity, "GREEDY", Atom("a")));
--test_mix("a+?", all_flags,
--         Quantifier(1, kInfinity, "NON_GREEDY", Atom("a")));
--
--test_mix("a?", all_flags,
--         Quantifier(0, 1, "GREEDY", Atom("a")));
--test_mix("a??", all_flags,
--         Quantifier(0, 1, "NON_GREEDY", Atom("a")));
--
--test_mix("a{3}", all_flags,
--         Quantifier(3, 3, "GREEDY", Atom("a")));
--test_mix("a{3}?", all_flags,
--         Quantifier(3, 3, "NON_GREEDY", Atom("a")));
--
--test_mix("a{3,}", all_flags,
--         Quantifier(3, kInfinity, "GREEDY", Atom("a")));
--test_mix("a{3,}?", all_flags,
--         Quantifier(3, kInfinity, "NON_GREEDY", Atom("a")));
--
--test_mix("a{3,5}", all_flags,
--         Quantifier(3, 5, "GREEDY", Atom("a")));
--test_mix("a{3,5}?", all_flags,
--         Quantifier(3, 5, "NON_GREEDY", Atom("a")));
--
--// Surrogate Pair and Quantifier
--
--test("\\uD83D\\uDC38+", no_unicode_flags,
--     Alternative([
--         Atom("\uD83D"),
--         Quantifier(1, kInfinity, "GREEDY", Atom("\uDC38"))
--     ]));
--test("\\uD83D\\uDC38+", unicode_flags,
--     Quantifier(1, kInfinity, "GREEDY", Atom("\uD83D\uDC38")));
--
--// Invalid
--
--test_mix("a{", no_unicode_flags,
--         Atom("a{"));
--test_mix("a{1", no_unicode_flags,
--         Atom("a{1"));
--test_mix("a{1,", no_unicode_flags,
--         Atom("a{1,"));
--test_mix("a{1,2", no_unicode_flags,
--         Atom("a{1,2"));
--
--test_mix("a{,", no_unicode_flags,
--         Atom("a{,"));
-diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp
---- a/js/src/jit/BaselineIC.cpp
-+++ b/js/src/jit/BaselineIC.cpp
-@@ -2083,16 +2083,21 @@ GetTemplateObjectForNative(JSContext* cx
-         return !!res;
-     }
- 
-     if (native == js::intrinsic_NewStringIterator) {
-         res.set(NewStringIteratorObject(cx, TenuredObject));
-         return !!res;
-     }
- 
-+    if (native == js::intrinsic_NewRegExpStringIterator) {
-+        res.set(NewRegExpStringIteratorObject(cx, TenuredObject));
-+        return !!res;
-+    }
-+
-     if (JitSupportsSimd() && GetTemplateObjectForSimd(cx, target, res))
-        return !!res;
- 
-     return true;
- }
- 
- static bool
- GetTemplateObjectForClassHook(JSContext* cx, JSNative hook, CallArgs& args,
-diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp
---- a/js/src/jit/CodeGenerator.cpp
-+++ b/js/src/jit/CodeGenerator.cpp
-@@ -21,31 +21,32 @@
- #include "jsprf.h"
- #include "jsstr.h"
- 
- #include "builtin/Eval.h"
- #include "builtin/RegExp.h"
- #include "builtin/SelfHostingDefines.h"
- #include "builtin/TypedObject.h"
- #include "gc/Nursery.h"
--#include "irregexp/NativeRegExpMacroAssembler.h"
-+#include "irregexp/RegExpTypes.h"
- #include "jit/AtomicOperations.h"
- #include "jit/BaselineCompiler.h"
- #include "jit/IonBuilder.h"
- #include "jit/IonIC.h"
- #include "jit/IonOptimizationLevels.h"
- #include "jit/JitcodeMap.h"
- #include "jit/JitSpewer.h"
- #include "jit/Linker.h"
- #include "jit/Lowering.h"
- #include "jit/MIRGenerator.h"
- #include "jit/MoveEmitter.h"
- #include "jit/RangeAnalysis.h"
- #include "jit/SharedICHelpers.h"
- #include "jit/StackSlotAllocator.h"
-+#include "js/RegExpFlags.h"
- #include "vm/AsyncFunction.h"
- #include "vm/AsyncIteration.h"
- #include "vm/MatchPairs.h"
- #include "vm/RegExpObject.h"
- #include "vm/RegExpStatics.h"
- #include "vm/TraceLogging.h"
- #include "vm/TypedArrayObject.h"
- #include "vm/Unicode.h"
-@@ -1204,253 +1205,324 @@ CodeGenerator::visitRegExp(LRegExp* lir)
-                                    StoreRegisterTo(output));
-     if (lir->mir()->hasShared())
-         masm.createGCObject(output, temp, templateObject, gc::DefaultHeap, ool->entry());
-     else
-         masm.jump(ool->entry());
-     masm.bind(ool->rejoin());
- }
- 
-+static const size_t InputOutputDataSize = sizeof(irregexp::InputOutputData);
-+
- // Amount of space to reserve on the stack when executing RegExps inline.
--static const size_t RegExpReservedStack = sizeof(irregexp::InputOutputData)
-+static const size_t RegExpReservedStack = InputOutputDataSize
-                                         + sizeof(MatchPairs)
-                                         + RegExpObject::MaxPairCount * sizeof(MatchPair);
- 
- static size_t
- RegExpPairsVectorStartOffset(size_t inputOutputDataStartOffset)
- {
--    return inputOutputDataStartOffset + sizeof(irregexp::InputOutputData) + sizeof(MatchPairs);
-+    return inputOutputDataStartOffset + InputOutputDataSize + sizeof(MatchPairs);
- }
- 
- static Address
- RegExpPairCountAddress(MacroAssembler& masm, size_t inputOutputDataStartOffset)
- {
-     return Address(masm.getStackPointer(), inputOutputDataStartOffset
--                                           + sizeof(irregexp::InputOutputData)
-+                                           + InputOutputDataSize
-                                            + MatchPairs::offsetOfPairCount());
- }
- 
--// Prepare an InputOutputData and optional MatchPairs which space has been
--// allocated for on the stack, and try to execute a RegExp on a string input.
--// If the RegExp was successfully executed and matched the input, fallthrough,
--// otherwise jump to notFound or failure.
--static bool
--PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm, Register regexp, Register input,
-+// When the unicode flag is set, if lastIndex points to a trail
-+// surrogate, we should step back to the corresponding lead surrogate.
-+// See ExecuteRegExp in builtin/RegExp.cpp for more detail.
-+static void
-+StepBackToLeadSurrogate(MacroAssembler& masm,
-+                        Register regexpShared,
-+                        Register input,
-                         Register lastIndex,
--                        Register temp1, Register temp2, Register temp3,
--                        size_t inputOutputDataStartOffset,
--                        RegExpShared::CompilationMode mode,
--                        Label* notFound, Label* failure)
--{
--    size_t matchPairsStartOffset = inputOutputDataStartOffset + sizeof(irregexp::InputOutputData);
--    size_t pairsVectorStartOffset = RegExpPairsVectorStartOffset(inputOutputDataStartOffset);
--
--    Address inputStartAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, inputStart));
--    Address inputEndAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, inputEnd));
--    Address matchesPointerAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, matches));
--    Address startIndexAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, startIndex));
--    Address endIndexAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, endIndex));
--    Address matchResultAddress(masm.getStackPointer(),
--        inputOutputDataStartOffset + offsetof(irregexp::InputOutputData, result));
--
--    Address pairCountAddress = RegExpPairCountAddress(masm, inputOutputDataStartOffset);
--    Address pairsPointerAddress(masm.getStackPointer(),
--        matchPairsStartOffset + MatchPairs::offsetOfPairs());
--
--    Address pairsVectorAddress(masm.getStackPointer(), pairsVectorStartOffset);
--
--    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global());
--    if (!res)
--        return false;
--#ifdef JS_USE_LINK_REGISTER
--    if (mode != RegExpShared::MatchOnly)
--        masm.pushReturnAddress();
--#endif
--    if (mode == RegExpShared::Normal) {
--        // First, fill in a skeletal MatchPairs instance on the stack. This will be
--        // passed to the OOL stub in the caller if we aren't able to execute the
--        // RegExp inline, and that stub needs to be able to determine whether the
--        // execution finished successfully.
--        masm.store32(Imm32(1), pairCountAddress);
--        masm.store32(Imm32(-1), pairsVectorAddress);
--        masm.computeEffectiveAddress(pairsVectorAddress, temp1);
--        masm.storePtr(temp1, pairsPointerAddress);
--    }
--
--    // Check for a linear input string.
--    masm.branchIfRopeOrExternal(input, temp1, failure);
--
--    // Get the RegExpShared for the RegExp.
--    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)), temp1);
--    masm.branchPtr(Assembler::Equal, temp1, ImmWord(0), failure);
--
--    // ES6 21.2.2.2 step 2.
--    // See RegExp.cpp ExecuteRegExp for more detail.
--    {
--        Label done;
--
--        masm.branchTest32(Assembler::Zero, Address(temp1, RegExpShared::offsetOfFlags()),
--                          Imm32(UnicodeFlag), &done);
--
--        // If input is latin1, there should not be surrogate pair.
--        masm.branchLatin1String(input, &done);
--
--        // Check if |lastIndex > 0 && lastIndex < input->length()|.
--        // lastIndex should already have no sign here.
--        masm.branchTest32(Assembler::Zero, lastIndex, lastIndex, &done);
--        masm.loadStringLength(input, temp2);
--        masm.branch32(Assembler::AboveOrEqual, lastIndex, temp2, &done);
--
--        // Check if input[lastIndex] is trail surrogate.
--        masm.loadStringChars(input, temp2);
--        masm.computeEffectiveAddress(BaseIndex(temp2, lastIndex, TimesTwo), temp3);
--        masm.load16ZeroExtend(Address(temp3, 0), temp3);
--
--        masm.branch32(Assembler::Below, temp3, Imm32(unicode::TrailSurrogateMin), &done);
--        masm.branch32(Assembler::Above, temp3, Imm32(unicode::TrailSurrogateMax), &done);
--
--        // Check if input[lastIndex-1] is lead surrogate.
--        masm.move32(lastIndex, temp3);
--        masm.sub32(Imm32(1), temp3);
--        masm.computeEffectiveAddress(BaseIndex(temp2, temp3, TimesTwo), temp3);
--        masm.load16ZeroExtend(Address(temp3, 0), temp3);
--
--        masm.branch32(Assembler::Below, temp3, Imm32(unicode::LeadSurrogateMin), &done);
--        masm.branch32(Assembler::Above, temp3, Imm32(unicode::LeadSurrogateMax), &done);
--
--        // Move lastIndex to lead surrogate.
--        masm.subPtr(Imm32(1), lastIndex);
--
--        masm.bind(&done);
--    }
--
--    if (mode == RegExpShared::Normal) {
--        // Don't handle RegExps with excessive parens.
--        masm.load32(Address(temp1, RegExpShared::offsetOfParenCount()), temp2);
--        masm.branch32(Assembler::AboveOrEqual, temp2, Imm32(RegExpObject::MaxPairCount), failure);
--
--        // Fill in the paren count in the MatchPairs on the stack.
--        masm.add32(Imm32(1), temp2);
--        masm.store32(temp2, pairCountAddress);
--    }
--
--    // Load the code pointer for the type of input string we have, and compute
--    // the input start/end pointers in the InputOutputData.
--    Register codePointer = temp1;
--    {
--        masm.loadStringChars(input, temp2);
--        masm.storePtr(temp2, inputStartAddress);
--        masm.loadStringLength(input, temp3);
--
--        Label isLatin1, done;
--        masm.branchLatin1String(input, &isLatin1);
--        {
--            masm.lshiftPtr(Imm32(1), temp3);
--            masm.loadPtr(Address(temp1, RegExpShared::offsetOfTwoByteJitCode(mode)),
--                         codePointer);
--        }
--        masm.jump(&done);
--        {
--            masm.bind(&isLatin1);
--            masm.loadPtr(Address(temp1, RegExpShared::offsetOfLatin1JitCode(mode)),
--                         codePointer);
--        }
--        masm.bind(&done);
--
--        masm.addPtr(temp3, temp2);
--        masm.storePtr(temp2, inputEndAddress);
--    }
--
--    // Check the RegExpShared has been compiled for this type of input.
--    masm.branchPtr(Assembler::Equal, codePointer, ImmWord(0), failure);
--    masm.loadPtr(Address(codePointer, JitCode::offsetOfCode()), codePointer);
--
--    // Finish filling in the InputOutputData instance on the stack.
--    if (mode == RegExpShared::Normal) {
--        masm.computeEffectiveAddress(Address(masm.getStackPointer(), matchPairsStartOffset), temp2);
--        masm.storePtr(temp2, matchesPointerAddress);
--    } else {
--        // Use InputOutputData.endIndex itself for output.
--        masm.computeEffectiveAddress(endIndexAddress, temp2);
--        masm.storePtr(temp2, endIndexAddress);
--    }
--    masm.storePtr(lastIndex, startIndexAddress);
--    masm.store32(Imm32(0), matchResultAddress);
--
--    // Save any volatile inputs.
--    LiveGeneralRegisterSet volatileRegs;
--    if (lastIndex.volatile_())
--        volatileRegs.add(lastIndex);
--    if (input.volatile_())
--        volatileRegs.add(input);
--    if (regexp.volatile_())
--        volatileRegs.add(regexp);
--
--#ifdef JS_TRACE_LOGGING
--    if (TraceLogTextIdEnabled(TraceLogger_IrregexpExecute)) {
--        masm.push(temp1);
--        masm.loadTraceLogger(temp1);
--        masm.tracelogStartId(temp1, TraceLogger_IrregexpExecute);
--        masm.pop(temp1);
--    }
--#endif
--
--    // Execute the RegExp.
--    masm.computeEffectiveAddress(Address(masm.getStackPointer(), inputOutputDataStartOffset), temp2);
--    masm.PushRegsInMask(volatileRegs);
--    masm.setupUnalignedABICall(temp3);
--    masm.passABIArg(temp2);
--    masm.callWithABI(codePointer);
--    masm.PopRegsInMask(volatileRegs);
--
--#ifdef JS_TRACE_LOGGING
--    if (TraceLogTextIdEnabled(TraceLogger_IrregexpExecute)) {
--        masm.loadTraceLogger(temp1);
--        masm.tracelogStopId(temp1, TraceLogger_IrregexpExecute);
--    }
--#endif
--
--    Label success;
--    masm.branch32(Assembler::Equal, matchResultAddress,
--                  Imm32(RegExpRunStatus_Success_NotFound), notFound);
--    masm.branch32(Assembler::Equal, matchResultAddress,
--                  Imm32(RegExpRunStatus_Error), failure);
--
--    // Lazily update the RegExpStatics.
--    masm.movePtr(ImmPtr(res), temp1);
--
--    Address pendingInputAddress(temp1, RegExpStatics::offsetOfPendingInput());
--    Address matchesInputAddress(temp1, RegExpStatics::offsetOfMatchesInput());
--    Address lazySourceAddress(temp1, RegExpStatics::offsetOfLazySource());
--    Address lazyIndexAddress(temp1, RegExpStatics::offsetOfLazyIndex());
-+                        Register temp1,
-+                        Register temp2)
-+{
-+    Label done;
-+
-+    // If the unicode flag is not set, there is nothing to do.
-+    masm.branchTest32(Assembler::Zero,
-+                      Address(regexpShared, RegExpShared::offsetOfFlags()),
-+                      Imm32(int32_t(JS::RegExpFlag::Unicode)),
-+                      &done);
-+
-+    // If the input is latin1, there can't be any surrogates.
-+    masm.branchLatin1String(input, &done);
-+
-+    // Check if |lastIndex > 0 && lastIndex < input->length()|.
-+    // lastIndex should already have no sign here.
-+    masm.branchTest32(Assembler::Zero, lastIndex, lastIndex, &done);
-+    masm.loadStringLength(input, temp1);
-+    masm.branch32(Assembler::AboveOrEqual, lastIndex, temp1, &done);
-+
-+    Register charsReg = temp1;
-+    masm.loadStringChars(input, charsReg);
-+
-+    // Check if input[lastIndex] is trail surrogate.
-+    masm.computeEffectiveAddress(BaseIndex(charsReg, lastIndex, TimesTwo), temp2);
-+    masm.load16ZeroExtend(Address(temp2, 0), temp2);
-+
-+    masm.branch32(Assembler::Below, temp2, Imm32(unicode::TrailSurrogateMin), &done);
-+    masm.branch32(Assembler::Above, temp2, Imm32(unicode::TrailSurrogateMax), &done);
-+
-+    // Check if input[lastIndex-1] is lead surrogate.
-+    masm.move32(lastIndex, temp2);
-+    masm.sub32(Imm32(1), temp2);
-+    masm.computeEffectiveAddress(BaseIndex(charsReg, temp2, TimesTwo), temp2);
-+    masm.load16ZeroExtend(Address(temp2, 0), temp2);
-+
-+    masm.branch32(Assembler::Below, temp2, Imm32(unicode::LeadSurrogateMin), &done);
-+    masm.branch32(Assembler::Above, temp2, Imm32(unicode::LeadSurrogateMax), &done);
-+
-+    // Move lastIndex back to lead surrogate.
-+    masm.subPtr(Imm32(1), lastIndex);
-+
-+    masm.bind(&done);
-+}
-+
-+static void
-+UpdateRegExpStatics(MacroAssembler& masm,
-+                    Register regexp,
-+                    Register input,
-+                    Register lastIndex,
-+                    Register staticsReg,
-+                    Register temp1,
-+                    Register temp2,
-+                    bool stringsCanBeInNursery,
-+                    LiveGeneralRegisterSet& volatileRegs)
-+{
-+    Address pendingInputAddress(staticsReg, RegExpStatics::offsetOfPendingInput());
-+    Address matchesInputAddress(staticsReg, RegExpStatics::offsetOfMatchesInput());
-+    Address lazySourceAddress(staticsReg, RegExpStatics::offsetOfLazySource());
-+    Address lazyIndexAddress(staticsReg, RegExpStatics::offsetOfLazyIndex());
- 
-     masm.guardedCallPreBarrier(pendingInputAddress, MIRType::String);
-     masm.guardedCallPreBarrier(matchesInputAddress, MIRType::String);
-     masm.guardedCallPreBarrier(lazySourceAddress, MIRType::String);
- 
-     masm.storePtr(input, pendingInputAddress);
-     masm.storePtr(input, matchesInputAddress);
--    masm.storePtr(lastIndex, Address(temp1, RegExpStatics::offsetOfLazyIndex()));
--    masm.store32(Imm32(1), Address(temp1, RegExpStatics::offsetOfPendingLazyEvaluation()));
--
--    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)), temp2);
--    masm.loadPtr(Address(temp2, RegExpShared::offsetOfSource()), temp3);
--    masm.storePtr(temp3, lazySourceAddress);
--    masm.load32(Address(temp2, RegExpShared::offsetOfFlags()), temp3);
--    masm.store32(temp3, Address(temp1, RegExpStatics::offsetOfLazyFlags()));
--
--    if (mode == RegExpShared::MatchOnly) {
--        // endIndex is passed via temp3.
--        masm.load32(endIndexAddress, temp3);
--    }
-+    masm.storePtr(lastIndex, Address(staticsReg, RegExpStatics::offsetOfLazyIndex()));
-+    masm.store32(Imm32(1), Address(staticsReg, RegExpStatics::offsetOfPendingLazyEvaluation()));
-+
-+    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)),
-+                 temp1);
-+    masm.loadPtr(Address(temp1, RegExpShared::offsetOfSource()), temp2);
-+    masm.storePtr(temp2, lazySourceAddress);
-+    masm.load32(Address(temp1, RegExpShared::offsetOfFlags()), temp2);
-+    masm.store32(temp2, Address(staticsReg, RegExpStatics::offsetOfLazyFlags()));
-+}
-+
-+// Prepare an InputOutputData and optional MatchPairs which space has been
-+// allocated for on the stack, and try to execute a RegExp on a string input.
-+// If the RegExp was successfully executed and matched the input, fallthrough.
-+// Otherwise, jump to notFound or failure.
-+static bool
-+PrepareAndExecuteRegExp(JSContext* cx,
-+                        MacroAssembler& masm,
-+                        Register regexp,
-+                        Register input,
-+                        Register lastIndex,
-+                        Register temp1,
-+                        Register temp2,
-+                        Register temp3,
-+                        size_t inputOutputDataStartOffset,
-+                        bool stringsCanBeInNursery,
-+                        Label* notFound,
-+                        Label* failure)
-+{
-+    using irregexp::InputOutputData;
-+
-+    size_t ioOffset = inputOutputDataStartOffset;
-+    size_t matchPairsOffset = ioOffset + sizeof(InputOutputData);
-+    size_t pairsArrayOffset = matchPairsOffset + sizeof(MatchPairs);
-+
-+    Address inputStartAddress(masm.getStackPointer(),
-+                              ioOffset + offsetof(InputOutputData, inputStart));
-+    Address inputEndAddress(masm.getStackPointer(),
-+                            ioOffset + offsetof(InputOutputData, inputEnd));
-+    Address startIndexAddress(masm.getStackPointer(),
-+                              ioOffset + offsetof(InputOutputData, startIndex));
-+    Address matchesAddress(masm.getStackPointer(), ioOffset + offsetof(InputOutputData, matches));
-+
-+    Address matchPairsAddress(masm.getStackPointer(), matchPairsOffset);
-+    Address pairCountAddress(masm.getStackPointer(),
-+                             matchPairsOffset + MatchPairs::offsetOfPairCount());
-+    Address pairsPointerAddress(masm.getStackPointer(),
-+                                matchPairsOffset + MatchPairs::offsetOfPairs());
-+
-+    Address pairsArrayAddress(masm.getStackPointer(), pairsArrayOffset);
-+
-+    // First, fill in a skeletal MatchPairs instance on the stack. This will be
-+    // passed to the OOL stub in the caller if we aren't able to execute the
-+    // RegExp inline, and that stub needs to be able to determine whether the
-+    // execution finished successfully.
-+
-+    // Initialize MatchPairs::pairCount to 1. The correct value can only
-+    // be determined after loading the RegExpShared. If the RegExpShared
-+    // has Kind::Atom, this is the correct pairCount.
-+    masm.store32(Imm32(1), pairCountAddress);
-+
-+    // Initialize MatchPairs::pairs pointer
-+    masm.store32(Imm32(-1), pairsArrayAddress);
-+    masm.computeEffectiveAddress(pairsArrayAddress, temp1);
-+    masm.storePtr(temp1, pairsPointerAddress);
-+
-+    // Check for a linear input string.
-+    masm.branchIfRopeOrExternal(input, temp1, failure);
-+
-+    // Load the RegExpShared.
-+    Register regexpReg = temp1;
-+
-+    // Get the RegExpShared for the RegExp.
-+    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)),
-+                 regexpReg);
-+    masm.branchPtr(Assembler::Equal, regexpReg, ImmWord(0), failure);
-+
-+    // Handle Atom matches
-+    Label notAtom, checkSuccess;
-+    masm.branchPtr(Assembler::Equal,
-+                   Address(regexpReg, RegExpShared::offsetOfPatternAtom()),
-+                   ImmWord(0), &notAtom);
-+    {
-+      LiveGeneralRegisterSet regsToSave(GeneralRegisterSet::Volatile());
-+      regsToSave.takeUnchecked(temp1);
-+      regsToSave.takeUnchecked(temp2);
-+      regsToSave.takeUnchecked(temp3);
-+
-+      masm.computeEffectiveAddress(matchPairsAddress, temp3);
-+
-+      masm.PushRegsInMask(regsToSave);
-+      masm.setupUnalignedABICall(temp2);
-+      masm.passABIArg(regexpReg);
-+      masm.passABIArg(input);
-+      masm.passABIArg(lastIndex);
-+      masm.passABIArg(temp3);
-+      masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ExecuteRegExpAtomRaw));
-+      masm.storeCallInt32Result(temp1);
-+      masm.PopRegsInMask(regsToSave);
-+
-+      masm.jump(&checkSuccess);
-+    }
-+    masm.bind(&notAtom);
-+
-+    // Don't handle regexps with too many capture pairs.
-+    masm.load32(Address(regexpReg, RegExpShared::offsetOfPairCount()), temp2);
-+    masm.branch32(Assembler::Above, temp2, Imm32(RegExpObject::MaxPairCount), failure);
-+
-+    // Fill in the pair count in the MatchPairs on the stack.
-+    masm.store32(temp2, pairCountAddress);
-+
-+    // Update lastIndex if necessary.
-+    StepBackToLeadSurrogate(masm, regexpReg, input, lastIndex, temp2, temp3);
-+
-+    // Load code pointer and length of input (in bytes).
-+    // Store the input start in the InputOutputData.
-+    Register codePointer = temp1; // Note: temp1 was previously regexpReg.
-+    Register byteLength = temp3;
-+    {
-+        Label isLatin1, done;
-+        masm.loadStringChars(input, temp2);
-+        masm.storePtr(temp2, inputStartAddress);
-+        masm.loadStringLength(input, byteLength);
-+
-+        masm.branchLatin1String(input, &isLatin1);
-+
-+        // Two-byte input
-+        masm.loadPtr(Address(regexpReg, RegExpShared::offsetOfJitCode(/*latin1 =*/false)),
-+                     codePointer);
-+        masm.lshiftPtr(Imm32(1), byteLength);
-+        masm.jump(&done);
-+
-+        // Latin1 input
-+        masm.bind(&isLatin1);
-+        masm.loadPtr(Address(regexpReg, RegExpShared::offsetOfJitCode(/*latin1 = */ true)),
-+                     codePointer);
-+
-+        masm.bind(&done);
-+
-+        // Store end pointer
-+        masm.addPtr(byteLength, temp2);
-+        masm.storePtr(temp2, inputEndAddress);
-+    }
-+
-+    // Guard that the RegExpShared has been compiled for this type of input.
-+    // If it has not been compiled, we fall back to the OOL case, which will
-+    // do a VM call into the interpreter.
-+    // TODO: add an interpreter trampoline?
-+    masm.branchPtr(Assembler::Equal, codePointer, ImmWord(0), failure);
-+    masm.loadPtr(Address(codePointer, JitCode::offsetOfCode()), codePointer);
-+
-+    // Finish filling in the InputOutputData instance on the stack
-+    masm.computeEffectiveAddress(matchPairsAddress, temp2);
-+    masm.storePtr(temp2, matchesAddress);
-+    masm.storePtr(lastIndex, startIndexAddress);
-+
-+    // Save any volatile inputs.
-+    LiveGeneralRegisterSet volatileRegs;
-+    if (lastIndex.volatile_()) {
-+        volatileRegs.add(lastIndex);
-+    }
-+    if (input.volatile_()) {
-+        volatileRegs.add(input);
-+    }
-+    if (regexp.volatile_()) {
-+        volatileRegs.add(regexp);
-+    }
-+
-+#ifdef JS_TRACE_LOGGING
-+    if (TraceLogTextIdEnabled(TraceLogger_IrregexpExecute)) {
-+        masm.loadTraceLogger(temp2);
-+        masm.tracelogStartId(temp2, TraceLogger_IrregexpExecute);
-+    }
-+#endif
-+
-+    // Execute the RegExp.
-+    masm.computeEffectiveAddress(Address(masm.getStackPointer(), inputOutputDataStartOffset),
-+                                 temp2);
-+    masm.PushRegsInMask(volatileRegs);
-+    masm.setupUnalignedABICall(temp3);
-+    masm.passABIArg(temp2);
-+    masm.callWithABI(codePointer);
-+    masm.storeCallInt32Result(temp1);
-+    masm.PopRegsInMask(volatileRegs);
-+
-+#ifdef JS_TRACE_LOGGING
-+    if (TraceLogTextIdEnabled(TraceLogger_IrregexpExecute)) {
-+        masm.loadTraceLogger(temp2);
-+        masm.tracelogStopId(temp2, TraceLogger_IrregexpExecute);
-+    }
-+#endif
-+
-+    Label success;
-+    masm.bind(&checkSuccess);
-+    masm.branch32(Assembler::Equal, temp1, Imm32(RegExpRunStatus_Success_NotFound), notFound);
-+    masm.branch32(Assembler::Equal, temp1, Imm32(RegExpRunStatus_Error), failure);
-+
-+    // Lazily update the RegExpStatics.
-+    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global());
-+    if (!res) {
-+        return false;
-+    }
-+    masm.movePtr(ImmPtr(res), temp1);
-+    UpdateRegExpStatics(masm,
-+                        regexp,
-+                        input,
-+                        lastIndex,
-+                        temp1,
-+                        temp2,
-+                        temp3,
-+                        stringsCanBeInNursery,
-+                        volatileRegs);
- 
-     return true;
- }
- 
- static void
- CopyStringChars(MacroAssembler& masm, Register to, Register from, Register len,
-                 Register byteOpScratch, size_t fromWidth, size_t toWidth);
- 
-@@ -1726,37 +1798,52 @@ JitCompartment::generateRegExpMatcherStu
- 
-     // The template object should have enough space for the maximum number of
-     // pairs this stub can handle.
-     MOZ_ASSERT(ObjectElements::VALUES_PER_HEADER + RegExpObject::MaxPairCount ==
-                gc::GetGCKindSlots(templateObject->asTenured().getAllocKind()));
- 
-     MacroAssembler masm(cx);
- 
-+#ifdef JS_USE_LINK_REGISTER
-+    masm.pushReturnAddress();
-+#endif
-+
-     // The InputOutputData is placed above the return address on the stack.
-     size_t inputOutputDataStartOffset = sizeof(void*);
- 
-     Label notFound, oolEntry;
-     if (!PrepareAndExecuteRegExp(cx, masm, regexp, input, lastIndex,
-                                  temp1, temp2, temp5, inputOutputDataStartOffset,
--                                 RegExpShared::Normal, &notFound, &oolEntry))
-+                                 &notFound, &oolEntry))
-     {
-         return nullptr;
-     }
- 
-+    // If a regexp has named captures, fall back to the OOL stub, which
-+    // will end up calling CreateRegExpMatchResults.
-+    Register shared = temp2;
-+    masm.loadPtr(Address(regexp, NativeObject::getFixedSlotOffset(RegExpObject::PRIVATE_SLOT)),
-+                 shared);
-+    masm.branchPtr(Assembler::NotEqual,
-+                   Address(shared, RegExpShared::offsetOfGroupsTemplate()),
-+                   ImmWord(0),
-+                   &oolEntry);
-+
-     // Construct the result.
-     Register object = temp1;
-     Label matchResultFallback, matchResultJoin;
-     masm.createGCObject(object, temp2, templateObject, gc::DefaultHeap, &matchResultFallback);
-     masm.bind(&matchResultJoin);
- 
-     // Initialize slots of result object.
-     masm.loadPtr(Address(object, NativeObject::offsetOfSlots()), temp2);
-     masm.storeValue(templateObject->getSlot(0), Address(temp2, 0));
-     masm.storeValue(templateObject->getSlot(1), Address(temp2, sizeof(Value)));
-+    masm.storeValue(templateObject->getSlot(2), Address(temp2, 2 * sizeof(Value)));
- 
-     size_t elementsOffset = NativeObject::offsetOfFixedElements();
- 
- #ifdef DEBUG
-     // Assert the initial value of initializedLength and length to make sure
-     // restoration on failure case works.
-     {
-         Label initLengthOK, lengthOK;
-@@ -1956,17 +2043,17 @@ CodeGenerator::visitOutOfLineRegExpMatch
- 
-     AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
-     regs.take(lastIndex);
-     regs.take(input);
-     regs.take(regexp);
-     Register temp = regs.takeAny();
- 
-     masm.computeEffectiveAddress(Address(masm.getStackPointer(),
--        sizeof(irregexp::InputOutputData)), temp);
-+        InputOutputDataSize), temp);
- 
-     pushArg(temp);
-     pushArg(lastIndex);
-     pushArg(input);
-     pushArg(regexp);
- 
-     // We are not using oolCallVM because we are in a Call, and that live
-     // registers are already saved by the the register allocator.
-@@ -2027,23 +2114,27 @@ JitCompartment::generateRegExpSearcherSt
-     regs.take(lastIndex);
- 
-     Register temp1 = regs.takeAny();
-     Register temp2 = regs.takeAny();
-     Register temp3 = regs.takeAny();
- 
-     MacroAssembler masm(cx);
- 
-+#ifdef JS_USE_LINK_REGISTER
-+    masm.pushReturnAddress();
-+#endif
-+
-     // The InputOutputData is placed above the return address on the stack.
-     size_t inputOutputDataStartOffset = sizeof(void*);
- 
-     Label notFound, oolEntry;
-     if (!PrepareAndExecuteRegExp(cx, masm, regexp, input, lastIndex,
-                                  temp1, temp2, temp3, inputOutputDataStartOffset,
--                                 RegExpShared::Normal, &notFound, &oolEntry))
-+                                 &notFound, &oolEntry))
-     {
-         return nullptr;
-     }
- 
-     size_t pairsVectorStartOffset = RegExpPairsVectorStartOffset(inputOutputDataStartOffset);
-     Address stringIndexAddress(masm.getStackPointer(),
-                                pairsVectorStartOffset + offsetof(MatchPair, start));
-     Address stringLimitAddress(masm.getStackPointer(),
-@@ -2113,17 +2204,17 @@ CodeGenerator::visitOutOfLineRegExpSearc
- 
-     AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
-     regs.take(lastIndex);
-     regs.take(input);
-     regs.take(regexp);
-     Register temp = regs.takeAny();
- 
-     masm.computeEffectiveAddress(Address(masm.getStackPointer(),
--        sizeof(irregexp::InputOutputData)), temp);
-+        InputOutputDataSize), temp);
- 
-     pushArg(temp);
-     pushArg(lastIndex);
-     pushArg(input);
-     pushArg(regexp);
- 
-     // We are not using oolCallVM because we are in a Call, and that live
-     // registers are already saved by the the register allocator.
-@@ -2179,41 +2270,50 @@ JitCompartment::generateRegExpTesterStub
-     regs.take(input);
-     regs.take(regexp);
-     regs.take(lastIndex);
- 
-     Register temp1 = regs.takeAny();
-     Register temp2 = regs.takeAny();
-     Register temp3 = regs.takeAny();
- 
--    masm.reserveStack(sizeof(irregexp::InputOutputData));
-+    masm.reserveStack(RegExpReservedStack);
- 
-     Label notFound, oolEntry;
-     if (!PrepareAndExecuteRegExp(cx, masm, regexp, input, lastIndex,
-                                  temp1, temp2, temp3, 0,
--                                 RegExpShared::MatchOnly, &notFound, &oolEntry))
-+                                 &notFound, &oolEntry))
-     {
-         return nullptr;
-     }
- 
-     Label done;
- 
--    // temp3 contains endIndex.
--    masm.move32(temp3, result);
-+    // In visitRegExpMatcher and visitRegExpSearcher, we reserve stack space
-+    // before calling the stub. For RegExpTester we call the stub before reserving
-+    // stack space, so the offset of the InputOutputData is 0.
-+    size_t inputOutputDataStartOffset = 0;
-+
-+    size_t pairsVectorStartOffset = RegExpPairsVectorStartOffset(inputOutputDataStartOffset);
-+    Address matchPairLimit(masm.getStackPointer(),
-+                           pairsVectorStartOffset + offsetof(MatchPair, limit));
-+
-+    // RegExpTester returns the end index of the match to update lastIndex.
-+    masm.load32(matchPairLimit, result);
-     masm.jump(&done);
- 
-     masm.bind(&notFound);
-     masm.move32(Imm32(RegExpTesterResultNotFound), result);
-     masm.jump(&done);
- 
-     masm.bind(&oolEntry);
-     masm.move32(Imm32(RegExpTesterResultFailed), result);
- 
-     masm.bind(&done);
--    masm.freeStack(sizeof(irregexp::InputOutputData));
-+    masm.freeStack(RegExpReservedStack);
-     masm.ret();
- 
-     Linker linker(masm);
-     AutoFlushICache afc("RegExpTesterStub");
-     JitCode* code = linker.newCode<CanGC>(cx, OTHER_CODE);
-     if (!code)
-         return nullptr;
- 
-@@ -5779,16 +5879,22 @@ CodeGenerator::visitNewArrayDynamicLengt
- typedef ArrayIteratorObject* (*NewArrayIteratorObjectFn)(JSContext*, NewObjectKind);
- static const VMFunction NewArrayIteratorObjectInfo =
-     FunctionInfo<NewArrayIteratorObjectFn>(NewArrayIteratorObject, "NewArrayIteratorObject");
- 
- typedef StringIteratorObject* (*NewStringIteratorObjectFn)(JSContext*, NewObjectKind);
- static const VMFunction NewStringIteratorObjectInfo =
-     FunctionInfo<NewStringIteratorObjectFn>(NewStringIteratorObject, "NewStringIteratorObject");
- 
-+typedef RegExpStringIteratorObject* (*NewRegExpStringIteratorObjectFn)(JSContext*, NewObjectKind);
-+
-+static const VMFunction NewRegExpStringIteratorObjectInfo =
-+  FunctionInfo<NewRegExpStringIteratorObjectFn>(NewRegExpStringIteratorObject,
-+                                                "NewRegExpStringIteratorObject");
-+
- void
- CodeGenerator::visitNewIterator(LNewIterator* lir)
- {
-     Register objReg = ToRegister(lir->output());
-     Register tempReg = ToRegister(lir->temp());
-     JSObject* templateObject = lir->mir()->templateObject();
- 
-     OutOfLineCode* ool;
-@@ -5798,16 +5904,22 @@ CodeGenerator::visitNewIterator(LNewIter
-                         ArgList(Imm32(GenericObject)),
-                         StoreRegisterTo(objReg));
-         break;
-       case MNewIterator::StringIterator:
-         ool = oolCallVM(NewStringIteratorObjectInfo, lir,
-                         ArgList(Imm32(GenericObject)),
-                         StoreRegisterTo(objReg));
-         break;
-+      case MNewIterator::RegExpStringIterator:
-+          ool = oolCallVM(NewRegExpStringIteratorObjectInfo,
-+                          lir,
-+                          ArgList(Imm32(GenericObject)),
-+                          StoreRegisterTo(objReg));
-+          break;
-       default:
-           MOZ_CRASH("unexpected iterator type");
-     }
- 
-     masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, ool->entry());
- 
-     masm.bind(ool->rejoin());
- }
-diff --git a/js/src/jit/InlinableNatives.h b/js/src/jit/InlinableNatives.h
---- a/js/src/jit/InlinableNatives.h
-+++ b/js/src/jit/InlinableNatives.h
-@@ -131,25 +131,27 @@
-     _(IntrinsicObjectHasPrototype)  \
-     _(IntrinsicFinishBoundFunctionInit) \
-     _(IntrinsicIsPackedArray)       \
-                                     \
-     _(IntrinsicGuardToArrayIterator) \
-     _(IntrinsicGuardToMapIterator)  \
-     _(IntrinsicGuardToSetIterator)  \
-     _(IntrinsicGuardToStringIterator) \
-+    _(IntrinsicGuardToRegExpStringIterator) \
-                                     \
-     _(IntrinsicGuardToMapObject)    \
-     _(IntrinsicGetNextMapEntryForIterator) \
-                                     \
-     _(IntrinsicGuardToSetObject)    \
-     _(IntrinsicGetNextSetEntryForIterator) \
-                                     \
-     _(IntrinsicNewArrayIterator)    \
-     _(IntrinsicNewStringIterator)   \
-+    _(IntrinsicNewRegExpStringIterator)              \
-                                     \
-     _(IntrinsicGuardToArrayBuffer)  \
-     _(IntrinsicArrayBufferByteLength) \
-     _(IntrinsicPossiblyWrappedArrayBufferByteLength) \
-                                     \
-     _(IntrinsicGuardToSharedArrayBuffer) \
-                                     \
-     _(TypedArrayConstructor)        \
-diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp
---- a/js/src/jit/JitOptions.cpp
-+++ b/js/src/jit/JitOptions.cpp
-@@ -156,16 +156,20 @@ DefaultJitOptions::DefaultJitOptions()
- 
-     // Whether to enable extra code to perform dynamic validations.
-     SET_DEFAULT(runExtraChecks, false);
- 
-     // How many invocations or loop iterations are needed before functions
-     // are compiled with the baseline compiler.
-     SET_DEFAULT(baselineWarmUpThreshold, 10);
- 
-+    // How many invocations are needed before regexps are compiled to
-+    // native code.
-+    SET_DEFAULT(regexpWarmUpThreshold, 10);
-+
-     // Number of exception bailouts (resuming into catch/finally block) before
-     // we invalidate and forbid Ion compilation.
-     SET_DEFAULT(exceptionBailoutThreshold, 10);
- 
-     // Number of bailouts without invalidation before we set
-     // JSScript::hadFrequentBailouts and invalidate.
-     SET_DEFAULT(frequentBailoutThreshold, 10);
- 
-@@ -269,16 +273,17 @@ DefaultJitOptions::enableGvn(bool enable
-     disableGvn = !enable;
- }
- 
- void
- DefaultJitOptions::setEagerCompilation()
- {
-     eagerCompilation = true;
-     baselineWarmUpThreshold = 0;
-+    regexpWarmUpThreshold = 0;
-     forcedDefaultIonWarmUpThreshold.reset();
-     forcedDefaultIonWarmUpThreshold.emplace(0);
-     forcedDefaultIonSmallFunctionWarmUpThreshold.reset();
-     forcedDefaultIonSmallFunctionWarmUpThreshold.emplace(0);
- }
- 
- void
- DefaultJitOptions::setCompilerWarmUpThreshold(uint32_t warmUpThreshold)
-diff --git a/js/src/jit/JitOptions.h b/js/src/jit/JitOptions.h
---- a/js/src/jit/JitOptions.h
-+++ b/js/src/jit/JitOptions.h
-@@ -72,16 +72,17 @@ struct DefaultJitOptions
-     bool fullDebugChecks;
-     bool limitScriptSize;
-     bool osr;
-     bool asmJSAtomicsEnable;
-     bool wasmFoldOffsets;
-     bool ionInterruptWithoutSignals;
-     bool simulatorAlwaysInterrupt;
-     uint32_t baselineWarmUpThreshold;
-+    uint32_t regexpWarmUpThreshold;
-     uint32_t exceptionBailoutThreshold;
-     uint32_t frequentBailoutThreshold;
-     uint32_t maxStackArgs;
-     uint32_t osrPcMismatchesBeforeRecompile;
-     uint32_t smallFunctionMaxBytecodeLength_;
-     uint32_t jumpThreshold;
-     uint32_t branchPruningHitCountFactor;
-     uint32_t branchPruningInstFactor;
-diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp
---- a/js/src/jit/MCallOptimize.cpp
-+++ b/js/src/jit/MCallOptimize.cpp
-@@ -20,16 +20,17 @@
- #include "builtin/TestingFunctions.h"
- #include "builtin/TypedObject.h"
- #include "jit/BaselineInspector.h"
- #include "jit/InlinableNatives.h"
- #include "jit/IonBuilder.h"
- #include "jit/Lowering.h"
- #include "jit/MIR.h"
- #include "jit/MIRGraph.h"
-+#include "js/RegExpFlags.h"
- #include "vm/ArgumentsObject.h"
- #include "vm/ArrayBufferObject.h"
- #include "vm/JSObject.h"
- #include "vm/ProxyObject.h"
- #include "vm/SelfHosting.h"
- #include "vm/SharedArrayObject.h"
- #include "vm/TypedArrayObject.h"
- 
-@@ -38,16 +39,18 @@
- #include "vm/NativeObject-inl.h"
- #include "vm/StringObject-inl.h"
- #include "vm/UnboxedObject-inl.h"
- 
- using mozilla::ArrayLength;
- using mozilla::AssertedCast;
- 
- using JS::DoubleNaNValue;
-+using JS::RegExpFlag;
-+using JS::RegExpFlags;
- using JS::TrackedOutcome;
- using JS::TrackedStrategy;
- using JS::TrackedTypeSite;
- 
- namespace js {
- namespace jit {
- 
- IonBuilder::InliningResult
-@@ -220,16 +223,18 @@ IonBuilder::inlineNativeCall(CallInfo& c
-       case InlinableNative::IsPossiblyWrappedRegExpObject:
-         return inlineIsPossiblyWrappedRegExpObject(callInfo);
-       case InlinableNative::RegExpPrototypeOptimizable:
-         return inlineRegExpPrototypeOptimizable(callInfo);
-       case InlinableNative::RegExpInstanceOptimizable:
-         return inlineRegExpInstanceOptimizable(callInfo);
-       case InlinableNative::GetFirstDollarIndex:
-         return inlineGetFirstDollarIndex(callInfo);
-+      case InlinableNative::IntrinsicNewRegExpStringIterator:
-+        return inlineNewIterator(callInfo, MNewIterator::RegExpStringIterator);
- 
-       // String natives.
-       case InlinableNative::String:
-         return inlineStringObject(callInfo);
-       case InlinableNative::StringCharCodeAt:
-         return inlineStrCharCodeAt(callInfo);
-       case InlinableNative::StringFromCharCode:
-         return inlineStrFromCharCode(callInfo);
-@@ -324,16 +329,18 @@ IonBuilder::inlineNativeCall(CallInfo& c
-       case InlinableNative::IntrinsicGuardToArrayIterator:
-         return inlineGuardToClass(callInfo, &ArrayIteratorObject::class_);
-       case InlinableNative::IntrinsicGuardToMapIterator:
-         return inlineGuardToClass(callInfo, &MapIteratorObject::class_);
-       case InlinableNative::IntrinsicGuardToSetIterator:
-         return inlineGuardToClass(callInfo, &SetIteratorObject::class_);
-       case InlinableNative::IntrinsicGuardToStringIterator:
-         return inlineGuardToClass(callInfo, &StringIteratorObject::class_);
-+      case InlinableNative::IntrinsicGuardToRegExpStringIterator:
-+        return inlineHasClass(callInfo, &RegExpStringIteratorObject::class_);
-       case InlinableNative::IntrinsicObjectHasPrototype:
-         return inlineObjectHasPrototype(callInfo);
-       case InlinableNative::IntrinsicFinishBoundFunctionInit:
-         return inlineFinishBoundFunctionInit(callInfo);
-       case InlinableNative::IntrinsicIsPackedArray:
-         return inlineIsPackedArray(callInfo);
- 
-       // Map intrinsics.
-@@ -428,26 +435,26 @@ IonBuilder::inlineNativeGetter(CallInfo&
-             return InliningStatus_NotInlined;
- 
-         MInstruction* length = addTypedArrayLength(thisArg);
-         current->push(length);
-         return InliningStatus_Inlined;
-     }
- 
-     // Try to optimize RegExp getters.
--    RegExpFlag mask = NoFlags;
-+    RegExpFlags mask = RegExpFlag::NoFlags;
-     if (RegExpObject::isOriginalFlagGetter(native, &mask)) {
-         const Class* clasp = thisTypes->getKnownClass(constraints());
-         if (clasp != &RegExpObject::class_)
-             return InliningStatus_NotInlined;
- 
-         MLoadFixedSlot* flags = MLoadFixedSlot::New(alloc(), thisArg, RegExpObject::flagsSlot());
-         current->add(flags);
-         flags->setResultType(MIRType::Int32);
--        MConstant* maskConst = MConstant::New(alloc(), Int32Value(mask));
-+        MConstant* maskConst = MConstant::New(alloc(), Int32Value(mask.value()));
-         current->add(maskConst);
-         MBitAnd* maskedFlag = MBitAnd::New(alloc(), flags, maskConst);
-         maskedFlag->setInt32Specialization();
-         current->add(maskedFlag);
- 
-         MDefinition* result = convertToBoolean(maskedFlag);
-         current->push(result);
-         return InliningStatus_Inlined;
-@@ -1033,16 +1040,20 @@ IonBuilder::inlineNewIterator(CallInfo& 
-       case MNewIterator::ArrayIterator:
-         templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewArrayIterator);
-         MOZ_ASSERT_IF(templateObject, templateObject->is<ArrayIteratorObject>());
-         break;
-       case MNewIterator::StringIterator:
-         templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewStringIterator);
-         MOZ_ASSERT_IF(templateObject, templateObject->is<StringIteratorObject>());
-         break;
-+      case MNewIterator::RegExpStringIterator:
-+        templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewRegExpStringIterator);
-+        MOZ_ASSERT_IF(templateObject, templateObject->is<RegExpStringIteratorObject>());
-+        break;
-     }
- 
-     if (!templateObject)
-         return InliningStatus_NotInlined;
- 
-     callInfo.setImplicitlyUsedUnchecked();
- 
-     MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
-diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h
---- a/js/src/jit/MIR.h
-+++ b/js/src/jit/MIR.h
-@@ -3608,16 +3608,17 @@ class MNewObject
- class MNewIterator
-   : public MUnaryInstruction,
-     public NoTypePolicy::Data
- {
-   public:
-     enum Type {
-         ArrayIterator,
-         StringIterator,
-+        RegExpStringIterator,
-     };
- 
- private:
-     Type type_;
- 
-     MNewIterator(TempAllocator& alloc, CompilerConstraintList* constraints,
-                  MConstant* templateConst, Type type)
-       : MUnaryInstruction(classOpcode, templateConst),
-diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h
---- a/js/src/jit/MacroAssembler.h
-+++ b/js/src/jit/MacroAssembler.h
-@@ -2558,16 +2558,30 @@ class MacroAssembler : public MacroAssem
-     // on the stack, such that the JitFrameLayout would be correctly aligned on
-     // the JitStackAlignment.
-     void alignJitStackBasedOnNArgs(Register nargs);
-     void alignJitStackBasedOnNArgs(uint32_t nargs);
- 
-     inline void assertStackAlignment(uint32_t alignment, int32_t offset = 0);
- };
- 
-+// StackMacroAssembler checks no GC will happen while it's on the stack.
-+class MOZ_RAII StackMacroAssembler : public MacroAssembler
-+{
-+    JS::AutoCheckCannotGC nogc;
-+
-+  public:
-+    StackMacroAssembler()
-+      : MacroAssembler()
-+    {}
-+    explicit StackMacroAssembler(JSContext* cx)
-+      : MacroAssembler(cx)
-+    {}
-+};
-+
- //{{{ check_macroassembler_style
- inline uint32_t
- MacroAssembler::framePushed() const
- {
-     return framePushed_;
- }
- 
- inline void
-diff --git a/js/src/jit/Recover.cpp b/js/src/jit/Recover.cpp
---- a/js/src/jit/Recover.cpp
-+++ b/js/src/jit/Recover.cpp
-@@ -1450,16 +1450,19 @@ RNewIterator::recover(JSContext* cx, Sna
-     JSObject* resultObject = nullptr;
-     switch (MNewIterator::Type(type_)) {
-       case MNewIterator::ArrayIterator:
-         resultObject = NewArrayIteratorObject(cx);
-         break;
-       case MNewIterator::StringIterator:
-         resultObject = NewStringIteratorObject(cx);
-         break;
-+      case MNewIterator::RegExpStringIterator:
-+        resultObject = NewRegExpStringIteratorObject(cx);
-+        break;
-     }
- 
-     if (!resultObject)
-         return false;
- 
-     result.setObject(*resultObject);
-     iter.storeInstructionResult(result);
-     return true;
-diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h
---- a/js/src/jit/VMFunctions.h
-+++ b/js/src/jit/VMFunctions.h
-@@ -326,16 +326,17 @@ template <> struct TypeToDataType<Native
- template <> struct TypeToDataType<PlainObject*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<InlineTypedObject*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<NamedLambdaObject*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<LexicalEnvironmentObject*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<ArrayObject*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<TypedArrayObject*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<ArrayIteratorObject*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<StringIteratorObject*> { static const DataType result = Type_Object; };
-+template <> struct TypeToDataType<RegExpStringIteratorObject*>{ static const DataType result = Type_Object; };
- template <> struct TypeToDataType<JSString*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<JSFlatString*> { static const DataType result = Type_Object; };
- template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
- template <> struct TypeToDataType<HandleString> { static const DataType result = Type_Handle; };
- template <> struct TypeToDataType<HandlePropertyName> { static const DataType result = Type_Handle; };
- template <> struct TypeToDataType<HandleFunction> { static const DataType result = Type_Handle; };
- template <> struct TypeToDataType<Handle<NativeObject*> > { static const DataType result = Type_Handle; };
- template <> struct TypeToDataType<Handle<InlineTypedObject*> > { static const DataType result = Type_Handle; };
-diff --git a/js/src/jit/arm64/Assembler-arm64.h b/js/src/jit/arm64/Assembler-arm64.h
---- a/js/src/jit/arm64/Assembler-arm64.h
-+++ b/js/src/jit/arm64/Assembler-arm64.h
-@@ -70,19 +70,16 @@ static constexpr FloatRegister ScratchSi
- // StackPointer is intentionally undefined on ARM64 to prevent misuse:
- //  using sp as a base register is only valid if sp % 16 == 0.
- static constexpr Register RealStackPointer { Registers::sp };
- 
- static constexpr Register PseudoStackPointer { Registers::x28 };
- static constexpr ARMRegister PseudoStackPointer64 = { Registers::x28, 64 };
- static constexpr ARMRegister PseudoStackPointer32 = { Registers::x28, 32 };
- 
--// StackPointer for use by irregexp.
--static constexpr Register RegExpStackPointer = PseudoStackPointer;
--
- static constexpr Register IntArgReg0 { Registers::x0 };
- static constexpr Register IntArgReg1 { Registers::x1 };
- static constexpr Register IntArgReg2 { Registers::x2 };
- static constexpr Register IntArgReg3 { Registers::x3 };
- static constexpr Register IntArgReg4 { Registers::x4 };
- static constexpr Register IntArgReg5 { Registers::x5 };
- static constexpr Register IntArgReg6 { Registers::x6 };
- static constexpr Register IntArgReg7 { Registers::x7 };
-diff --git a/js/src/js.msg b/js/src/js.msg
---- a/js/src/js.msg
-+++ b/js/src/js.msg
-@@ -499,35 +499,41 @@ MSG_DEF(JSMSG_INVALID_KEY,             1
- MSG_DEF(JSMSG_INVALID_LANGUAGE_TAG,    1, JSEXN_RANGEERR, "invalid language tag: {0}")
- MSG_DEF(JSMSG_INVALID_LOCALES_ELEMENT, 0, JSEXN_TYPEERR, "invalid element in locales argument")
- MSG_DEF(JSMSG_INVALID_LOCALE_MATCHER,  1, JSEXN_RANGEERR, "invalid locale matcher in supportedLocalesOf(): {0}")
- MSG_DEF(JSMSG_INVALID_OPTION_VALUE,    2, JSEXN_RANGEERR, "invalid value {1} for option {0}")
- MSG_DEF(JSMSG_INVALID_TIME_ZONE,       1, JSEXN_RANGEERR, "invalid time zone in DateTimeFormat(): {0}")
- MSG_DEF(JSMSG_UNDEFINED_CURRENCY,      0, JSEXN_TYPEERR, "undefined currency in NumberFormat() with currency style")
- 
- // RegExp
--MSG_DEF(JSMSG_BACK_REF_OUT_OF_RANGE,   0, JSEXN_SYNTAXERR, "back reference out of range in regular expression")
- MSG_DEF(JSMSG_BAD_CLASS_RANGE,         0, JSEXN_SYNTAXERR, "invalid range in character class")
- MSG_DEF(JSMSG_ESCAPE_AT_END_OF_REGEXP, 0, JSEXN_SYNTAXERR, "\\ at end of pattern")
- MSG_DEF(JSMSG_EXEC_NOT_OBJORNULL,      0, JSEXN_TYPEERR, "RegExp exec method should return object or null")
- MSG_DEF(JSMSG_INVALID_DECIMAL_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid decimal escape in regular expression")
- MSG_DEF(JSMSG_INVALID_GROUP,           0, JSEXN_SYNTAXERR, "invalid regexp group")
- MSG_DEF(JSMSG_INVALID_IDENTITY_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid identity escape in regular expression")
- MSG_DEF(JSMSG_INVALID_UNICODE_ESCAPE,  0, JSEXN_SYNTAXERR, "invalid unicode escape in regular expression")
- MSG_DEF(JSMSG_MISSING_PAREN,           0, JSEXN_SYNTAXERR, "unterminated parenthetical")
- MSG_DEF(JSMSG_NEWREGEXP_FLAGGED,       0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another")
- MSG_DEF(JSMSG_NOTHING_TO_REPEAT,       0, JSEXN_SYNTAXERR, "nothing to repeat")
- MSG_DEF(JSMSG_NUMBERS_OUT_OF_ORDER,    0, JSEXN_SYNTAXERR, "numbers out of order in {} quantifier.")
- MSG_DEF(JSMSG_RANGE_WITH_CLASS_ESCAPE, 0, JSEXN_SYNTAXERR, "character class escape cannot be used in class range in regular expression")
--MSG_DEF(JSMSG_RAW_BRACE_IN_REGEP,      0, JSEXN_SYNTAXERR, "raw brace is not allowed in regular expression with unicode flag")
--MSG_DEF(JSMSG_RAW_BRACKET_IN_REGEP,    0, JSEXN_SYNTAXERR, "raw bracket is not allowed in regular expression with unicode flag")
-+MSG_DEF(JSMSG_RAW_BRACKET_IN_REGEXP,   0, JSEXN_SYNTAXERR, "raw bracket is not allowed in regular expression with unicode flag")
- MSG_DEF(JSMSG_TOO_MANY_PARENS,         0, JSEXN_INTERNALERR, "too many parentheses in regular expression")
- MSG_DEF(JSMSG_UNICODE_OVERFLOW,        1, JSEXN_SYNTAXERR, "Unicode codepoint must not be greater than 0x10FFFF in {0}")
- MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN,   0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
- MSG_DEF(JSMSG_UNTERM_CLASS,            0, JSEXN_SYNTAXERR, "unterminated character class")
-+MSG_DEF(JSMSG_INVALID_PROPERTY_NAME,       0, JSEXN_SYNTAXERR, "invalid property name in regular expression")
-+MSG_DEF(JSMSG_INVALID_CLASS_PROPERTY_NAME, 0, JSEXN_SYNTAXERR, "invalid class property name in regular expression")
-+MSG_DEF(JSMSG_INCOMPLETE_QUANTIFIER,       0, JSEXN_SYNTAXERR, "incomplete quantifier in regular expression")
-+MSG_DEF(JSMSG_INVALID_QUANTIFIER,          0, JSEXN_SYNTAXERR, "invalid quantifier in regular expression")
-+MSG_DEF(JSMSG_INVALID_CAPTURE_NAME,        0, JSEXN_SYNTAXERR, "invalid capture group name in regular expression")
-+MSG_DEF(JSMSG_DUPLICATE_CAPTURE_NAME,      0, JSEXN_SYNTAXERR, "duplicate capture group name in regular expression")
-+MSG_DEF(JSMSG_INVALID_NAMED_REF,           0, JSEXN_SYNTAXERR, "invalid named reference in regular expression")
-+MSG_DEF(JSMSG_INVALID_NAMED_CAPTURE_REF,   0, JSEXN_SYNTAXERR, "invalid named capture reference in regular expression")
- 
- // Self-hosting
- MSG_DEF(JSMSG_DEFAULT_LOCALE_ERROR,    0, JSEXN_ERR, "internal error getting the default locale")
- MSG_DEF(JSMSG_NO_SUCH_SELF_HOSTED_PROP,1, JSEXN_ERR, "No such property on self-hosted object: {0}")
- 
- // Typed object / SIMD
- MSG_DEF(JSMSG_INVALID_PROTOTYPE,       0, JSEXN_TYPEERR, "prototype field is not an object")
- MSG_DEF(JSMSG_TYPEDOBJECT_BAD_ARGS,    0, JSEXN_TYPEERR, "invalid arguments")
-diff --git a/js/src/jsapi-tests/testRegExp.cpp b/js/src/jsapi-tests/testRegExp.cpp
---- a/js/src/jsapi-tests/testRegExp.cpp
-+++ b/js/src/jsapi-tests/testRegExp.cpp
-@@ -1,60 +1,64 @@
- /* This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
-+#include "js/RegExp.h"
-+#include "js/RegExpFlags.h"
- #include "jsapi-tests/tests.h"
- 
- BEGIN_TEST(testObjectIsRegExp)
- {
-     JS::RootedValue val(cx);
- 
-     bool isRegExp;
- 
-     EVAL("new Object", &val);
-     JS::RootedObject obj(cx, val.toObjectOrNull());
--    CHECK(JS_ObjectIsRegExp(cx, obj, &isRegExp));
-+    CHECK(JS::ObjectIsRegExp(cx, obj, &isRegExp));
-     CHECK(!isRegExp);
- 
-     EVAL("/foopy/", &val);
-     obj = val.toObjectOrNull();
--    CHECK(JS_ObjectIsRegExp(cx, obj, &isRegExp));
-+    CHECK(JS::ObjectIsRegExp(cx, obj, &isRegExp));
-     CHECK(isRegExp);
- 
-     return true;
- }
- END_TEST(testObjectIsRegExp)
- 
- BEGIN_TEST(testGetRegExpFlags)
- {
-     JS::RootedValue val(cx);
-     JS::RootedObject obj(cx);
- 
-     EVAL("/foopy/", &val);
-     obj = val.toObjectOrNull();
--    CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), 0u);
-+    CHECK_EQUAL(JS::GetRegExpFlags(cx, obj), JS::RegExpFlags(JS::RegExpFlag::NoFlags));
- 
-     EVAL("/foopy/g", &val);
-     obj = val.toObjectOrNull();
--    CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), JSREG_GLOB);
-+    CHECK_EQUAL(JS::GetRegExpFlags(cx, obj), JS::RegExpFlags(JS::RegExpFlag::Global));
- 
-     EVAL("/foopy/gi", &val);
-     obj = val.toObjectOrNull();
--    CHECK_EQUAL(JS_GetRegExpFlags(cx, obj), (JSREG_FOLD | JSREG_GLOB));
-+    CHECK_EQUAL(JS::GetRegExpFlags(cx, obj),
-+                JS::RegExpFlags(JS::RegExpFlag::Global | JS::RegExpFlag::IgnoreCase));
- 
-     return true;
- }
- END_TEST(testGetRegExpFlags)
- 
- BEGIN_TEST(testGetRegExpSource)
- {
-     JS::RootedValue val(cx);
-     JS::RootedObject obj(cx);
- 
-     EVAL("/foopy/", &val);
-     obj = val.toObjectOrNull();
--    JSString* source = JS_GetRegExpSource(cx, obj);
-+    JSString* source = JS::GetRegExpSource(cx, obj);
-+    CHECK(source);
-     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(source), "foopy"));
- 
-     return true;
- }
- END_TEST(testGetRegExpSource)
-diff --git a/js/src/jsapi-tests/tests.h b/js/src/jsapi-tests/tests.h
---- a/js/src/jsapi-tests/tests.h
-+++ b/js/src/jsapi-tests/tests.h
-@@ -13,16 +13,17 @@
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- 
- #include "jsalloc.h"
- #include "jsgc.h"
- 
-+#include "js/RegExpFlags.h"
- #include "js/Vector.h"
- #include "vm/JSContext.h"
- 
- /* Note: Aborts on OOM. */
- class JSAPITestString {
-     js::Vector<char, 0, js::SystemAllocPolicy> chars;
- 
-   public:
-@@ -145,16 +146,40 @@ class JSAPITest
-     JSAPITestString toSource(int v) {
-         return toSource((long)v);
-     }
- 
-     JSAPITestString toSource(bool v) {
-         return JSAPITestString(v ? "true" : "false");
-     }
- 
-+    JSAPITestString toSource(JS::RegExpFlags flags)
-+    {
-+        JSAPITestString str;
-+        if (flags.global()) {
-+            str += "g";
-+        }
-+        if (flags.ignoreCase()) {
-+            str += "i";
-+        }
-+        if (flags.multiline()) {
-+            str += "m";
-+        }
-+        if (flags.dotAll()) {
-+            str += "s";
-+        }
-+        if (flags.unicode()) {
-+            str += "u";
-+        }
-+        if (flags.sticky()) {
-+            str += "y";
-+        }
-+        return str;
-+    }
-+
-     JSAPITestString toSource(JSAtom* v) {
-         JS::RootedValue val(cx, JS::StringValue((JSString*)v));
-         return jsvalToSource(val);
-     }
- 
-     // Note that in some still-supported GCC versions (we think anything before
-     // GCC 4.6), this template does not work when the second argument is
-     // nullptr. It infers type U = long int. Use CHECK_NULL instead.
-diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
---- a/js/src/jsapi.cpp
-+++ b/js/src/jsapi.cpp
-@@ -38,17 +38,16 @@
- #include "jsweakmap.h"
- #include "jswrapper.h"
- 
- #include "builtin/AtomicsObject.h"
- #include "builtin/Eval.h"
- #include "builtin/JSON.h"
- #include "builtin/MapObject.h"
- #include "builtin/Promise.h"
--#include "builtin/RegExp.h"
- #include "builtin/Stream.h"
- #include "builtin/SymbolObject.h"
- #ifdef ENABLE_SIMD
- # include "builtin/SIMD.h"
- #endif
- #ifdef ENABLE_BINARYDATA
- # include "builtin/TypedObject.h"
- #endif
-@@ -75,17 +74,16 @@
- #include "vm/ErrorObject.h"
- #include "vm/HelperThreads.h"
- #include "vm/Interpreter.h"
- #include "vm/JSAtom.h"
- #include "vm/JSContext.h"
- #include "vm/JSFunction.h"
- #include "vm/JSObject.h"
- #include "vm/JSScript.h"
--#include "vm/RegExpStatics.h"
- #include "vm/Runtime.h"
- #include "vm/SavedStacks.h"
- #include "vm/SelfHosting.h"
- #include "vm/Shape.h"
- #include "vm/String.h"
- #include "vm/StringBuffer.h"
- #include "vm/Symbol.h"
- #include "vm/WrapperObject.h"
-@@ -6637,148 +6635,16 @@ JS_ObjectIsDate(JSContext* cx, HandleObj
-         return false;
- 
-     *isDate = cls == ESClass::Date;
-     return true;
- }
- 
- /************************************************************************/
- 
--/*
-- * Regular Expressions.
-- */
--JS_PUBLIC_API(JSObject*)
--JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--
--    ScopedJSFreePtr<char16_t> chars(InflateString(cx, bytes, length));
--    if (!chars)
--        return nullptr;
--
--    return RegExpObject::create(cx, chars.get(), length, RegExpFlag(flags), cx->tempLifoAlloc(),
--                                GenericObject);
--}
--
--JS_PUBLIC_API(JSObject*)
--JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--
--    return RegExpObject::create(cx, chars, length, RegExpFlag(flags), cx->tempLifoAlloc(),
--                                GenericObject);
--}
--
--JS_PUBLIC_API(bool)
--JS_SetRegExpInput(JSContext* cx, HandleObject obj, HandleString input)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--    assertSameCompartment(cx, input);
--
--    Handle<GlobalObject*> global = obj.as<GlobalObject>();
--    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
--    if (!res)
--        return false;
--
--    res->reset(input);
--    return true;
--}
--
--JS_PUBLIC_API(bool)
--JS_ClearRegExpStatics(JSContext* cx, HandleObject obj)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--    MOZ_ASSERT(obj);
--
--    Handle<GlobalObject*> global = obj.as<GlobalObject>();
--    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
--    if (!res)
--        return false;
--
--    res->clear();
--    return true;
--}
--
--JS_PUBLIC_API(bool)
--JS_ExecuteRegExp(JSContext* cx, HandleObject obj, HandleObject reobj, char16_t* chars,
--                 size_t length, size_t* indexp, bool test, MutableHandleValue rval)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--
--    Handle<GlobalObject*> global = obj.as<GlobalObject>();
--    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
--    if (!res)
--        return false;
--
--    RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
--    if (!input)
--        return false;
--
--    return ExecuteRegExpLegacy(cx, res, reobj.as<RegExpObject>(), input, indexp, test, rval);
--}
--
--JS_PUBLIC_API(bool)
--JS_ExecuteRegExpNoStatics(JSContext* cx, HandleObject obj, char16_t* chars, size_t length,
--                          size_t* indexp, bool test, MutableHandleValue rval)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--
--    RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
--    if (!input)
--        return false;
--
--    return ExecuteRegExpLegacy(cx, nullptr, obj.as<RegExpObject>(), input, indexp, test,
--                               rval);
--}
--
--JS_PUBLIC_API(bool)
--JS_ObjectIsRegExp(JSContext* cx, HandleObject obj, bool* isRegExp)
--{
--    assertSameCompartment(cx, obj);
--
--    ESClass cls;
--    if (!GetBuiltinClass(cx, obj, &cls))
--        return false;
--
--    *isRegExp = cls == ESClass::RegExp;
--    return true;
--}
--
--JS_PUBLIC_API(unsigned)
--JS_GetRegExpFlags(JSContext* cx, HandleObject obj)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--
--    RegExpShared* shared = RegExpToShared(cx, obj);
--    if (!shared)
--        return false;
--    return shared->getFlags();
--}
--
--JS_PUBLIC_API(JSString*)
--JS_GetRegExpSource(JSContext* cx, HandleObject obj)
--{
--    AssertHeapIsIdle();
--    CHECK_REQUEST(cx);
--
--    RegExpShared* shared = RegExpToShared(cx, obj);
--    if (!shared)
--        return nullptr;
--    return shared->getSource();
--}
--
--/************************************************************************/
--
- JS_PUBLIC_API(bool)
- JS_SetDefaultLocale(JSRuntime* rt, const char* locale)
- {
-     AssertHeapIsIdle();
-     return rt->setDefaultLocale(locale);
- }
- 
- JS_PUBLIC_API(UniqueChars)
-diff --git a/js/src/jsapi.h b/js/src/jsapi.h
---- a/js/src/jsapi.h
-+++ b/js/src/jsapi.h
-@@ -5025,17 +5025,18 @@ GetSymbolDescription(HandleSymbol symbol
-     macro(replace) \
-     macro(search) \
-     macro(species) \
-     macro(hasInstance) \
-     macro(split) \
-     macro(toPrimitive) \
-     macro(toStringTag) \
-     macro(unscopables) \
--    macro(asyncIterator)
-+    macro(asyncIterator) \
-+    macro(matchAll)
- 
- enum class SymbolCode : uint32_t {
-     // There is one SymbolCode for each well-known symbol.
- #define JS_DEFINE_SYMBOL_ENUM(name) name,
-     JS_FOR_EACH_WELL_KNOWN_SYMBOL(JS_DEFINE_SYMBOL_ENUM)  // SymbolCode::iterator, etc.
- #undef JS_DEFINE_SYMBOL_ENUM
-     Limit,
-     InSymbolRegistry = 0xfffffffe,  // created by Symbol.for() or JS::GetSymbolFor()
-@@ -5657,66 +5658,16 @@ JS_NewDateObject(JSContext* cx, int year
-  * This method returns true with |*isDate == false| when passed a proxy whose
-  * target is a Date, or when passed a revoked proxy.
-  */
- extern JS_PUBLIC_API(bool)
- JS_ObjectIsDate(JSContext* cx, JS::HandleObject obj, bool* isDate);
- 
- /************************************************************************/
- 
--/*
-- * Regular Expressions.
-- */
--#define JSREG_FOLD      0x01u   /* fold uppercase to lowercase */
--#define JSREG_GLOB      0x02u   /* global exec, creates array of matches */
--#define JSREG_MULTILINE 0x04u   /* treat ^ and $ as begin and end of line */
--#define JSREG_STICKY    0x08u   /* only match starting at lastIndex */
--#define JSREG_UNICODE   0x10u   /* unicode */
--
--extern JS_PUBLIC_API(JSObject*)
--JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags);
--
--extern JS_PUBLIC_API(JSObject*)
--JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags);
--
--extern JS_PUBLIC_API(bool)
--JS_SetRegExpInput(JSContext* cx, JS::HandleObject obj, JS::HandleString input);
--
--extern JS_PUBLIC_API(bool)
--JS_ClearRegExpStatics(JSContext* cx, JS::HandleObject obj);
--
--extern JS_PUBLIC_API(bool)
--JS_ExecuteRegExp(JSContext* cx, JS::HandleObject obj, JS::HandleObject reobj,
--                 char16_t* chars, size_t length, size_t* indexp, bool test,
--                 JS::MutableHandleValue rval);
--
--/* RegExp interface for clients without a global object. */
--
--extern JS_PUBLIC_API(bool)
--JS_ExecuteRegExpNoStatics(JSContext* cx, JS::HandleObject reobj, char16_t* chars, size_t length,
--                          size_t* indexp, bool test, JS::MutableHandleValue rval);
--
--/**
-- * Returns true and sets |*isRegExp| indicating whether |obj| is a RegExp
-- * object or a wrapper around one, otherwise returns false on failure.
-- *
-- * This method returns true with |*isRegExp == false| when passed a proxy whose
-- * target is a RegExp, or when passed a revoked proxy.
-- */
--extern JS_PUBLIC_API(bool)
--JS_ObjectIsRegExp(JSContext* cx, JS::HandleObject obj, bool* isRegExp);
--
--extern JS_PUBLIC_API(unsigned)
--JS_GetRegExpFlags(JSContext* cx, JS::HandleObject obj);
--
--extern JS_PUBLIC_API(JSString*)
--JS_GetRegExpSource(JSContext* cx, JS::HandleObject obj);
--
--/************************************************************************/
--
- extern JS_PUBLIC_API(bool)
- JS_IsExceptionPending(JSContext* cx);
- 
- extern JS_PUBLIC_API(bool)
- JS_GetPendingException(JSContext* cx, JS::MutableHandleValue vp);
- 
- extern JS_PUBLIC_API(void)
- JS_SetPendingException(JSContext* cx, JS::HandleValue v);
-diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp
---- a/js/src/jsgc.cpp
-+++ b/js/src/jsgc.cpp
-@@ -2812,17 +2812,18 @@ static const AllocKinds UpdatePhaseMisc 
-     AllocKind::SCRIPT,
-     AllocKind::LAZY_SCRIPT,
-     AllocKind::BASE_SHAPE,
-     AllocKind::SHAPE,
-     AllocKind::ACCESSOR_SHAPE,
-     AllocKind::OBJECT_GROUP,
-     AllocKind::STRING,
-     AllocKind::JITCODE,
--    AllocKind::SCOPE
-+    AllocKind::SCOPE,
-+    AllocKind::REGEXP_SHARED
- };
- 
- static const AllocKinds UpdatePhaseObjects {
-     AllocKind::FUNCTION,
-     AllocKind::FUNCTION_EXTENDED,
-     AllocKind::OBJECT0,
-     AllocKind::OBJECT0_BACKGROUND,
-     AllocKind::OBJECT2,
-diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp
---- a/js/src/jsiter.cpp
-+++ b/js/src/jsiter.cpp
-@@ -15,16 +15,17 @@
- #include "mozilla/PodOperations.h"
- #include "mozilla/Unused.h"
- 
- #include "jsarray.h"
- #include "jsopcode.h"
- #include "jstypes.h"
- #include "jsutil.h"
- 
-+#include "builtin/SelfHostingDefines.h"
- #include "ds/Sort.h"
- #include "gc/FreeOp.h"
- #include "gc/Marking.h"
- #include "js/Proxy.h"
- #include "vm/GeneratorObject.h"
- #include "vm/GlobalObject.h"
- #include "vm/Interpreter.h"
- #include "vm/JSAtom.h"
-@@ -1092,16 +1093,88 @@ js::NewStringIteratorObject(JSContext* c
- {
-     RootedObject proto(cx, GlobalObject::getOrCreateStringIteratorPrototype(cx, cx->global()));
-     if (!proto)
-         return nullptr;
- 
-     return NewObjectWithGivenProto<StringIteratorObject>(cx, proto, newKind);
- }
- 
-+static const Class RegExpStringIteratorPrototypeClass = {
-+    "RegExp String Iterator", 0
-+};
-+
-+enum {
-+  // The regular expression used for iteration. May hold the original RegExp
-+  // object when it is reused instead of a new RegExp object.
-+  RegExpStringIteratorSlotRegExp,
-+
-+  // The String value being iterated upon.
-+  RegExpStringIteratorSlotString,
-+
-+  // The source string of the original RegExp object. Used to validate we can
-+  // reuse the original RegExp object for matching.
-+  RegExpStringIteratorSlotSource,
-+
-+  // The flags of the original RegExp object.
-+  RegExpStringIteratorSlotFlags,
-+
-+  // When non-negative, this slot holds the current lastIndex position when
-+  // reusing the original RegExp object for matching. When set to |-1|, the
-+  // iterator has finished. When set to any other negative value, the
-+  // iterator is not yet exhausted and we're not on the fast path and we're
-+  // not reusing the input RegExp object.
-+  RegExpStringIteratorSlotLastIndex,
-+
-+  RegExpStringIteratorSlotCount
-+};
-+
-+static_assert(RegExpStringIteratorSlotRegExp ==
-+                  REGEXP_STRING_ITERATOR_REGEXP_SLOT,
-+              "RegExpStringIteratorSlotRegExp must match self-hosting define "
-+              "for regexp slot.");
-+static_assert(RegExpStringIteratorSlotString ==
-+                  REGEXP_STRING_ITERATOR_STRING_SLOT,
-+              "RegExpStringIteratorSlotString must match self-hosting define "
-+              "for string slot.");
-+static_assert(RegExpStringIteratorSlotSource ==
-+                  REGEXP_STRING_ITERATOR_SOURCE_SLOT,
-+              "RegExpStringIteratorSlotString must match self-hosting define "
-+              "for source slot.");
-+static_assert(RegExpStringIteratorSlotFlags ==
-+                  REGEXP_STRING_ITERATOR_FLAGS_SLOT,
-+              "RegExpStringIteratorSlotFlags must match self-hosting define "
-+              "for flags slot.");
-+static_assert(RegExpStringIteratorSlotLastIndex ==
-+                  REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
-+              "RegExpStringIteratorSlotLastIndex must match self-hosting "
-+              "define for lastIndex slot.");
-+
-+const Class RegExpStringIteratorObject::class_ = {
-+    "RegExp String Iterator",
-+    JSCLASS_HAS_RESERVED_SLOTS(RegExpStringIteratorSlotCount)
-+};
-+
-+static const JSFunctionSpec regexp_string_iterator_methods[] = {
-+    JS_SELF_HOSTED_FN("next", "RegExpStringIteratorNext", 0, 0),
-+    JS_FS_END
-+};
-+
-+RegExpStringIteratorObject* js::NewRegExpStringIteratorObject(
-+    JSContext* cx, NewObjectKind newKind) {
-+  RootedObject proto(cx, GlobalObject::getOrCreateRegExpStringIteratorPrototype(
-+                             cx, cx->global()));
-+  if (!proto) {
-+    return nullptr;
-+  }
-+
-+  return NewObjectWithGivenProto<RegExpStringIteratorObject>(cx, proto,
-+                                                             newKind);
-+}
-+
- JSObject*
- js::ValueToIterator(JSContext* cx, HandleValue vp)
- {
-     RootedObject obj(cx);
-     if (vp.isObject()) {
-         /* Common case. */
-         obj = &vp.toObject();
-     } else if (vp.isNullOrUndefined()) {
-@@ -1429,8 +1502,34 @@ GlobalObject::initStringIteratorProto(JS
-         !DefineToStringTag(cx, proto, cx->names().StringIterator))
-     {
-         return false;
-     }
- 
-     global->setReservedSlot(STRING_ITERATOR_PROTO, ObjectValue(*proto));
-     return true;
- }
-+
-+/* static */ bool
-+GlobalObject::initRegExpStringIteratorProto(JSContext* cx, Handle<GlobalObject*> global)
-+{
-+    if (global->getReservedSlot(REGEXP_STRING_ITERATOR_PROTO).isObject()) {
-+        return true;
-+    }
-+
-+    RootedObject iteratorProto(cx, GlobalObject::getOrCreateIteratorPrototype(cx, global));
-+    if (!iteratorProto) {
-+        return false;
-+    }
-+
-+    const Class* cls = &RegExpStringIteratorPrototypeClass;
-+    RootedObject proto(cx, GlobalObject::createBlankPrototypeInheriting(cx, global, cls,
-+                                                                        iteratorProto));
-+    if (!proto ||
-+        !DefinePropertiesAndFunctions(cx, proto, nullptr, regexp_string_iterator_methods) ||
-+        !DefineToStringTag(cx, proto, cx->names().RegExpStringIterator))
-+    {
-+        return false;
-+    }
-+
-+    global->setReservedSlot(REGEXP_STRING_ITERATOR_PROTO, ObjectValue(*proto));
-+    return true;
-+}
-diff --git a/js/src/jsiter.h b/js/src/jsiter.h
---- a/js/src/jsiter.h
-+++ b/js/src/jsiter.h
-@@ -153,16 +153,25 @@ JSObject*
- GetIterator(JSContext* cx, HandleObject obj);
- 
- PropertyIteratorObject*
- LookupInIteratorCache(JSContext* cx, HandleObject obj);
- 
- JSObject*
- EnumeratedIdVectorToIterator(JSContext* cx, HandleObject obj, AutoIdVector& props);
- 
-+class RegExpStringIteratorObject : public NativeObject
-+{
-+ public:
-+  static const Class class_;
-+};
-+
-+RegExpStringIteratorObject*
-+NewRegExpStringIteratorObject(JSContext* cx, NewObjectKind newKind = GenericObject);
-+
- JSObject*
- NewEmptyPropertyIterator(JSContext* cx);
- 
- JSObject*
- ValueToIterator(JSContext* cx, HandleValue vp);
- 
- void
- CloseIterator(JSObject* obj);
-diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp
---- a/js/src/jsstr.cpp
-+++ b/js/src/jsstr.cpp
-@@ -3580,16 +3580,17 @@ static const JSFunctionSpec string_metho
- #endif
-     JS_SELF_HOSTED_FN("repeat", "String_repeat",      1,0),
- #if JS_HAS_INTL_API
-     JS_FN("normalize",         str_normalize,         0,0),
- #endif
- 
-     /* Perl-ish methods (search is actually Python-esque). */
-     JS_SELF_HOSTED_FN("match", "String_match",        1,0),
-+    JS_SELF_HOSTED_FN("matchAll", "String_matchAll",  1,0),
-     JS_SELF_HOSTED_FN("search", "String_search",      1,0),
-     JS_SELF_HOSTED_FN("replace", "String_replace",    2,0),
-     JS_SELF_HOSTED_FN("replaceAll", "String_replaceAll", 2, 0),
-     JS_SELF_HOSTED_FN("split",  "String_split",       2,0),
-     JS_SELF_HOSTED_FN("substr", "String_substr",      2,0),
- 
-     /* Python-esque sequence methods. */
-     JS_FN("concat",            str_concat,            1,0),
-diff --git a/js/src/moz.build b/js/src/moz.build
---- a/js/src/moz.build
-+++ b/js/src/moz.build
-@@ -139,16 +139,18 @@ EXPORTS.js += [
-     '../public/LegacyIntTypes.h',
-     '../public/MemoryMetrics.h',
-     '../public/Principals.h',
-     '../public/ProfilingFrameIterator.h',
-     '../public/ProfilingStack.h',
-     '../public/Proxy.h',
-     '../public/Realm.h',
-     '../public/RefCounted.h',
-+    '../public/RegExp.h',
-+    '../public/RegExpFlags.h',
-     '../public/RequiredDefines.h',
-     '../public/Result.h',
-     '../public/RootingAPI.h',
-     '../public/SliceBudget.h',
-     '../public/Stream.h',
-     '../public/StructuredClone.h',
-     '../public/SweepingAPI.h',
-     '../public/TraceKind.h',
-@@ -163,16 +165,20 @@ EXPORTS.js += [
-     '../public/UbiNodeShortestPaths.h',
-     '../public/UniquePtr.h',
-     '../public/Utility.h',
-     '../public/Value.h',
-     '../public/Vector.h',
-     '../public/WeakMapPtr.h',
- ]
- 
-+SOURCES += [
-+    'util/Text.cpp',
-+]
-+
- UNIFIED_SOURCES += [
-     'builtin/AtomicsObject.cpp',
-     'builtin/DataViewObject.cpp',
-     'builtin/Eval.cpp',
-     'builtin/intl/Collator.cpp',
-     'builtin/intl/CommonFunctions.cpp',
-     'builtin/intl/DateTimeFormat.cpp',
-     'builtin/intl/IntlObject.cpp',
-@@ -192,24 +198,16 @@ UNIFIED_SOURCES += [
-     'builtin/Stream.cpp',
-     'builtin/SymbolObject.cpp',
-     'builtin/TestingFunctions.cpp',
-     'builtin/TypedObject.cpp',
-     'builtin/WeakMapObject.cpp',
-     'builtin/WeakSetObject.cpp',
-     'ds/Bitmap.cpp',
-     'ds/LifoAlloc.cpp',
--    'irregexp/NativeRegExpMacroAssembler.cpp',
--    'irregexp/RegExpAST.cpp',
--    'irregexp/RegExpCharacters.cpp',
--    'irregexp/RegExpEngine.cpp',
--    'irregexp/RegExpInterpreter.cpp',
--    'irregexp/RegExpMacroAssembler.cpp',
--    'irregexp/RegExpParser.cpp',
--    'irregexp/RegExpStack.cpp',
-     'jsalloc.cpp',
-     'jsapi.cpp',
-     'jsarray.cpp',
-     'jsbool.cpp',
-     'jsdate.cpp',
-     'jsexn.cpp',
-     'jsfriendapi.cpp',
-     'jsgc.cpp',
-@@ -375,23 +373,49 @@ if CONFIG['HAVE_LINUX_PERF_EVENT_H']:
-     ]
-     if CONFIG['LINUX_HEADERS_INCLUDES']:
-         SOURCES['perf/pm_linux.cpp'].flags += [CONFIG['LINUX_HEADERS_INCLUDES']]
- else:
-     SOURCES += [
-         'perf/pm_stub.cpp'
-     ]
- 
-+SOURCES += [
-+    'irregexp/imported/regexp-ast.cc',
-+    'irregexp/imported/regexp-bytecode-generator.cc',
-+    'irregexp/imported/regexp-bytecode-peephole.cc',
-+    'irregexp/imported/regexp-bytecodes.cc',
-+    'irregexp/imported/regexp-compiler-tonode.cc',
-+    'irregexp/imported/regexp-compiler.cc',
-+    'irregexp/imported/regexp-dotprinter.cc',
-+    'irregexp/imported/regexp-interpreter.cc',
-+    'irregexp/imported/regexp-macro-assembler-tracer.cc',
-+    'irregexp/imported/regexp-macro-assembler.cc',
-+    'irregexp/imported/regexp-parser.cc',
-+    'irregexp/imported/regexp-stack.cc',
-+    'irregexp/RegExpAPI.cpp',
-+    'irregexp/RegExpNativeMacroAssembler.cpp',
-+    'irregexp/RegExpShim.cpp',
-+    'irregexp/util/UnicodeShim.cpp'
-+]
-+
-+if CONFIG['JS_HAS_INTL_API']:
-+    CXXFLAGS += ['-DV8_INTL_SUPPORT']
-+    SOURCES += [
-+        'irregexp/imported/property-sequences.cc',
-+        'irregexp/imported/special-case.cc'
-+    ]
-+
- DIRS += [
-     'build',
-     'frontend',
-     'gc',
-     'jit',
-     'wasm',
--] + (['new-regexp'] if CONFIG['ENABLE_NEW_REGEXP'] else [])
-+]
- 
- FINAL_LIBRARY = 'js'
- 
- selfhosted_inputs = [
-     'js.msg',
-     'builtin/TypedObjectConstants.h',
-     'builtin/SelfHostingDefines.h',
-     'builtin/Utilities.js',
-diff --git a/js/src/moz.build.later b/js/src/moz.build.later
-new file mode 100644
---- /dev/null
-+++ b/js/src/moz.build.later
-@@ -0,0 +1,10 @@
-+--- js/src/moz.build
-++++ js/src/moz.build
-+@@ -114,6 +114,7 @@
-+     'frontend',
-+     'gc',
-+     'jit',
-++    'irregexp',
-+     'perf',
-+     'proxy',
-+     'threading',
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -70,19 +70,21 @@
- #include "builtin/TestingFunctions.h"
- #include "frontend/Parser.h"
- #include "gc/GCInternals.h"
- #include "jit/arm/Simulator-arm.h"
- #include "jit/InlinableNatives.h"
- #include "jit/Ion.h"
- #include "jit/JitcodeMap.h"
- #include "jit/OptimizationTracking.h"
-+#include "jit/OptimizationTracking.h"
- #include "js/Debug.h"
- #include "js/GCVector.h"
- #include "js/Initialization.h"
-+#include "js/RegExp.h"  // JS::ObjectIsRegExp
- #include "js/StructuredClone.h"
- #include "js/SweepingAPI.h"
- #include "js/TrackedOptimizationInfo.h"
- #include "perf/jsperf.h"
- #include "shell/jsoptparse.h"
- #include "shell/jsshell.h"
- #include "shell/OSObject.h"
- #include "threading/ConditionVariable.h"
-@@ -7128,17 +7130,17 @@ Help(JSContext* cx, unsigned argc, Value
-         JS_ReportErrorASCII(cx, "primitive arg");
-         return false;
-     }
- 
-     RootedObject obj(cx, &args[0].toObject());
-     if (!obj)
-         return true;
-     bool isRegexp;
--    if (!JS_ObjectIsRegExp(cx, obj, &isRegexp))
-+    if (!JS::ObjectIsRegExp(cx, obj, &isRegexp))
-         return false;
- 
-     if (isRegexp) {
-         // help(/pattern/)
-         return PrintEnumeratedHelp(cx, global, obj, false);
-     }
- 
-     // help(function)
-@@ -8258,16 +8260,21 @@ SetContextOptions(JSContext* cx, const O
-     int32_t warmUpThreshold = op.getIntOption("ion-warmup-threshold");
-     if (warmUpThreshold >= 0)
-         jit::JitOptions.setCompilerWarmUpThreshold(warmUpThreshold);
- 
-     warmUpThreshold = op.getIntOption("baseline-warmup-threshold");
-     if (warmUpThreshold >= 0)
-         jit::JitOptions.baselineWarmUpThreshold = warmUpThreshold;
- 
-+    warmUpThreshold = op.getIntOption("regexp-warmup-threshold");
-+    if (warmUpThreshold >= 0) {
-+        jit::JitOptions.regexpWarmUpThreshold = warmUpThreshold;
-+    }
-+
-     if (op.getBoolOption("baseline-eager"))
-         jit::JitOptions.baselineWarmUpThreshold = 0;
- 
-     if (const char* str = op.getStringOption("ion-regalloc")) {
-         jit::JitOptions.forcedRegisterAllocator = jit::LookupRegisterAllocator(str);
-         if (!jit::JitOptions.forcedRegisterAllocator.isSome())
-             return OptionFailure("ion-regalloc", str);
-     }
-@@ -8609,16 +8616,21 @@ main(int argc, char** argv, char** envp)
-         || !op.addBoolOption('\0', "no-ion", "Disable IonMonkey")
-         || !op.addBoolOption('\0', "no-asmjs", "Disable asm.js compilation")
-         || !op.addBoolOption('\0', "no-wasm", "Disable WebAssembly compilation")
-         || !op.addBoolOption('\0', "no-wasm-baseline", "Disable wasm baseline compiler")
-         || !op.addBoolOption('\0', "no-wasm-ion", "Disable wasm ion compiler")
-         || !op.addBoolOption('\0', "test-wasm-await-tier2", "Forcibly activate tiering and block "
-                                    "instantiation on completion of tier2")
-         || !op.addBoolOption('\0', "no-native-regexp", "Disable native regexp compilation")
-+        || !op.addIntOption(
-+          '\0', "regexp-warmup-threshold", "COUNT",
-+          "Wait for COUNT invocations before compiling regexps to native code "
-+          "(default 10)",
-+          -1)
-         || !op.addBoolOption('\0', "no-unboxed-objects", "Disable creating unboxed plain objects")
-         || !op.addBoolOption('\0', "enable-streams", "Enable WHATWG Streams")
- #ifdef ENABLE_SHARED_ARRAY_BUFFER
-         || !op.addStringOption('\0', "shared-memory", "on/off",
-                                "SharedArrayBuffer and Atomics "
- #  if SHARED_MEMORY_DEFAULT
-                                "(default: on, off to disable)"
- #  else
-diff --git a/js/src/tests/non262/RegExp/RegExpExec-exec-type-check.js b/js/src/tests/non262/RegExp/RegExpExec-exec-type-check.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/tests/non262/RegExp/RegExpExec-exec-type-check.js
-@@ -0,0 +1,12 @@
-+// Bug 1667094.
-+
-+var obj = {
-+  exec() {
-+    return function(){};
-+  }
-+};
-+
-+assertEq(RegExp.prototype.test.call(obj, ""), true);
-+
-+if (typeof reportCompare === "function")
-+    reportCompare(true, true);
-diff --git a/js/src/tests/non262/extensions/bad-regexp-data-clone.js b/js/src/tests/non262/extensions/bad-regexp-data-clone.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/tests/non262/extensions/bad-regexp-data-clone.js
-@@ -0,0 +1,20 @@
-+// |reftest| skip-if(!xulRuntime.shell)
-+// -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-+// Any copyright is dedicated to the Public Domain.
-+// http://creativecommons.org/licenses/publicdomain/
-+
-+let data = new Uint8Array([
-+  104,97,108,101,6,0,255,255,95,98,
-+  0,0,0,0,0,104,97,108,101,9,0,255,
-+  255,95,98,115,0,0,0,0,0,0,65,0,0,
-+  0,0,0,0,0,0,0,0,0,0,0,0,0
-+]);
-+let cloneBuffer = serialize(null);
-+cloneBuffer.clonebuffer = data.buffer;
-+
-+// One of the bytes above encodes a JS::RegExpFlags, but that byte contains bits
-+// outside of JS::RegExpFlag::AllFlags and so will trigger an error.
-+assertThrowsInstanceOf(() => deserialize(cloneBuffer), InternalError);
-+
-+if (typeof reportCompare === "function")
-+  reportCompare(0, 0, 'ok');
-diff --git a/js/src/util/Text.cpp b/js/src/util/Text.cpp
-new file mode 100644
---- /dev/null
-+++ b/js/src/util/Text.cpp
-@@ -0,0 +1,37 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * vim: set ts=8 sts=2 et sw=2 tw=80:
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#include "util/Text.h"
-+
-+#include "mozilla/Assertions.h"
-+#include "vm/Unicode.h"
-+
-+using namespace JS;
-+using namespace js;
-+
-+size_t
-+js::unicode::CountCodePoints(const char16_t* begin, const char16_t* end)
-+{
-+    MOZ_ASSERT(begin <= end);
-+
-+    size_t count = 0;
-+
-+    const char16_t* ptr = begin;
-+    while (ptr < end) {
-+        count++;
-+
-+        if (!IsLeadSurrogate(*ptr++)) {
-+            continue;
-+        }
-+
-+        if (ptr < end && IsTrailSurrogate(*ptr)) {
-+            ptr++;
-+        }
-+    }
-+    MOZ_ASSERT(ptr == end, "should have consumed the full range");
-+
-+    return count;
-+}
-diff --git a/js/src/util/Text.h b/js/src/util/Text.h
-new file mode 100644
---- /dev/null
-+++ b/js/src/util/Text.h
-@@ -0,0 +1,27 @@
-+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * vim: set ts=8 sts=2 et sw=2 tw=80:
-+ * This Source Code Form is subject to the terms of the Mozilla Public
-+ * License, v. 2.0. If a copy of the MPL was not distributed with this
-+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-+
-+#ifndef util_Text_h
-+#define util_Text_h
-+
-+#include <stddef.h>
-+
-+namespace js {
-+
-+namespace unicode {
-+/**
-+ * Count the number of code points in [begin, end].
-+ *
-+ * Every sequence of 16-bit units is considered valid.  Lone surrogates are
-+ * treated as if they represented a code point of the same value.
-+ */
-+extern size_t
-+CountCodePoints(const char16_t* begin, const char16_t* end);
-+} // namespace unicode
-+
-+} // namespace js
-+
-+#endif // util_Text_h
-diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
---- a/js/src/vm/CommonPropertyNames.h
-+++ b/js/src/vm/CommonPropertyNames.h
-@@ -98,16 +98,17 @@
-     macro(defineProperty, defineProperty, "defineProperty") \
-     macro(defineSetter, defineSetter, "__defineSetter__") \
-     macro(delete, delete_, "delete") \
-     macro(deleteProperty, deleteProperty, "deleteProperty") \
-     macro(direction, direction, "direction") \
-     macro(displayURL, displayURL, "displayURL") \
-     macro(do, do_, "do") \
-     macro(done, done, "done") \
-+    macro(dotAll, dotAll, "dotAll") \
-     macro(dotGenerator, dotGenerator, ".generator") \
-     macro(dotThis, dotThis, ".this") \
-     macro(each, each, "each") \
-     macro(elementType, elementType, "elementType") \
-     macro(else, else_, "else") \
-     macro(empty, empty, "") \
-     macro(emptyRegExp, emptyRegExp, "(?:)") \
-     macro(encodeURI, encodeURI, "encodeURI") \
-@@ -164,16 +165,17 @@
-     macro(getOwnPropertyNames, getOwnPropertyNames, "getOwnPropertyNames") \
-     macro(getPrefix, getPrefix, "get ") \
-     macro(getPropertyDescriptor, getPropertyDescriptor, "getPropertyDescriptor") \
-     macro(getPropertySuper, getPropertySuper, "getPropertySuper") \
-     macro(getPrototypeOf, getPrototypeOf, "getPrototypeOf") \
-     macro(global, global, "global") \
-     macro(globalThis, globalThis, "globalThis") \
-     macro(group, group, "group") \
-+    macro(groups, groups, "groups") \
-     macro(Handle, Handle, "Handle") \
-     macro(has, has, "has") \
-     macro(hasOwn, hasOwn, "hasOwn") \
-     macro(hasOwnProperty, hasOwnProperty, "hasOwnProperty") \
-     macro(highWaterMark, highWaterMark, "highWaterMark") \
-     macro(hour, hour, "hour") \
-     macro(if, if_, "if") \
-     macro(ignoreCase, ignoreCase, "ignoreCase") \
-@@ -342,16 +344,17 @@
-           ReadableStreamDefaultReader_read, \
-           "ReadableStreamDefaultReader_read") \
-     macro(ReadableStreamDefaultReader_releaseLock, \
-           ReadableStreamDefaultReader_releaseLock, \
-           "ReadableStreamDefaultReader_releaseLock") \
-     macro(ReadableStreamTee, ReadableStreamTee, "ReadableStreamTee") \
-     macro(reason, reason, "reason") \
-     macro(RegExpFlagsGetter, RegExpFlagsGetter, "RegExpFlagsGetter") \
-+    macro(RegExpStringIterator, RegExpStringIterator, "RegExp String Iterator") \
-     macro(Reify, Reify, "Reify") \
-     macro(reject, reject, "reject") \
-     macro(rejected, rejected, "rejected") \
-     macro(RelativeTimeFormat, RelativeTimeFormat, "RelativeTimeFormat") \
-     macro(RelativeTimeFormatFormat, RelativeTimeFormatFormat, "Intl_RelativeTimeFormat_Format") \
-     macro(RequireObjectCoercible, RequireObjectCoercible, "RequireObjectCoercible") \
-     macro(resolve, resolve, "resolve") \
-     macro(resumeGenerator, resumeGenerator, "resumeGenerator") \
-diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp
---- a/js/src/vm/GlobalObject.cpp
-+++ b/js/src/vm/GlobalObject.cpp
-@@ -525,73 +525,40 @@ GlobalObject::initSelfHostingBuiltins(JS
- {
-     // Define a top-level property 'undefined' with the undefined value.
-     if (!DefineDataProperty(cx, global, cx->names().undefined, UndefinedHandleValue,
-                             JSPROP_PERMANENT | JSPROP_READONLY))
-     {
-         return false;
-     }
- 
--    RootedValue std_isConcatSpreadable(cx);
--    std_isConcatSpreadable.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::isConcatSpreadable));
--    if (!JS_DefineProperty(cx, global, "std_isConcatSpreadable", std_isConcatSpreadable,
--                           JSPROP_PERMANENT | JSPROP_READONLY))
--    {
--        return false;
--    }
-+    struct SymbolAndName {
-+        JS::SymbolCode code;
-+        const char* name;
-+    };
- 
--    // Define a top-level property 'std_iterator' with the name of the method
--    // used by for-of loops to create an iterator.
--    RootedValue std_iterator(cx);
--    std_iterator.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::iterator));
--    if (!JS_DefineProperty(cx, global, "std_iterator", std_iterator,
--                           JSPROP_PERMANENT | JSPROP_READONLY))
--    {
--        return false;
--    }
-+  SymbolAndName wellKnownSymbols[] = {
-+      {JS::SymbolCode::isConcatSpreadable, "std_isConcatSpreadable"},
-+      {JS::SymbolCode::iterator, "std_iterator"},
-+      {JS::SymbolCode::match, "std_match"},
-+      {JS::SymbolCode::matchAll, "std_matchAll"},
-+      {JS::SymbolCode::replace, "std_replace"},
-+      {JS::SymbolCode::search, "std_search"},
-+      {JS::SymbolCode::species, "std_species"},
-+      {JS::SymbolCode::split, "std_split"},
-+  };
- 
--    RootedValue std_match(cx);
--    std_match.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::match));
--    if (!JS_DefineProperty(cx, global, "std_match", std_match,
--                           JSPROP_PERMANENT | JSPROP_READONLY))
--    {
-+  RootedValue symVal(cx);
-+  for (const auto& sym : wellKnownSymbols) {
-+    symVal.setSymbol(cx->wellKnownSymbols().get(sym.code));
-+    if (!JS_DefineProperty(cx, global, sym.name, symVal,
-+                           JSPROP_PERMANENT | JSPROP_READONLY)) {
-         return false;
-     }
--
--    RootedValue std_replace(cx);
--    std_replace.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::replace));
--    if (!JS_DefineProperty(cx, global, "std_replace", std_replace,
--                           JSPROP_PERMANENT | JSPROP_READONLY))
--    {
--        return false;
--    }
--
--    RootedValue std_search(cx);
--    std_search.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::search));
--    if (!JS_DefineProperty(cx, global, "std_search", std_search,
--                           JSPROP_PERMANENT | JSPROP_READONLY))
--    {
--        return false;
--    }
--
--    RootedValue std_species(cx);
--    std_species.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::species));
--    if (!JS_DefineProperty(cx, global, "std_species", std_species,
--                           JSPROP_PERMANENT | JSPROP_READONLY))
--    {
--        return false;
--    }
--
--    RootedValue std_split(cx);
--    std_split.setSymbol(cx->wellKnownSymbols().get(JS::SymbolCode::split));
--    if (!JS_DefineProperty(cx, global, "std_split", std_split,
--                           JSPROP_PERMANENT | JSPROP_READONLY))
--    {
--        return false;
--    }
-+  }
- 
-     return InitBareBuiltinCtor(cx, global, JSProto_Array) &&
-            InitBareBuiltinCtor(cx, global, JSProto_TypedArray) &&
-            InitBareBuiltinCtor(cx, global, JSProto_Uint8Array) &&
-            InitBareBuiltinCtor(cx, global, JSProto_Int32Array) &&
-            InitBareSymbolCtor(cx, global) &&
-            DefineFunctions(cx, global, builtins, AsIntrinsic);
- }
-diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h
---- a/js/src/vm/GlobalObject.h
-+++ b/js/src/vm/GlobalObject.h
-@@ -72,16 +72,17 @@ class GlobalObject : public NativeObject
-         THROWTYPEERROR,
- 
-         /* One-off properties stored after slots for built-ins. */
-         LEXICAL_ENVIRONMENT,
-         EMPTY_GLOBAL_SCOPE,
-         ITERATOR_PROTO,
-         ARRAY_ITERATOR_PROTO,
-         STRING_ITERATOR_PROTO,
-+        REGEXP_STRING_ITERATOR_PROTO,
-         GENERATOR_OBJECT_PROTO,
-         GENERATOR_FUNCTION_PROTO,
-         GENERATOR_FUNCTION,
-         ASYNC_FUNCTION_PROTO,
-         ASYNC_FUNCTION,
-         ASYNC_ITERATOR_PROTO,
-         ASYNC_FROM_SYNC_ITERATOR_PROTO,
-         ASYNC_GENERATOR,
-@@ -601,16 +602,22 @@ class GlobalObject : public NativeObject
- 
-     static NativeObject*
-     getOrCreateStringIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
-         return MaybeNativeObject(getOrCreateObject(cx, global, STRING_ITERATOR_PROTO,
-                                                    initStringIteratorProto));
-     }
- 
-     static NativeObject*
-+    getOrCreateRegExpStringIteratorPrototype(JSContext* cx, Handle<GlobalObject*> global) {
-+        return MaybeNativeObject(getOrCreateObject(cx, global, REGEXP_STRING_ITERATOR_PROTO,
-+                                               initRegExpStringIteratorProto));
-+    }
-+
-+    static NativeObject*
-     getOrCreateGeneratorObjectPrototype(JSContext* cx, Handle<GlobalObject*> global)
-     {
-         return MaybeNativeObject(getOrCreateObject(cx, global, GENERATOR_OBJECT_PROTO,
-                                                    initGenerators));
-     }
- 
-     static NativeObject*
-     getOrCreateGeneratorFunctionPrototype(JSContext* cx, Handle<GlobalObject*> global) {
-@@ -781,16 +788,17 @@ class GlobalObject : public NativeObject
- 
-     // Infallibly test whether the given value is the eval function for this global.
-     bool valueIsEval(const Value& val);
- 
-     // Implemented in jsiter.cpp.
-     static bool initIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
-     static bool initArrayIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
-     static bool initStringIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
-+    static bool initRegExpStringIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
- 
-     // Implemented in vm/GeneratorObject.cpp.
-     static bool initGenerators(JSContext* cx, Handle<GlobalObject*> global);
- 
-     static bool initAsyncFunction(JSContext* cx, Handle<GlobalObject*> global);
- 
-     static bool initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global);
- 
-diff --git a/js/src/vm/JSContext.cpp b/js/src/vm/JSContext.cpp
---- a/js/src/vm/JSContext.cpp
-+++ b/js/src/vm/JSContext.cpp
-@@ -36,16 +36,17 @@
- #include "jsprf.h"
- #include "jspubtd.h"
- #include "jsstr.h"
- #include "jstypes.h"
- #include "jswin.h"
- 
- #include "gc/FreeOp.h"
- #include "gc/Marking.h"
-+#include "irregexp/RegExpAPI.h"
- #include "jit/Ion.h"
- #include "jit/PcScriptCache.h"
- #include "js/CharacterEncoding.h"
- #include "vm/ErrorReporting.h"
- #include "vm/HelperThreads.h"
- #include "vm/JSAtom.h"
- #include "vm/JSCompartment.h"
- #include "vm/JSFunction.h"
-@@ -112,32 +113,34 @@ JSContext::init(ContextKind kind)
-         return false;
-         static_assert(sizeof(HANDLE) <= sizeof(threadNative_), "need bigger field");
-         threadNative_ = (size_t)self;
- #else
-         static_assert(sizeof(pthread_t) <= sizeof(threadNative_), "need bigger field");
-         threadNative_ = (size_t)pthread_self();
- #endif
- 
--        if (!regexpStack.ref().init())
--            return false;
--
-         if (!fx.initInstance())
-             return false;
- 
- #ifdef JS_SIMULATOR
-         simulator_ = js::jit::Simulator::Create(this);
-         if (!simulator_)
-             return false;
- #endif
- 
-         if (!wasm::EnsureSignalHandlers(this))
-             return false;
-     }
- 
-+    isolate = irregexp::CreateIsolate(this);
-+    if (!isolate) {
-+        return false;
-+    }
-+
-     // Set the ContextKind last, so that ProtectedData checks will allow us to
-     // initialize this context before it becomes the runtime's active context.
-     kind_ = kind;
- 
-     return true;
- }
- 
- JSContext*
-@@ -1347,16 +1350,20 @@ JSContext::~JSContext()
-     js::jit::Simulator::Destroy(simulator_);
- #endif
- 
- #ifdef JS_TRACE_LOGGING
-     if (traceLogger)
-         DestroyTraceLogger(traceLogger);
- #endif
- 
-+    if (isolate) {
-+      irregexp::DestroyIsolate(isolate.ref());
-+    }
-+
-     MOZ_ASSERT(TlsContext.get() == this);
-     TlsContext.set(nullptr);
- }
- 
- void
- JSContext::setRuntime(JSRuntime* rt)
- {
-     MOZ_ASSERT(!resolvingList);
-@@ -1478,25 +1485,25 @@ IsJITBrokenHere()
- }
- 
- void
- JSContext::updateJITEnabled()
- {
-     jitIsBroken = IsJITBrokenHere();
- }
- 
--size_t
--JSContext::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
--{
--    /*
--     * There are other JSContext members that could be measured; the following
--     * ones have been found by DMD to be worth measuring.  More stuff may be
--     * added later.
--     */
--    return cycleDetectorVector().sizeOfExcludingThis(mallocSizeOf);
-+size_t JSContext::sizeOfExcludingThis(
-+    mozilla::MallocSizeOf mallocSizeOf) const {
-+  /*
-+   * There are other JSContext members that could be measured; the following
-+   * ones have been found by DMD to be worth measuring.  More stuff may be
-+   * added later.
-+   */
-+  return cycleDetectorVector().sizeOfExcludingThis(mallocSizeOf) +
-+         irregexp::IsolateSizeOfIncludingThis(isolate, mallocSizeOf);
- }
- 
- void
- JSContext::trace(JSTracer* trc)
- {
-     cycleDetectorVector().trace(trc);
-     geckoProfiler().trace(trc);
- 
-diff --git a/js/src/vm/JSContext.h b/js/src/vm/JSContext.h
---- a/js/src/vm/JSContext.h
-+++ b/js/src/vm/JSContext.h
-@@ -6,16 +6,17 @@
- 
- /* JS execution context. */
- 
- #ifndef vm_JSContext_h
- #define vm_JSContext_h
- 
- #include "mozilla/MemoryReporting.h"
- 
-+#include "irregexp/RegExpTypes.h"
- #include "js/CharacterEncoding.h"
- #include "js/GCVector.h"
- #include "js/Result.h"
- #include "js/Utility.h"
- #include "js/Vector.h"
- #include "threading/ProtectedData.h"
- #include "vm/ErrorReporting.h"
- #include "vm/MallocProvider.h"
-@@ -335,18 +336,18 @@ struct JSContext : public JS::RootingCon
-     mozilla::GenericErrorResult<JS::Error&> alreadyReportedError();
- 
-     /*
-      * Points to the most recent JitActivation pushed on the thread.
-      * See JitActivation constructor in vm/Stack.cpp
-      */
-     js::ThreadData<js::jit::JitActivation*> jitActivation;
- 
--    // Information about the heap allocated backtrack stack used by RegExp JIT code.
--    js::ThreadData<js::irregexp::RegExpStack> regexpStack;
-+    // Shim for V8 interfaces used by irregexp code
-+    js::ThreadData<js::irregexp::Isolate*> isolate;
- 
-     /*
-      * Points to the most recent activation running on the thread.
-      * See Activation comment in vm/Stack.h.
-      */
-     js::ThreadData<js::Activation*> activation_;
- 
-     /*
-diff --git a/js/src/vm/MatchPairs.h b/js/src/vm/MatchPairs.h
---- a/js/src/vm/MatchPairs.h
-+++ b/js/src/vm/MatchPairs.h
-@@ -74,29 +74,29 @@ class MatchPairs
-     friend class RegExpStatics;
- 
-     /* MatchPair buffer allocator: set pairs_ and pairCount_. */
-     virtual bool allocOrExpandArray(size_t pairCount) = 0;
- 
-     bool initArrayFrom(MatchPairs& copyFrom);
-     void forgetArray() { pairs_ = nullptr; }
- 
-+  public:
-     void checkAgainst(size_t inputLength) {
- #ifdef DEBUG
-         for (size_t i = 0; i < pairCount_; i++) {
-             const MatchPair& p = (*this)[i];
-             MOZ_ASSERT(p.check());
-             if (p.isUndefined())
-                 continue;
-             MOZ_ASSERT(size_t(p.limit) <= inputLength);
-         }
- #endif
-     }
- 
--  public:
-     /* Querying functions in the style of RegExpStatics. */
-     bool   empty() const           { return pairCount_ == 0; }
-     size_t pairCount() const       { MOZ_ASSERT(pairCount_ > 0); return pairCount_; }
-     size_t parenCount() const      { return pairCount_ - 1; }
- 
-     static size_t offsetOfPairs() { return offsetof(MatchPairs, pairs_); }
-     static size_t offsetOfPairCount() { return offsetof(MatchPairs, pairCount_); }
- 
-diff --git a/js/src/vm/MutexIDs.h b/js/src/vm/MutexIDs.h
---- a/js/src/vm/MutexIDs.h
-+++ b/js/src/vm/MutexIDs.h
-@@ -50,16 +50,17 @@
-   _(WasmCompileTaskState,        500) \
-   _(WasmCodeStreamEnd,           500) \
-   _(WasmTailBytesPtr,            500) \
-   _(WasmStreamStatus,            500) \
-   _(SharedArrayGrow,             500) \
-   _(RuntimeScriptData,           500) \
-                                       \
-   _(IcuTimeZoneStateMutex,       600) \
-+  _(IrregexpLazyStatic,          600) \
-   _(ThreadId,                    600) \
-   _(WasmCodeSegmentMap,          600) \
-   _(TraceLoggerGraphState,       600) \
-   _(VTuneLock,                   600)
- 
- namespace js {
- namespace mutexid {
- 
-diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp
---- a/js/src/vm/RegExpObject.cpp
-+++ b/js/src/vm/RegExpObject.cpp
-@@ -11,49 +11,59 @@
- 
- #include "jshashutil.h"
- #include "jsstr.h"
- #ifdef DEBUG
- #include "jsutil.h"
- #endif
- 
- #include "builtin/RegExp.h"
-+#include "builtin/SelfHostingDefines.h"
- #include "frontend/TokenStream.h"
--#ifdef DEBUG
--#include "irregexp/RegExpBytecode.h"
--#endif
--#include "irregexp/RegExpParser.h"
-+#include "irregexp/RegExpAPI.h"
- #include "vm/MatchPairs.h"
- #include "vm/RegExpStatics.h"
- #include "vm/StringBuffer.h"
- #include "vm/TraceLogging.h"
- #ifdef DEBUG
- #include "vm/Unicode.h"
- #endif
- #include "vm/Xdr.h"
- 
- #include "vm/JSObject-inl.h"
- #include "vm/NativeObject-inl.h"
- #include "vm/Shape-inl.h"
- 
-+#include "js/RegExp.h"
-+#include "js/RegExpFlags.h"
-+
- using namespace js;
- 
- using mozilla::ArrayLength;
- using mozilla::DebugOnly;
- using mozilla::Maybe;
- using mozilla::PodCopy;
-+using JS::RegExpFlag;
-+using JS::RegExpFlags;
- using js::frontend::TokenStream;
- 
- using JS::AutoCheckCannotGC;
- 
--JS_STATIC_ASSERT(IgnoreCaseFlag == JSREG_FOLD);
--JS_STATIC_ASSERT(GlobalFlag == JSREG_GLOB);
--JS_STATIC_ASSERT(MultilineFlag == JSREG_MULTILINE);
--JS_STATIC_ASSERT(StickyFlag == JSREG_STICKY);
--JS_STATIC_ASSERT(UnicodeFlag == JSREG_UNICODE);
-+static_assert(RegExpFlag::Global == REGEXP_GLOBAL_FLAG,
-+              "self-hosted JS and /g flag bits must agree");
-+static_assert(RegExpFlag::IgnoreCase == REGEXP_IGNORECASE_FLAG,
-+              "self-hosted JS and /i flag bits must agree");
-+static_assert(RegExpFlag::Multiline == REGEXP_MULTILINE_FLAG,
-+              "self-hosted JS and /m flag bits must agree");
-+static_assert(RegExpFlag::DotAll == REGEXP_DOTALL_FLAG,
-+              "self-hosted JS and /s flag bits must agree");
-+static_assert(RegExpFlag::Unicode == REGEXP_UNICODE_FLAG,
-+              "self-hosted JS and /u flag bits must agree");
-+static_assert(RegExpFlag::Sticky == REGEXP_STICKY_FLAG,
-+              "self-hosted JS and /y flag bits must agree");
- 
- RegExpObject*
- js::RegExpAlloc(JSContext* cx, NewObjectKind newKind, HandleObject proto /* = nullptr */)
- {
-     Rooted<RegExpObject*> regexp(cx, NewObjectWithClassProto<RegExpObject>(cx, proto, newKind));
-     if (!regexp)
-         return nullptr;
- 
-@@ -120,36 +130,40 @@ RegExpObject::getShared(JSContext* cx, H
- {
-     if (regexp->hasShared())
-         return regexp->sharedRef();
- 
-     return createShared(cx, regexp);
- }
- 
- /* static */ bool
--RegExpObject::isOriginalFlagGetter(JSNative native, RegExpFlag* mask)
-+RegExpObject::isOriginalFlagGetter(JSNative native, RegExpFlags* mask)
- {
-   if (native == regexp_global) {
--      *mask = GlobalFlag;
-+      *mask = RegExpFlag::Global;
-       return true;
-   }
-   if (native == regexp_ignoreCase) {
--      *mask = IgnoreCaseFlag;
-+      *mask = RegExpFlag::IgnoreCase;
-       return true;
-   }
-   if (native == regexp_multiline) {
--      *mask = MultilineFlag;
-+      *mask = RegExpFlag::Multiline;
-       return true;
-   }
-   if (native == regexp_sticky) {
--      *mask = StickyFlag;
-+      *mask = RegExpFlag::Sticky;
-       return true;
-   }
-   if (native == regexp_unicode) {
--      *mask = UnicodeFlag;
-+      *mask = RegExpFlag::Unicode;
-+      return true;
-+  }
-+  if (native == regexp_dotAll) {
-+      *mask = RegExpFlag::DotAll;
-       return true;
-   }
- 
-   return false;
- }
- 
- /* static */ void
- RegExpObject::trace(JSTracer* trc, JSObject* obj)
-@@ -219,81 +233,81 @@ const Class RegExpObject::protoClass_ = 
-     js_Object_str,
-     JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
-     JS_NULL_CLASS_OPS,
-     &RegExpObjectClassSpec
- };
- 
- template<typename CharT>
- RegExpObject*
--RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
-+RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlags flags,
-                      frontend::TokenStreamAnyChars& tokenStream, LifoAlloc& alloc,
-                      NewObjectKind newKind)
- {
-     static_assert(mozilla::IsSame<CharT, char16_t>::value,
-                   "this code may need updating if/when CharT encodes UTF-8");
- 
-     RootedAtom source(cx, AtomizeChars(cx, chars, length));
-     if (!source)
-         return nullptr;
- 
-     return create(cx, source, flags, tokenStream, alloc, newKind);
- }
- 
- template RegExpObject*
--RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlag flags,
-+RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlags flags,
-                      frontend::TokenStreamAnyChars& tokenStream, LifoAlloc& alloc,
-                      NewObjectKind newKind);
- 
- template<typename CharT>
- RegExpObject*
--RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
-+RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlags flags,
-                      LifoAlloc& alloc, NewObjectKind newKind)
- {
-     static_assert(mozilla::IsSame<CharT, char16_t>::value,
-                   "this code may need updating if/when CharT encodes UTF-8");
- 
-     RootedAtom source(cx, AtomizeChars(cx, chars, length));
-     if (!source)
-         return nullptr;
- 
-     return create(cx, source, flags, alloc, newKind);
- }
- 
- template RegExpObject*
--RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlag flags,
-+RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlags flags,
-                      LifoAlloc& alloc, NewObjectKind newKind);
- 
- RegExpObject*
--RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags,
-+RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlags flags,
-                      frontend::TokenStreamAnyChars& tokenStream,
-                      LifoAlloc& alloc, NewObjectKind newKind)
- {
--    if (!irregexp::ParsePatternSyntax(tokenStream, alloc, source, flags & UnicodeFlag))
-+    if (!irregexp::CheckPatternSyntax(cx, tokenStream, source, flags)) {
-         return nullptr;
--
-+    }
-     Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, newKind));
-     if (!regexp)
-         return nullptr;
- 
-     regexp->initAndZeroLastIndex(source, flags, cx);
- 
-     return regexp;
- }
- 
- RegExpObject*
--RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlag flags, LifoAlloc& alloc,
-+RegExpObject::create(JSContext* cx, HandleAtom source, RegExpFlags flags, LifoAlloc& alloc,
-                      NewObjectKind newKind)
- {
-     CompileOptions dummyOptions(cx);
-     TokenStream dummyTokenStream(cx, dummyOptions, (const char16_t*) nullptr, 0, nullptr);
- 
--    if (!irregexp::ParsePatternSyntax(dummyTokenStream, alloc, source, flags & UnicodeFlag))
-+    if (!irregexp::CheckPatternSyntax(cx, dummyTokenStream, source, flags)) {
-         return nullptr;
--
-+    }
-     Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, newKind));
-     if (!regexp)
-         return nullptr;
- 
-     regexp->initAndZeroLastIndex(source, flags, cx);
- 
-     return regexp;
- }
-@@ -319,28 +333,28 @@ RegExpObject::assignInitialShape(JSConte
-     JS_STATIC_ASSERT(LAST_INDEX_SLOT == 0);
- 
-     /* The lastIndex property alone is writable but non-configurable. */
-     return NativeObject::addDataProperty(cx, self, cx->names().lastIndex, LAST_INDEX_SLOT,
-                                          JSPROP_PERMANENT);
- }
- 
- void
--RegExpObject::initIgnoringLastIndex(JSAtom* source, RegExpFlag flags)
-+RegExpObject::initIgnoringLastIndex(JSAtom* source, RegExpFlags flags)
- {
-     // If this is a re-initialization with an existing RegExpShared, 'flags'
-     // may not match getShared()->flags, so forget the RegExpShared.
-     sharedRef() = nullptr;
- 
-     setSource(source);
-     setFlags(flags);
- }
- 
- void
--RegExpObject::initAndZeroLastIndex(JSAtom* source, RegExpFlag flags, JSContext* cx)
-+RegExpObject::initAndZeroLastIndex(JSAtom* source, RegExpFlags flags, JSContext* cx)
- {
-     initIgnoringLastIndex(source, flags);
-     zeroLastIndex(cx);
- }
- 
- static MOZ_ALWAYS_INLINE bool
- IsLineTerminator(const JS::Latin1Char c)
- {
-@@ -519,416 +533,22 @@ RegExpObject::toString(JSContext* cx) co
-     if (ignoreCase() && !sb.append('i'))
-         return nullptr;
-     if (multiline() && !sb.append('m'))
-         return nullptr;
-     if (unicode() && !sb.append('u'))
-         return nullptr;
-     if (sticky() && !sb.append('y'))
-         return nullptr;
-+    if (dotAll() && !sb.append('s'))
-+        return nullptr;
- 
-     return sb.finishString();
- }
- 
--#ifdef DEBUG
--/* static */ bool
--RegExpShared::dumpBytecode(JSContext* cx, MutableHandleRegExpShared re, bool match_only,
--                           HandleLinearString input)
--{
--    CompilationMode mode = match_only ? MatchOnly : Normal;
--    if (!RegExpShared::compileIfNecessary(cx, re, input, mode, ForceByteCode))
--        return false;
--
--    const uint8_t* byteCode = re->compilation(mode, input->hasLatin1Chars()).byteCode;
--    const uint8_t* pc = byteCode;
--
--    auto Load32Aligned = [](const uint8_t* pc) -> int32_t {
--        MOZ_ASSERT((reinterpret_cast<uintptr_t>(pc) & 3) == 0);
--        return *reinterpret_cast<const int32_t*>(pc);
--    };
--
--    auto Load16Aligned = [](const uint8_t* pc) -> int32_t {
--        MOZ_ASSERT((reinterpret_cast<uintptr_t>(pc) & 1) == 0);
--        return *reinterpret_cast<const uint16_t*>(pc);
--    };
--
--    int32_t numRegisters = Load32Aligned(pc);
--    fprintf(stderr, "numRegisters: %d\n", numRegisters);
--    pc += 4;
--
--    fprintf(stderr, "loc     op\n");
--    fprintf(stderr, "-----   --\n");
--
--    auto DumpLower = [](const char* text) {
--        while (*text) {
--            fprintf(stderr, "%c", unicode::ToLowerCase(*text));
--            text++;
--        }
--    };
--
--#define BYTECODE(NAME) \
--    case irregexp::BC_##NAME: \
--      DumpLower(#NAME);
--#define ADVANCE(NAME) \
--    fprintf(stderr, "\n"); \
--    pc += irregexp::BC_##NAME##_LENGTH; \
--    maxPc = js::Max(maxPc, pc); \
--    break;
--#define STOP(NAME) \
--    fprintf(stderr, "\n"); \
--    pc += irregexp::BC_##NAME##_LENGTH; \
--    break;
--#define JUMP(NAME, OFFSET) \
--    fprintf(stderr, "\n"); \
--    maxPc = js::Max(maxPc, byteCode + OFFSET); \
--    pc += irregexp::BC_##NAME##_LENGTH; \
--    break;
--#define BRANCH(NAME, OFFSET) \
--    fprintf(stderr, "\n"); \
--    pc += irregexp::BC_##NAME##_LENGTH; \
--    maxPc = js::Max(maxPc, js::Max(pc, byteCode + OFFSET)); \
--    break;
--
--    // Bytecode has no end marker, we need to calculate the bytecode length by
--    // tracing jumps and branches.
--    const uint8_t* maxPc = pc;
--    while (pc <= maxPc) {
--        fprintf(stderr, "%05d:  ", int32_t(pc - byteCode));
--        int32_t insn = Load32Aligned(pc);
--        switch (insn & irregexp::BYTECODE_MASK) {
--          BYTECODE(BREAK) {
--            STOP(BREAK);
--          }
--          BYTECODE(PUSH_CP) {
--            ADVANCE(PUSH_CP);
--          }
--          BYTECODE(PUSH_BT) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d",
--                    offset);
--            // Pushed value is used by POP_BT for jumping.
--            // Resolve maxPc here.
--            BRANCH(PUSH_BT, offset);
--          }
--          BYTECODE(PUSH_REGISTER) {
--            fprintf(stderr, " reg[%d]",
--                    insn >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(PUSH_REGISTER);
--          }
--          BYTECODE(SET_REGISTER) {
--            fprintf(stderr, " reg[%d], %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load32Aligned(pc + 4));
--            ADVANCE(SET_REGISTER);
--          }
--          BYTECODE(ADVANCE_REGISTER) {
--            fprintf(stderr, " reg[%d], %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load32Aligned(pc + 4));
--            ADVANCE(ADVANCE_REGISTER);
--          }
--          BYTECODE(SET_REGISTER_TO_CP) {
--            fprintf(stderr, " reg[%d], %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load32Aligned(pc + 4));
--            ADVANCE(SET_REGISTER_TO_CP);
--          }
--          BYTECODE(SET_CP_TO_REGISTER) {
--            fprintf(stderr, " reg[%d]",
--                    insn >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(SET_CP_TO_REGISTER);
--          }
--          BYTECODE(SET_REGISTER_TO_SP) {
--            fprintf(stderr, " reg[%d]",
--                    insn >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(SET_REGISTER_TO_SP);
--          }
--          BYTECODE(SET_SP_TO_REGISTER) {
--            fprintf(stderr, " reg[%d]",
--                    insn >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(SET_SP_TO_REGISTER);
--          }
--          BYTECODE(POP_CP) {
--            ADVANCE(POP_CP);
--          }
--          BYTECODE(POP_BT) {
--            // Jump is already resolved in PUSH_BT.
--            STOP(POP_BT);
--          }
--          BYTECODE(POP_REGISTER) {
--            fprintf(stderr, " reg[%d]",
--                    insn >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(POP_REGISTER);
--          }
--          BYTECODE(FAIL) {
--            ADVANCE(FAIL);
--          }
--          BYTECODE(SUCCEED) {
--            ADVANCE(SUCCEED);
--          }
--          BYTECODE(ADVANCE_CP) {
--            fprintf(stderr, " %d",
--                    insn >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(ADVANCE_CP);
--          }
--          BYTECODE(GOTO) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d",
--                    offset);
--            JUMP(GOTO, offset);
--          }
--          BYTECODE(ADVANCE_CP_AND_GOTO) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            JUMP(ADVANCE_CP_AND_GOTO, offset);
--          }
--          BYTECODE(CHECK_GREEDY) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d",
--                    offset);
--            BRANCH(CHECK_GREEDY, offset);
--          }
--          BYTECODE(LOAD_CURRENT_CHAR) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(LOAD_CURRENT_CHAR, offset);
--          }
--          BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
--            fprintf(stderr, " %d",
--                    insn >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(LOAD_CURRENT_CHAR_UNCHECKED);
--          }
--          BYTECODE(LOAD_2_CURRENT_CHARS) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(LOAD_2_CURRENT_CHARS, offset);
--          }
--          BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
--            fprintf(stderr, " %d",
--                    insn >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(LOAD_2_CURRENT_CHARS_UNCHECKED);
--          }
--          BYTECODE(LOAD_4_CURRENT_CHARS) {
--            ADVANCE(LOAD_4_CURRENT_CHARS);
--          }
--          BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
--            ADVANCE(LOAD_4_CURRENT_CHARS_UNCHECKED);
--          }
--          BYTECODE(CHECK_4_CHARS) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " %d, %d",
--                    Load32Aligned(pc + 4),
--                    offset);
--            BRANCH(CHECK_4_CHARS, offset);
--          }
--          BYTECODE(CHECK_CHAR) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(CHECK_CHAR, offset);
--          }
--          BYTECODE(CHECK_NOT_4_CHARS) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " %d, %d",
--                    Load32Aligned(pc + 4),
--                    offset);
--            BRANCH(CHECK_NOT_4_CHARS, offset);
--          }
--          BYTECODE(CHECK_NOT_CHAR) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(CHECK_NOT_CHAR, offset);
--          }
--          BYTECODE(AND_CHECK_4_CHARS) {
--            int32_t offset = Load32Aligned(pc + 12);
--            fprintf(stderr, " %d, %d, %d",
--                    Load32Aligned(pc + 4),
--                    Load32Aligned(pc + 8),
--                    offset);
--            BRANCH(AND_CHECK_4_CHARS, offset);
--          }
--          BYTECODE(AND_CHECK_CHAR) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " %d, %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load32Aligned(pc + 4),
--                    offset);
--            BRANCH(AND_CHECK_CHAR, offset);
--          }
--          BYTECODE(AND_CHECK_NOT_4_CHARS) {
--            int32_t offset = Load32Aligned(pc + 12);
--            fprintf(stderr, " %d, %d, %d",
--                    Load32Aligned(pc + 4),
--                    Load32Aligned(pc + 8),
--                    offset);
--            BRANCH(AND_CHECK_NOT_4_CHARS, offset);
--          }
--          BYTECODE(AND_CHECK_NOT_CHAR) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " %d, %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load32Aligned(pc + 4),
--                    offset);
--            BRANCH(AND_CHECK_NOT_CHAR, offset);
--          }
--          BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " %d, %d, %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load16Aligned(pc + 4),
--                    Load16Aligned(pc + 6),
--                    offset);
--            BRANCH(MINUS_AND_CHECK_NOT_CHAR, offset);
--          }
--          BYTECODE(CHECK_CHAR_IN_RANGE) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " %d, %d, %d",
--                    Load16Aligned(pc + 4),
--                    Load16Aligned(pc + 6),
--                    offset);
--            BRANCH(CHECK_CHAR_IN_RANGE, offset);
--          }
--          BYTECODE(CHECK_CHAR_NOT_IN_RANGE) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " %d, %d, %d",
--                    Load16Aligned(pc + 4),
--                    Load16Aligned(pc + 6),
--                    offset);
--            BRANCH(CHECK_CHAR_NOT_IN_RANGE, offset);
--          }
--          BYTECODE(CHECK_BIT_IN_TABLE) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d, "
--                    "%02x %02x %02x %02x %02x %02x %02x %02x "
--                    "%02x %02x %02x %02x %02x %02x %02x %02x",
--                    offset,
--                    pc[8], pc[9], pc[10], pc[11],
--                    pc[12], pc[13], pc[14], pc[15],
--                    pc[16], pc[17], pc[18], pc[19],
--                    pc[20], pc[21], pc[22], pc[23]);
--            BRANCH(CHECK_BIT_IN_TABLE, offset);
--          }
--          BYTECODE(CHECK_LT) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(CHECK_LT, offset);
--          }
--          BYTECODE(CHECK_GT) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(CHECK_GT, offset);
--          }
--          BYTECODE(CHECK_REGISTER_LT) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " reg[%d], %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load32Aligned(pc + 4),
--                    offset);
--            BRANCH(CHECK_REGISTER_LT, offset);
--          }
--          BYTECODE(CHECK_REGISTER_GE) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " reg[%d], %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load32Aligned(pc + 4),
--                    offset);
--            BRANCH(CHECK_REGISTER_GE, offset);
--          }
--          BYTECODE(CHECK_REGISTER_EQ_POS) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " reg[%d], %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(CHECK_REGISTER_EQ_POS, offset);
--          }
--          BYTECODE(CHECK_NOT_REGS_EQUAL) {
--            int32_t offset = Load32Aligned(pc + 8);
--            fprintf(stderr, " reg[%d], %d, %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    Load32Aligned(pc + 4),
--                    offset);
--            BRANCH(CHECK_NOT_REGS_EQUAL, offset);
--          }
--          BYTECODE(CHECK_NOT_BACK_REF) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " reg[%d], %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(CHECK_NOT_BACK_REF, offset);
--          }
--          BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " reg[%d], %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(CHECK_NOT_BACK_REF_NO_CASE, offset);
--          }
--          BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " reg[%d], %d",
--                    insn >> irregexp::BYTECODE_SHIFT,
--                    offset);
--            BRANCH(CHECK_NOT_BACK_REF_NO_CASE_UNICODE, offset);
--          }
--          BYTECODE(CHECK_AT_START) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d",
--                    offset);
--            BRANCH(CHECK_AT_START, offset);
--          }
--          BYTECODE(CHECK_NOT_AT_START) {
--            int32_t offset = Load32Aligned(pc + 4);
--            fprintf(stderr, " %d",
--                    offset);
--            BRANCH(CHECK_NOT_AT_START, offset);
--          }
--          BYTECODE(SET_CURRENT_POSITION_FROM_END) {
--            fprintf(stderr, " %u",
--                    static_cast<uint32_t>(insn) >> irregexp::BYTECODE_SHIFT);
--            ADVANCE(SET_CURRENT_POSITION_FROM_END);
--          }
--          default:
--            MOZ_CRASH("Bad bytecode");
--        }
--    }
--
--#undef BYTECODE
--#undef ADVANCE
--#undef STOP
--#undef JUMP
--#undef BRANCH
--
--    return true;
--}
--
--/* static */ bool
--RegExpObject::dumpBytecode(JSContext* cx, Handle<RegExpObject*> regexp,
--                           bool match_only, HandleLinearString input)
--{
--    RootedRegExpShared shared(cx, getShared(cx, regexp));
--    if (!shared)
--        return false;
--
--    return RegExpShared::dumpBytecode(cx, &shared, match_only, input);
--}
--#endif
--
- template <typename CharT>
- static MOZ_ALWAYS_INLINE bool
- IsRegExpMetaChar(CharT ch)
- {
-     switch (ch) {
-       /* ES 2016 draft Mar 25, 2016 21.2.1 SyntaxCharacter. */
-       case '^': case '$': case '\\': case '.': case '*': case '+':
-       case '?': case '(': case ')': case '[': case ']': case '{':
-@@ -963,257 +583,331 @@ js::StringHasRegExpMetaChars(JSLinearStr
-     if (str->hasLatin1Chars())
-         return HasRegExpMetaChars(str->latin1Chars(nogc), str->length());
- 
-     return HasRegExpMetaChars(str->twoByteChars(nogc), str->length());
- }
- 
- /* RegExpShared */
- 
--RegExpShared::RegExpShared(JSAtom* source, RegExpFlag flags)
--  : source(source), flags(flags), canStringMatch(false), parenCount(0)
-+RegExpShared::RegExpShared(JSAtom* source, RegExpFlags flags)
-+  : source(source)
-+  , flags(flags)
-+  , pairCount_(0)
- {}
- 
- void
- RegExpShared::traceChildren(JSTracer* trc)
- {
-     // Discard code to avoid holding onto ExecutablePools.
-     if (IsMarkingTrace(trc) && trc->runtime()->gc.isShrinkingGC())
-         discardJitCode();
- 
-     TraceNullableEdge(trc, &source, "RegExpShared source");
--    for (auto& comp : compilationArray)
--        TraceNullableEdge(trc, &comp.jitCode, "RegExpShared code");
-+    if (kind() == RegExpShared::Kind::Atom) {
-+        TraceNullableEdge(trc, &patternAtom_, "RegExpShared pattern atom");
-+    } else {
-+        for (auto& comp : compilationArray) {
-+            TraceNullableEdge(trc, &comp.jitCode, "RegExpShared code");
-+        }
-+        TraceNullableEdge(trc, &groupsTemplate_, "RegExpShared groups template");
-+    }
- }
- 
- void
- RegExpShared::discardJitCode()
- {
-     for (auto& comp : compilationArray)
-         comp.jitCode = nullptr;
- 
-     // We can also purge the tables used by JIT code.
-     tables.clearAndFree();
- }
- 
-+
- void
- RegExpShared::finalize(FreeOp* fop)
- {
--    for (auto& comp : compilationArray)
--        js_free(comp.byteCode);
-+    for (auto& comp : compilationArray) {
-+        if (comp.byteCode) {
-+            js_free(comp.byteCode);
-+        }
-+    }
-+    if (namedCaptureIndices_) {
-+        js_free(namedCaptureIndices_);
-+    }
-     tables.~JitCodeTables();
- }
- 
--/* static */ bool
--RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleLinearString input,
--                      CompilationMode mode, ForceByteCodeEnum force)
-+/* static */
-+bool
-+RegExpShared::compileIfNecessary(JSContext* cx,
-+                                 MutableHandleRegExpShared re,
-+                                 HandleLinearString input,
-+                                 RegExpShared::CodeKind codeKind)
- {
--    TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
--    AutoTraceLog logCompile(logger, TraceLogger_IrregexpCompile);
-+  if (codeKind == RegExpShared::CodeKind::Any) {
-+    // We start by interpreting regexps, then compile them once they are
-+    // sufficiently hot. For very long input strings, we tier up eagerly.
-+    codeKind = RegExpShared::CodeKind::Bytecode;
-+    if (re->markedForTierUp(cx) || input->length() > 1000) {
-+      codeKind = RegExpShared::CodeKind::Jitcode;
-+    }
-+  }
-+
-+  // Fall back to bytecode if native codegen is not available.
-+  if (!IsNativeRegExpEnabled(cx) && codeKind == RegExpShared::CodeKind::Jitcode) {
-+    codeKind = RegExpShared::CodeKind::Bytecode;
-+  }
- 
--    RootedAtom pattern(cx, re->source);
--    return compile(cx, re, pattern, input, mode, force);
-+  bool needsCompile = false;
-+  if (re->kind() == RegExpShared::Kind::Unparsed) {
-+    needsCompile = true;
-+  }
-+
-+  if (re->kind() == RegExpShared::Kind::RegExp) {
-+    if (!re->isCompiled(input->hasLatin1Chars(), codeKind)) {
-+      needsCompile = true;
-+    }
-+  }
-+
-+  if (needsCompile) {
-+    return irregexp::CompilePattern(cx, re, input, codeKind);
-+  }
-+  return true;
- }
- 
--/* static */ bool
--RegExpShared::compile(JSContext* cx, MutableHandleRegExpShared re, HandleAtom pattern,
--                      HandleLinearString input, CompilationMode mode, ForceByteCodeEnum force)
-+/* static */
-+RegExpRunStatus
-+RegExpShared::execute(JSContext* cx,
-+                      MutableHandleRegExpShared re,
-+                      HandleLinearString input,
-+                      size_t start,
-+                      MatchPairs* matches)
- {
--    if (!re->ignoreCase() && !StringHasRegExpMetaChars(pattern))
--        re->canStringMatch = true;
--
--    CompileOptions options(cx);
--    frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
-+    MOZ_ASSERT(matches);
- 
--    LifoAllocScope scope(&cx->tempLifoAlloc());
-+    // TODO: Add tracelogger support
- 
--    /* Parse the pattern. */
--    irregexp::RegExpCompileData data;
--    if (!irregexp::ParsePattern(dummyTokenStream, cx->tempLifoAlloc(), pattern,
--                                re->multiline(), mode == MatchOnly, re->unicode(),
--                                re->ignoreCase(), re->global(), re->sticky(), &data))
--    {
--        return false;
-+    /* Compile the code at point-of-use. */
-+    if (!compileIfNecessary(cx, re, input, RegExpShared::CodeKind::Any)) {
-+        return RegExpRunStatus_Error;
-     }
- 
--    re->parenCount = data.capture_count;
--
--    JitCodeTables tables;
--    irregexp::RegExpCode code = irregexp::CompilePattern(cx, re, &data, input,
--                                                         false /* global() */,
--                                                         re->ignoreCase(),
--                                                         input->hasLatin1Chars(),
--                                                         mode == MatchOnly,
--                                                         force == ForceByteCode,
--                                                         re->sticky(),
--                                                         re->unicode(),
--                                                         tables);
--    if (code.empty())
--        return false;
--
--    MOZ_ASSERT(!code.jitCode || !code.byteCode);
--    MOZ_ASSERT_IF(force == ForceByteCode, code.byteCode);
--
--    RegExpCompilation& compilation = re->compilation(mode, input->hasLatin1Chars());
--    if (code.jitCode) {
--        // First copy the tables. GC can purge the tables if the RegExpShared
--        // has no JIT code, so it's important to do this right before setting
--        // compilation.jitCode (to ensure no purging happens between adding the
--        // tables and setting the JIT code).
--        for (size_t i = 0; i < tables.length(); i++) {
--            if (!re->addTable(std::move(tables[i]))) {
--                ReportOutOfMemory(cx);
--                return false;
--            }
--        }
--        compilation.jitCode = code.jitCode;
--    } else if (code.byteCode) {
--        MOZ_ASSERT(tables.empty(), "RegExpInterpreter does not use data tables");
--        compilation.byteCode = code.byteCode;
-+    /*
-+     * Ensure sufficient memory for output vector.
-+     * No need to initialize it. The RegExp engine fills them in on a match.
-+     */
-+    if (!matches->allocOrExpandArray(re->pairCount())) {
-+        ReportOutOfMemory(cx);
-+        return RegExpRunStatus_Error;
-     }
- 
--    return true;
--}
--
--/* static */ bool
--RegExpShared::compileIfNecessary(JSContext* cx, MutableHandleRegExpShared re,
--                                 HandleLinearString input, CompilationMode mode,
--                                 ForceByteCodeEnum force)
--{
--    if (re->isCompiled(mode, input->hasLatin1Chars(), force))
--        return true;
--    return compile(cx, re, input, mode, force);
--}
--
--/* static */ RegExpRunStatus
--RegExpShared::execute(JSContext* cx, MutableHandleRegExpShared re, HandleLinearString input,
--                      size_t start, MatchPairs* matches, size_t* endIndex)
--{
--    MOZ_ASSERT_IF(matches, !endIndex);
--    MOZ_ASSERT_IF(!matches, endIndex);
--    TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
--
--    CompilationMode mode = matches ? Normal : MatchOnly;
--
--    /* Compile the code at point-of-use. */
--    if (!compileIfNecessary(cx, re, input, mode, DontForceByteCode))
--        return RegExpRunStatus_Error;
-+    if (re->kind() == RegExpShared::Kind::Atom) {
-+        return RegExpShared::executeAtom(re, input, start, matches);
-+    }
- 
-     /*
-      * Ensure sufficient memory for output vector.
-      * No need to initialize it. The RegExp engine fills them in on a match.
-      */
--    if (matches && !matches->allocOrExpandArray(re->pairCount())) {
-+    if (!matches->allocOrExpandArray(re->pairCount())) {
-         ReportOutOfMemory(cx);
-         return RegExpRunStatus_Error;
-     }
- 
--    size_t length = input->length();
--
--    // Reset the Irregexp backtrack stack if it grows during execution.
--    irregexp::RegExpStackScope stackScope(cx);
-+    uint32_t interruptRetries = 0;
-+    const uint32_t maxInterruptRetries = 4;
-+    do {
-+        RegExpRunStatus result = irregexp::Execute(cx, re, input, start, matches);
- 
--    if (re->canStringMatch) {
--        MOZ_ASSERT(re->pairCount() == 1);
--        size_t sourceLength = re->source->length();
--        if (re->sticky()) {
--            // First part checks size_t overflow.
--            if (sourceLength + start < sourceLength || sourceLength + start > length)
--                return RegExpRunStatus_Success_NotFound;
--            if (!HasSubstringAt(input, re->source, start))
--                return RegExpRunStatus_Success_NotFound;
--
--            if (matches) {
--                (*matches)[0].start = start;
--                (*matches)[0].limit = start + sourceLength;
--
--                matches->checkAgainst(length);
--            } else if (endIndex) {
--                *endIndex = start + sourceLength;
-+        if (result == RegExpRunStatus_Error) {
-+          /* Execute can return RegExpRunStatus_Error:
-+           *
-+           *  1. If the native stack overflowed
-+           *  2. If the backtrack stack overflowed
-+           *  3. If an interrupt was requested during execution.
-+           *
-+           * In the first two cases, we want to throw an error. In the
-+           * third case, we want to handle the interrupt and try again.
-+           * We cap the number of times we will retry.
-+           */
-+          if (cx->hasPendingInterrupt()) {
-+            if (!CheckForInterrupt(cx)) {
-+              return RegExpRunStatus_Error;
-             }
--            return RegExpRunStatus_Success;
-+            if (interruptRetries++ < maxInterruptRetries) {
-+              // The initial execution may have been interpreted, or the
-+              // interrupt may have triggered a GC that discarded jitcode.
-+              // To maximize the chance of succeeding before being
-+              // interrupted again, we want to ensure we are compiled.
-+              if (!compileIfNecessary(cx, re, input,
-+                                      RegExpShared::CodeKind::Jitcode)) {
-+                return RegExpRunStatus_Error;
-+              }
-+              continue;
-+            }
-+          }
-+          // If we have run out of retries, this regexp takes too long to
-+          // execute.
-+          ReportOverRecursed(cx);
-+          return RegExpRunStatus_Error;
-         }
- 
--        int res = StringFindPattern(input, re->source, start);
--        if (res == -1)
--            return RegExpRunStatus_Success_NotFound;
-+        MOZ_ASSERT(result == RegExpRunStatus_Success ||
-+                   result == RegExpRunStatus_Success_NotFound);
-+
-+        return result;
-+    } while (true);
-+
-+    MOZ_CRASH("Unreachable");
-+}
-+
-+void RegExpShared::useAtomMatch(HandleAtom pattern) {
-+  MOZ_ASSERT(kind() == RegExpShared::Kind::Unparsed);
-+  kind_ = RegExpShared::Kind::Atom;
-+  patternAtom_ = pattern;
-+  pairCount_ = 1;
-+}
-+
-+void RegExpShared::useRegExpMatch(size_t pairCount) {
-+  MOZ_ASSERT(kind() == RegExpShared::Kind::Unparsed);
-+  kind_ = RegExpShared::Kind::RegExp;
-+  pairCount_ = pairCount;
-+  ticks_ = jit::JitOptions.regexpWarmUpThreshold;
-+}
-+
-+/* static */
-+bool
-+RegExpShared::initializeNamedCaptures(JSContext* cx,
-+                                      HandleRegExpShared re,
-+                                      HandleNativeObject namedCaptures)
-+{
-+    MOZ_ASSERT(!re->groupsTemplate_);
-+    MOZ_ASSERT(!re->namedCaptureIndices_);
-+
-+    // The irregexp parser returns named capture information in the form
-+    // of an ArrayObject, where even elements store the capture name and
-+    // odd elements store the corresponding capture index. We create a
-+    // template object with a property for each capture name, and store
-+    // the capture indices as a heap-allocated array.
-+    MOZ_ASSERT(namedCaptures->getDenseInitializedLength() % 2 == 0);
-+    uint32_t numNamedCaptures = namedCaptures->getDenseInitializedLength() / 2;
-+
-+    // Create a plain template object.
-+    RootedPlainObject templateObject(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr, TenuredObject));
-+    if (!templateObject) {
-+        return false;
-+    }
-+
-+    // Create a new group for the template.
-+    Rooted<TaggedProto> proto(cx, templateObject->taggedProto());
-+    ObjectGroup* group =
-+      ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto);
-+    if (!group) {
-+        return false;
-+    }
-+    templateObject->setGroup(group);
- 
--        if (matches) {
--            (*matches)[0].start = res;
--            (*matches)[0].limit = res + sourceLength;
-+    // Initialize the properties of the template.
-+    RootedId id(cx);
-+    RootedValue dummyString(cx, StringValue(cx->runtime()->emptyString));
-+    for (uint32_t i = 0; i < numNamedCaptures; i++) {
-+        JSString* name = namedCaptures->getDenseElement(i * 2).toString();
-+        id = NameToId(name->asAtom().asPropertyName());
-+        if (!NativeDefineDataProperty(cx, templateObject, id, dummyString,
-+                                      JSPROP_ENUMERATE)) {
-+          return false;
-+        }
-+        AddTypePropertyId(cx, templateObject, id, UndefinedValue());
-+    }
-+
-+    // Allocate the capture index array.
-+    uint32_t arraySize = numNamedCaptures * sizeof(uint32_t);
-+    uint32_t* captureIndices = static_cast<uint32_t*>(js_malloc(arraySize));
-+    if (!captureIndices) {
-+        ReportOutOfMemory(cx);
-+        return false;
-+    }
-+
-+    // Populate the capture index array
-+    for (uint32_t i = 0; i < numNamedCaptures; i++) {
-+        captureIndices[i] = namedCaptures->getDenseElement(i * 2 + 1).toInt32();
-+    }
-+
-+    re->numNamedCaptures_ = numNamedCaptures;
-+    re->groupsTemplate_ = templateObject;
-+    re->namedCaptureIndices_ = captureIndices;
-+    // js::AddCellMemory(re, arraySize, MemoryUse::RegExpSharedNamedCaptureData);
-+    return true;
-+}
- 
--            matches->checkAgainst(length);
--        } else if (endIndex) {
--            *endIndex = res + sourceLength;
-+void RegExpShared::tierUpTick() {
-+  MOZ_ASSERT(kind() == RegExpShared::Kind::RegExp);
-+  if (ticks_ > 0) {
-+    ticks_--;
-+  }
-+}
-+
-+bool RegExpShared::markedForTierUp(JSContext* cx) const {
-+  if (!IsNativeRegExpEnabled(cx)) {
-+    return false;
-+  }
-+  if (kind() != RegExpShared::Kind::RegExp) {
-+    return false;
-+  }
-+  return ticks_ == 0;
-+}
-+
-+/* static */
-+RegExpRunStatus ExecuteAtomImpl(RegExpShared* re, JSLinearString* input,
-+                                size_t start, MatchPairs* matches)
-+{
-+    MOZ_ASSERT(re->pairCount() == 1);
-+    size_t length = input->length();
-+    size_t searchLength = re->patternAtom()->length();
-+
-+    if (re->sticky()) {
-+        // First part checks size_t overflow.
-+        if (searchLength + start < searchLength || searchLength + start > length) {
-+            return RegExpRunStatus_Success_NotFound;
-         }
-+        if (!HasSubstringAt(input, re->patternAtom(), start)) {
-+            return RegExpRunStatus_Success_NotFound;
-+        }
-+
-+        (*matches)[0].start = start;
-+        (*matches)[0].limit = start + searchLength;
-+        matches->checkAgainst(input->length());
-         return RegExpRunStatus_Success;
-     }
- 
--    do {
--        jit::JitCode* code = re->compilation(mode, input->hasLatin1Chars()).jitCode;
--        if (!code)
--            break;
--
--        RegExpRunStatus result;
--        {
--            AutoTraceLog logJIT(logger, TraceLogger_IrregexpExecute);
--            AutoCheckCannotGC nogc;
--            if (input->hasLatin1Chars()) {
--                const Latin1Char* chars = input->latin1Chars(nogc);
--                result = irregexp::ExecuteCode(cx, code, chars, start, length, matches, endIndex);
--            } else {
--                const char16_t* chars = input->twoByteChars(nogc);
--                result = irregexp::ExecuteCode(cx, code, chars, start, length, matches, endIndex);
--            }
--        }
--
--        if (result == RegExpRunStatus_Error) {
--            // An 'Error' result is returned if a stack overflow guard or
--            // interrupt guard failed. If CheckOverRecursed doesn't throw, break
--            // out and retry the regexp in the bytecode interpreter, which can
--            // execute while tolerating future interrupts. Otherwise, if we keep
--            // getting interrupted we will never finish executing the regexp.
--            if (!jit::CheckOverRecursed(cx))
--                return RegExpRunStatus_Error;
--            break;
--        }
--
--        if (result == RegExpRunStatus_Success_NotFound)
--            return RegExpRunStatus_Success_NotFound;
--
--        MOZ_ASSERT(result == RegExpRunStatus_Success);
--
--        if (matches)
--            matches->checkAgainst(length);
--        return RegExpRunStatus_Success;
--    } while (false);
--
--    // Compile bytecode for the RegExp if necessary.
--    if (!compileIfNecessary(cx, re, input, mode, ForceByteCode))
--        return RegExpRunStatus_Error;
--
--    uint8_t* byteCode = re->compilation(mode, input->hasLatin1Chars()).byteCode;
--    AutoTraceLog logInterpreter(logger, TraceLogger_IrregexpExecute);
--
--    AutoStableStringChars inputChars(cx);
--    if (!inputChars.init(cx, input))
--        return RegExpRunStatus_Error;
--
--    RegExpRunStatus result;
--    if (inputChars.isLatin1()) {
--        const Latin1Char* chars = inputChars.latin1Range().begin().get();
--        result = irregexp::InterpretCode(cx, byteCode, chars, start, length, matches, endIndex);
--    } else {
--        const char16_t* chars = inputChars.twoByteRange().begin().get();
--        result = irregexp::InterpretCode(cx, byteCode, chars, start, length, matches, endIndex);
-+    int res = StringFindPattern(input, re->patternAtom(), start);
-+    if (res == -1) {
-+        return RegExpRunStatus_Success_NotFound;
-     }
- 
--    if (result == RegExpRunStatus_Success && matches)
--        matches->checkAgainst(length);
--    return result;
-+    (*matches)[0].start = res;
-+    (*matches)[0].limit = res + searchLength;
-+    matches->checkAgainst(input->length());
-+    return RegExpRunStatus_Success;
-+}
-+
-+RegExpRunStatus js::ExecuteRegExpAtomRaw(RegExpShared* re,
-+                                         JSLinearString* input, size_t start,
-+                                         MatchPairs* matchPairs) {
-+  JS::AutoCheckCannotGC nogc;
-+  return ExecuteAtomImpl(re, input, start, matchPairs);
-+}
-+
-+/* static */
-+RegExpRunStatus RegExpShared::executeAtom(MutableHandleRegExpShared re,
-+                                          HandleLinearString input,
-+                                          size_t start, MatchPairs* matches) {
-+  return ExecuteAtomImpl(re, input, start, matches);
- }
- 
- size_t
- RegExpShared::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
- {
-     size_t n = 0;
- 
-     for (size_t i = 0; i < ArrayLength(compilationArray); i++) {
-@@ -1240,45 +934,60 @@ RegExpCompartment::RegExpCompartment()
- ArrayObject*
- RegExpCompartment::createMatchResultTemplateObject(JSContext* cx)
- {
-     MOZ_ASSERT(!matchResultTemplateObject_);
- 
-     /* Create template array object */
-     RootedArrayObject templateObject(cx, NewDenseUnallocatedArray(cx, RegExpObject::MaxPairCount,
-                                                                   nullptr, TenuredObject));
--    if (!templateObject)
--        return matchResultTemplateObject_; // = nullptr
-+    if (!templateObject) {
-+        return nullptr;
-+    }
- 
-     // Create a new group for the template.
-     Rooted<TaggedProto> proto(cx, templateObject->taggedProto());
-     ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto);
--    if (!group)
--        return matchResultTemplateObject_; // = nullptr
-+    if (!group) {
-+        return nullptr;
-+    }
-     templateObject->setGroup(group);
- 
-     /* Set dummy index property */
-     RootedValue index(cx, Int32Value(0));
-     if (!NativeDefineDataProperty(cx, templateObject, cx->names().index, index, JSPROP_ENUMERATE))
-         return matchResultTemplateObject_; // = nullptr
- 
-     /* Set dummy input property */
-     RootedValue inputVal(cx, StringValue(cx->runtime()->emptyString));
--    if (!NativeDefineDataProperty(cx, templateObject, cx->names().input, inputVal,
--                                  JSPROP_ENUMERATE))
--    {
--        return matchResultTemplateObject_; // = nullptr
-+    if (!NativeDefineDataProperty(
-+          cx, templateObject, cx->names().input, inputVal, JSPROP_ENUMERATE)) {
-+        return nullptr;
-     }
- 
-+    /* Set dummy groups property */
-+    RootedValue groupsVal(cx, UndefinedValue());
-+    if (!NativeDefineDataProperty(
-+          cx, templateObject, cx->names().groups, groupsVal, JSPROP_ENUMERATE)) {
-+        return nullptr;
-+    }
-+    AddTypePropertyId(cx, templateObject, NameToId(cx->names().groups), TypeSet::AnyObjectType());
-+
-     // Make sure that the properties are in the right slots.
--    DebugOnly<Shape*> shape = templateObject->lastProperty();
--    MOZ_ASSERT(shape->previous()->slot() == 0 &&
--               shape->previous()->propidRef() == NameToId(cx->names().index));
--    MOZ_ASSERT(shape->slot() == 1 &&
--               shape->propidRef() == NameToId(cx->names().input));
-+#ifdef DEBUG
-+  Shape* groupsShape = templateObject->lastProperty();
-+  MOZ_ASSERT(groupsShape->slot() == 0 &&
-+             groupsShape->propidRef() == NameToId(cx->names().groups));
-+  Shape* inputShape = groupsShape->previous().get();
-+  MOZ_ASSERT(inputShape->slot() == 1 &&
-+             inputShape->propidRef() == NameToId(cx->names().input));
-+  Shape* indexShape = inputShape->previous().get();
-+  MOZ_ASSERT(indexShape->slot() == 2 &&
-+             indexShape->propidRef() == NameToId(cx->names().index));
-+#endif
- 
-     // Make sure type information reflects the indexed properties which might
-     // be added.
-     AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::StringType());
-     AddTypePropertyId(cx, templateObject, JSID_VOID, TypeSet::UndefinedType());
- 
-     matchResultTemplateObject_.set(templateObject);
- 
-@@ -1312,17 +1021,17 @@ RegExpCompartment::sweep()
-     if (optimizableRegExpInstanceShape_ &&
-         IsAboutToBeFinalized(&optimizableRegExpInstanceShape_))
-     {
-         optimizableRegExpInstanceShape_.set(nullptr);
-     }
- }
- 
- RegExpShared*
--RegExpZone::get(JSContext* cx, HandleAtom source, RegExpFlag flags)
-+RegExpZone::get(JSContext* cx, HandleAtom source, RegExpFlags flags)
- {
-     DependentAddPtr<Set> p(cx, set_, Key(source, flags));
-     if (p)
-         return *p;
- 
-     auto shared = Allocate<RegExpShared>(cx);
-     if (!shared)
-         return nullptr;
-@@ -1335,17 +1044,17 @@ RegExpZone::get(JSContext* cx, HandleAto
-     }
- 
-     return shared;
- }
- 
- RegExpShared*
- RegExpZone::get(JSContext* cx, HandleAtom atom, JSString* opt)
- {
--    RegExpFlag flags = RegExpFlag(0);
-+    RegExpFlags flags = RegExpFlag::NoFlags;
-     if (opt && !ParseRegExpFlags(cx, opt, &flags))
-         return nullptr;
- 
-     return get(cx, atom, flags);
- }
- 
- size_t
- RegExpZone::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
-@@ -1379,54 +1088,57 @@ js::CloneRegExpObject(JSContext* cx, Han
-     clone->initAndZeroLastIndex(shared->getSource(), shared->getFlags(), cx);
-     clone->setShared(*shared);
- 
-     return clone;
- }
- 
- template <typename CharT>
- static bool
--ParseRegExpFlags(const CharT* chars, size_t length, RegExpFlag* flagsOut, char16_t* invalidFlag)
-+ParseRegExpFlags(const CharT* chars, size_t length, RegExpFlags* flagsOut, char16_t* invalidFlag)
- {
--    *flagsOut = RegExpFlag(0);
-+    *flagsOut = RegExpFlag::NoFlags;
- 
-     for (size_t i = 0; i < length; i++) {
--        RegExpFlag flag;
-+        uint8_t flag;
-         switch (chars[i]) {
-           case 'i':
--            flag = IgnoreCaseFlag;
-+            flag = RegExpFlag::IgnoreCase;
-             break;
-           case 'g':
--            flag = GlobalFlag;
-+            flag = RegExpFlag::Global;
-             break;
-           case 'm':
--            flag = MultilineFlag;
-+            flag = RegExpFlag::Multiline;
-             break;
-           case 'y':
--            flag = StickyFlag;
-+            flag = RegExpFlag::Sticky;
-             break;
-           case 'u':
--            flag = UnicodeFlag;
-+            flag = RegExpFlag::Unicode;
-+            break;
-+          case 's':
-+            flag = RegExpFlag::DotAll;
-             break;
-           default:
-             *invalidFlag = chars[i];
-             return false;
-         }
-         if (*flagsOut & flag) {
-             *invalidFlag = chars[i];
-             return false;
-         }
--        *flagsOut = RegExpFlag(*flagsOut | flag);
-+        *flagsOut = RegExpFlags(*flagsOut | flag);
-     }
- 
-     return true;
- }
- 
- bool
--js::ParseRegExpFlags(JSContext* cx, JSString* flagStr, RegExpFlag* flagsOut)
-+js::ParseRegExpFlags(JSContext* cx, JSString* flagStr, RegExpFlags* flagsOut)
- {
-     JSLinearString* linear = flagStr->ensureLinear(cx);
-     if (!linear)
-         return false;
- 
-     size_t len = linear->length();
- 
-     bool ok;
-@@ -1454,28 +1166,28 @@ js::ParseRegExpFlags(JSContext* cx, JSSt
- 
- template<XDRMode mode>
- bool
- js::XDRScriptRegExpObject(XDRState<mode>* xdr, MutableHandle<RegExpObject*> objp)
- {
-     /* NB: Keep this in sync with CloneScriptRegExpObject. */
- 
-     RootedAtom source(xdr->cx());
--    uint32_t flagsword = 0;
-+    uint8_t flags = 0;
- 
-     if (mode == XDR_ENCODE) {
-         MOZ_ASSERT(objp);
-         RegExpObject& reobj = *objp;
-         source = reobj.getSource();
--        flagsword = reobj.getFlags();
-+        flags = reobj.getFlags().value();
-     }
--    if (!XDRAtom(xdr, &source) || !xdr->codeUint32(&flagsword))
-+    if (!XDRAtom(xdr, &source) || !xdr->codeUint8(&flags))
-         return false;
-     if (mode == XDR_DECODE) {
--        RegExpObject* reobj = RegExpObject::create(xdr->cx(), source, RegExpFlag(flagsword),
-+        RegExpObject* reobj = RegExpObject::create(xdr->cx(), source, RegExpFlags(flags),
-                                                    xdr->lifoAlloc(), TenuredObject);
-         if (!reobj)
-             return false;
- 
-         objp.set(reobj);
-     }
-     return true;
- }
-@@ -1504,8 +1216,167 @@ js::RegExpToSharedNonInline(JSContext* c
- }
- 
- JS::ubi::Node::Size
- JS::ubi::Concrete<RegExpShared>::size(mozilla::MallocSizeOf mallocSizeOf) const
- {
-     return js::gc::Arena::thingSize(gc::AllocKind::REGEXP_SHARED) +
-         get().sizeOfExcludingThis(mallocSizeOf);
- }
-+
-+/*
-+ * Public API functions for Regular Expressions.
-+ */
-+JS_PUBLIC_API(JSObject*)
-+JS::NewRegExpObject(JSContext* cx, const char* bytes, size_t length, RegExpFlags flags)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+
-+    ScopedJSFreePtr<char16_t> chars(InflateString(cx, bytes, length));
-+    if (!chars)
-+        return nullptr;
-+
-+    return RegExpObject::create(cx, chars.get(), length, flags, cx->tempLifoAlloc(),
-+                                GenericObject);
-+}
-+
-+JS_PUBLIC_API(JSObject*)
-+JS::NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, RegExpFlags flags)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+
-+    return RegExpObject::create(cx, chars, length, flags, cx->tempLifoAlloc(),
-+                                GenericObject);
-+}
-+
-+JS_PUBLIC_API(bool)
-+JS::SetRegExpInput(JSContext* cx, HandleObject obj, HandleString input)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+    assertSameCompartment(cx, input);
-+
-+    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-+    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
-+    if (!res)
-+        return false;
-+
-+    res->reset(input);
-+    return true;
-+}
-+
-+JS_PUBLIC_API(bool)
-+JS::ClearRegExpStatics(JSContext* cx, HandleObject obj)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+    MOZ_ASSERT(obj);
-+
-+    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-+    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
-+    if (!res)
-+        return false;
-+
-+    res->clear();
-+    return true;
-+}
-+
-+JS_PUBLIC_API(bool)
-+JS::ExecuteRegExp(JSContext* cx, HandleObject obj, HandleObject reobj, char16_t* chars,
-+                 size_t length, size_t* indexp, bool test, MutableHandleValue rval)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+
-+    Handle<GlobalObject*> global = obj.as<GlobalObject>();
-+    RegExpStatics* res = GlobalObject::getRegExpStatics(cx, global);
-+    if (!res)
-+        return false;
-+
-+    RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
-+    if (!input)
-+        return false;
-+
-+    return ExecuteRegExpLegacy(cx, res, reobj.as<RegExpObject>(), input, indexp, test, rval);
-+}
-+
-+JS_PUBLIC_API(bool)
-+JS::ExecuteRegExpNoStatics(JSContext* cx, HandleObject obj, char16_t* chars, size_t length,
-+                          size_t* indexp, bool test, MutableHandleValue rval)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+
-+    RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length));
-+    if (!input)
-+        return false;
-+
-+    return ExecuteRegExpLegacy(cx, nullptr, obj.as<RegExpObject>(), input, indexp, test,
-+                               rval);
-+}
-+
-+JS_PUBLIC_API(bool)
-+JS::ObjectIsRegExp(JSContext* cx, HandleObject obj, bool* isRegExp)
-+{
-+    assertSameCompartment(cx, obj);
-+
-+    ESClass cls;
-+    if (!GetBuiltinClass(cx, obj, &cls))
-+        return false;
-+
-+    *isRegExp = cls == ESClass::RegExp;
-+    return true;
-+}
-+
-+JS_PUBLIC_API(RegExpFlags)
-+JS::GetRegExpFlags(JSContext* cx, HandleObject obj)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+
-+    RegExpShared* shared = RegExpToShared(cx, obj);
-+    if (!shared)
-+        return RegExpFlag::NoFlags;
-+    return shared->getFlags();
-+}
-+
-+JS_PUBLIC_API(JSString*)
-+JS::GetRegExpSource(JSContext* cx, HandleObject obj)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+
-+    RegExpShared* shared = RegExpToShared(cx, obj);
-+    if (!shared)
-+        return nullptr;
-+    return shared->getSource();
-+}
-+
-+JS_PUBLIC_API(bool)
-+JS::CheckRegExpSyntax(JSContext* cx,
-+                      const char16_t* chars,
-+                      size_t length,
-+                      RegExpFlags flags,
-+                      MutableHandleValue error)
-+{
-+    AssertHeapIsIdle();
-+    CHECK_REQUEST(cx);
-+
-+    CompileOptions options(cx);
-+    frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
-+
-+    mozilla::Range<const char16_t> source(chars, length);
-+    bool success = irregexp::CheckPatternSyntax(cx, dummyTokenStream, source, flags);
-+    error.set(UndefinedValue());
-+    if (!success) {
-+        // We can fail because of OOM or over-recursion even if the syntax is valid.
-+        if (cx->isThrowingOutOfMemory() || cx->isThrowingOverRecursed()) {
-+            return false;
-+        }
-+        if (!cx->getPendingException(error)) {
-+            return false;
-+        }
-+        cx->clearPendingException();
-+    }
-+    return true;
-+}
-diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h
---- a/js/src/vm/RegExpObject.h
-+++ b/js/src/vm/RegExpObject.h
-@@ -10,16 +10,17 @@
- #define vm_RegExpObject_h
- 
- #include "mozilla/Attributes.h"
- #include "mozilla/MemoryReporting.h"
- 
- #include "builtin/SelfHostingDefines.h"
- #include "gc/Marking.h"
- #include "js/GCHashTable.h"
-+#include "js/RegExpFlags.h"
- #include "proxy/Proxy.h"
- #include "vm/ArrayObject.h"
- #include "vm/JSContext.h"
- #include "vm/RegExpShared.h"
- #include "vm/Shape.h"
- 
- namespace JS { struct Zone; }
- 
-@@ -67,30 +68,30 @@ class RegExpObject : public NativeObject
-     static const Class protoClass_;
- 
-     // The maximum number of pairs a MatchResult can have, without having to
-     // allocate a bigger MatchResult.
-     static const size_t MaxPairCount = 14;
- 
-     template<typename CharT>
-     static RegExpObject*
--    create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags, LifoAlloc& alloc,
-+    create(JSContext* cx, const CharT* chars, size_t length, JS::RegExpFlags flags, LifoAlloc& alloc,
-            NewObjectKind newKind);
- 
-     template<typename CharT>
-     static RegExpObject*
--    create(JSContext* cx, const CharT* chars, size_t length, RegExpFlag flags,
-+    create(JSContext* cx, const CharT* chars, size_t length, JS::RegExpFlags flags,
-            frontend::TokenStreamAnyChars& ts, LifoAlloc& alloc, NewObjectKind kind);
- 
-     static RegExpObject*
--    create(JSContext* cx, HandleAtom atom, RegExpFlag flags, LifoAlloc& alloc,
-+    create(JSContext* cx, HandleAtom atom, JS::RegExpFlags flags, LifoAlloc& alloc,
-            NewObjectKind newKind);
- 
-     static RegExpObject*
--    create(JSContext* cx, HandleAtom atom, RegExpFlag flags, frontend::TokenStreamAnyChars& ts,
-+    create(JSContext* cx, HandleAtom atom, JS::RegExpFlags flags, frontend::TokenStreamAnyChars& ts,
-            LifoAlloc& alloc, NewObjectKind newKind);
- 
-     /*
-      * Compute the initial shape to associate with fresh RegExp objects,
-      * encoding their initial properties. Return the shape after
-      * changing |obj|'s last property to it.
-      */
-     static Shape*
-@@ -129,60 +130,64 @@ class RegExpObject : public NativeObject
-     void setSource(JSAtom* source) {
-         setSlot(SOURCE_SLOT, StringValue(source));
-     }
- 
-     /* Flags. */
- 
-     static unsigned flagsSlot() { return FLAGS_SLOT; }
- 
--    RegExpFlag getFlags() const {
--        return RegExpFlag(getFixedSlot(FLAGS_SLOT).toInt32());
-+    JS::RegExpFlags getFlags() const
-+    {
-+        return JS::RegExpFlags(getFixedSlot(FLAGS_SLOT).toInt32());
-     }
--    void setFlags(RegExpFlag flags) {
--        setSlot(FLAGS_SLOT, Int32Value(flags));
--    }
-+    void setFlags(JS::RegExpFlags flags) { setFixedSlot(FLAGS_SLOT, Int32Value(flags.value())); };
- 
--    bool ignoreCase() const { return getFlags() & IgnoreCaseFlag; }
--    bool global() const     { return getFlags() & GlobalFlag; }
--    bool multiline() const  { return getFlags() & MultilineFlag; }
--    bool sticky() const     { return getFlags() & StickyFlag; }
--    bool unicode() const    { return getFlags() & UnicodeFlag; }
-+    bool global() const { return getFlags().global(); }
-+    bool ignoreCase() const { return getFlags().ignoreCase(); }
-+    bool multiline() const { return getFlags().multiline(); }
-+    bool dotAll() const { return getFlags().dotAll(); }
-+    bool unicode() const { return getFlags().unicode(); }
-+    bool sticky() const { return getFlags().sticky(); }
- 
--    static bool isOriginalFlagGetter(JSNative native, RegExpFlag* mask);
-+    static bool isOriginalFlagGetter(JSNative native, JS::RegExpFlags* mask);
- 
-     static RegExpShared* getShared(JSContext* cx, Handle<RegExpObject*> regexp);
- 
--    bool hasShared() {
--        return !!sharedRef();
-+    bool hasShared() const { return !!sharedRef(); }
-+
-+    RegExpShared* getShared() const {
-+      MOZ_ASSERT(hasShared());
-+      return sharedRef();
-     }
- 
-     void setShared(RegExpShared& shared) {
-         MOZ_ASSERT(!hasShared());
-         sharedRef().init(&shared);
-     }
- 
--    PreBarriered<RegExpShared*>& sharedRef() {
-+    PreBarriered<RegExpShared*>& sharedRef() const {
-         auto& ref = NativeObject::privateRef(PRIVATE_SLOT);
-         return reinterpret_cast<PreBarriered<RegExpShared*>&>(ref);
-     }
- 
-     static void trace(JSTracer* trc, JSObject* obj);
-     void trace(JSTracer* trc);
- 
--    void initIgnoringLastIndex(JSAtom* source, RegExpFlag flags);
-+    void initIgnoringLastIndex(JSAtom* source, JS::RegExpFlags flags);
- 
-     // NOTE: This method is *only* safe to call on RegExps that haven't been
-     //       exposed to script, because it requires that the "lastIndex"
-     //       property be writable.
--    void initAndZeroLastIndex(JSAtom* source, RegExpFlag flags, JSContext* cx);
-+    void initAndZeroLastIndex(JSAtom* source, JS::RegExpFlags flags, JSContext* cx);
- 
- #ifdef DEBUG
--    static MOZ_MUST_USE bool dumpBytecode(JSContext* cx, Handle<RegExpObject*> regexp,
--                                          bool match_only, HandleLinearString input);
-+    static MOZ_MUST_USE bool dumpBytecode(JSContext* cx,
-+                                          Handle<RegExpObject*> regexp,
-+                                          HandleLinearString input);
- #endif
- 
-   private:
-     /*
-      * Precondition: the syntax for |source| has already been validated.
-      * Side effect: sets the private field.
-      */
-     static RegExpShared* createShared(JSContext* cx, Handle<RegExpObject*> regexp);
-@@ -193,17 +198,17 @@ class RegExpObject : public NativeObject
- 
- /*
-  * Parse regexp flags. Report an error and return false if an invalid
-  * sequence of flags is encountered (repeat/invalid flag).
-  *
-  * N.B. flagStr must be rooted.
-  */
- bool
--ParseRegExpFlags(JSContext* cx, JSString* flagStr, RegExpFlag* flagsOut);
-+ParseRegExpFlags(JSContext* cx, JSString* flagStr, JS::RegExpFlags* flagsOut);
- 
- /* Assuming GetBuiltinClass(obj) is ESClass::RegExp, return a RegExpShared for obj. */
- inline RegExpShared*
- RegExpToShared(JSContext* cx, HandleObject obj)
- {
-     if (obj->is<RegExpObject>())
-         return RegExpObject::getShared(cx, obj.as<RegExpObject>());
- 
-diff --git a/js/src/vm/RegExpShared.h b/js/src/vm/RegExpShared.h
---- a/js/src/vm/RegExpShared.h
-+++ b/js/src/vm/RegExpShared.h
-@@ -16,58 +16,50 @@
- #include "mozilla/MemoryReporting.h"
- 
- #include "jsalloc.h"
- 
- #include "builtin/SelfHostingDefines.h"
- #include "gc/Barrier.h"
- #include "gc/Heap.h"
- #include "gc/Marking.h"
-+#include "jit/JitOptions.h"
-+#include "js/RegExpFlags.h"
- #include "js/UbiNode.h"
- #include "js/Vector.h"
-+#include "irregexp/RegExpTypes.h"
- #include "vm/ArrayObject.h"
- #include "vm/JSAtom.h"
-+#include "vm/JSContext.h"
- 
- namespace js {
- 
- class ArrayObject;
- class MatchPairs;
- class RegExpCompartment;
- class RegExpShared;
- class RegExpStatics;
- 
- using RootedRegExpShared = JS::Rooted<RegExpShared*>;
- using HandleRegExpShared = JS::Handle<RegExpShared*>;
- using MutableHandleRegExpShared = JS::MutableHandle<RegExpShared*>;
- 
--enum RegExpFlag : uint8_t
-+enum RegExpRunStatus : int32_t
- {
--    IgnoreCaseFlag  = 0x01,
--    GlobalFlag      = 0x02,
--    MultilineFlag   = 0x04,
--    StickyFlag      = 0x08,
--    UnicodeFlag     = 0x10,
--
--    NoFlags         = 0x00,
--    AllFlags        = 0x1f
-+    RegExpRunStatus_Error = -1,
-+    RegExpRunStatus_Success = 1,
-+    RegExpRunStatus_Success_NotFound = 0,
- };
--
--static_assert(IgnoreCaseFlag == REGEXP_IGNORECASE_FLAG &&
--              GlobalFlag == REGEXP_GLOBAL_FLAG &&
--              MultilineFlag == REGEXP_MULTILINE_FLAG &&
--              StickyFlag == REGEXP_STICKY_FLAG &&
--              UnicodeFlag == REGEXP_UNICODE_FLAG,
--              "Flag values should be in sync with self-hosted JS");
--
--enum RegExpRunStatus
--{
--    RegExpRunStatus_Error,
--    RegExpRunStatus_Success,
--    RegExpRunStatus_Success_NotFound
--};
-+inline bool IsNativeRegExpEnabled(JSContext* cx) {
-+#ifdef JS_CODEGEN_NONE
-+  return false;
-+#else
-+  return cx->options().nativeRegExp();
-+#endif
-+}
- 
- /*
-  * A RegExpShared is the compiled representation of a regexp. A RegExpShared is
-  * potentially pointed to by multiple RegExpObjects. Additionally, C++ code may
-  * have pointers to RegExpShareds on the stack. The RegExpShareds are kept in a
-  * table so that they can be reused when compiling the same regex string.
-  *
-  * To save memory, a RegExpShared is not created for a RegExpObject until it is
-@@ -79,183 +71,243 @@ enum RegExpRunStatus
-  * than explicitly tracing them, so that the RegExpShared and any jitcode can
-  * be reclaimed quicker. However, the RegExpShareds are traced through by
-  * objects when we are preserving jitcode in their zone, to avoid the same
-  * recompilation inefficiencies as normal Ion and baseline compilation.
-  */
- class RegExpShared : public gc::TenuredCell
- {
-   public:
--    enum CompilationMode {
--        Normal,
--        MatchOnly
-+    enum class Kind
-+    {
-+        Unparsed,
-+        Atom,
-+        RegExp
-     };
- 
--    enum ForceByteCodeEnum {
--        DontForceByteCode,
--        ForceByteCode
-+    enum class CodeKind
-+    {
-+        Bytecode,
-+        Jitcode,
-+        Any
-     };
- 
--    using JitCodeTable = UniquePtr<uint8_t[], JS::FreePolicy>;
-+    using ByteCode = js::irregexp::ByteArrayData;
-+    using JitCodeTable = js::irregexp::ByteArray;
-     using JitCodeTables = Vector<JitCodeTable, 0, SystemAllocPolicy>;
- 
-   private:
-     friend class RegExpStatics;
-     friend class RegExpZone;
- 
-     struct RegExpCompilation
-     {
-         ReadBarriered<jit::JitCode*> jitCode;
--        uint8_t* byteCode;
-+        ByteCode* byteCode;
- 
-         RegExpCompilation() : byteCode(nullptr) {}
- 
--        bool compiled(ForceByteCodeEnum force = DontForceByteCode) const {
--            return byteCode || (force == DontForceByteCode && jitCode);
-+        bool compiled(CodeKind kind = CodeKind::Any) const
-+        {
-+            switch (kind) {
-+                case CodeKind::Bytecode:
-+                    return !!byteCode;
-+                case CodeKind::Jitcode:
-+                    return !!jitCode;
-+                case CodeKind::Any:
-+                    return !!byteCode || !!jitCode;
-+            }
-+            MOZ_CRASH("Unreachable");
-         }
-     };
- 
-     /* Source to the RegExp, for lazy compilation. */
-     GCPtr<JSAtom*>     source;
- 
--    RegExpFlag         flags;
--    bool               canStringMatch;
--    size_t             parenCount;
-+    JS::RegExpFlags    flags;
- 
--    RegExpCompilation  compilationArray[4];
-+    RegExpShared::Kind kind_ = Kind::Unparsed;
-+    GCPtrAtom patternAtom_;
-+    uint32_t maxRegisters_ = 0;
-+    uint32_t ticks_ = 0;
- 
--    static int CompilationIndex(CompilationMode mode, bool latin1) {
--        switch (mode) {
--          case Normal:    return latin1 ? 0 : 1;
--          case MatchOnly: return latin1 ? 2 : 3;
--        }
--        MOZ_CRASH();
--    }
-+    uint32_t numNamedCaptures_ = {};
-+    uint32_t* namedCaptureIndices_ = {};
-+    GCPtr<PlainObject*> groupsTemplate_ = {};
-+
-+    size_t             pairCount_;
-+
-+    // Make x86 build happy.
-+    size_t             dummy_;
-+
-+    RegExpCompilation  compilationArray[2];
-+
-+    static int CompilationIndex(bool latin1) { return latin1 ? 0 : 1; }
- 
-     // Tables referenced by JIT code.
-     JitCodeTables tables;
- 
-     /* Internal functions. */
--    RegExpShared(JSAtom* source, RegExpFlag flags);
--
--    static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleLinearString input,
--                        CompilationMode mode, ForceByteCodeEnum force);
--    static bool compile(JSContext* cx, MutableHandleRegExpShared res, HandleAtom pattern,
--                        HandleLinearString input, CompilationMode mode, ForceByteCodeEnum force);
-+    RegExpShared(JSAtom* source, JS::RegExpFlags flags);
- 
--    static bool compileIfNecessary(JSContext* cx, MutableHandleRegExpShared res,
--                                   HandleLinearString input, CompilationMode mode,
--                                   ForceByteCodeEnum force);
-+    static bool compileIfNecessary(JSContext* cx,
-+                                   MutableHandleRegExpShared res,
-+                                   HandleLinearString input,
-+                                   CodeKind code);
- 
--    const RegExpCompilation& compilation(CompilationMode mode, bool latin1) const {
--        return compilationArray[CompilationIndex(mode, latin1)];
-+    const RegExpCompilation& compilation(bool latin1) const {
-+        return compilationArray[CompilationIndex(latin1)];
-     }
- 
--    RegExpCompilation& compilation(CompilationMode mode, bool latin1) {
--        return compilationArray[CompilationIndex(mode, latin1)];
-+    RegExpCompilation& compilation(bool latin1) {
-+        return compilationArray[CompilationIndex(latin1)];
-     }
- 
-   public:
-     ~RegExpShared() = delete;
- 
--    // Execute this RegExp on input starting from searchIndex, filling in
--    // matches if specified and otherwise only determining if there is a match.
-+    static RegExpRunStatus executeAtom(MutableHandleRegExpShared re,
-+                                       HandleLinearString input,
-+                                       size_t start,
-+                                       MatchPairs* matches);
-+
-+    // Execute this RegExp on input starting from searchIndex, filling in matches.
-     static RegExpRunStatus execute(JSContext* cx, MutableHandleRegExpShared res,
-                                    HandleLinearString input, size_t searchIndex,
--                                   MatchPairs* matches, size_t* endIndex);
-+                                   MatchPairs* matches);
- 
-     // Register a table with this RegExpShared, and take ownership.
-     bool addTable(JitCodeTable table) {
-         return tables.append(Move(table));
-     }
- 
-     /* Accessors */
- 
--    size_t getParenCount() const {
--        MOZ_ASSERT(isCompiled());
--        return parenCount;
-+    size_t pairCount() const {
-+        MOZ_ASSERT(kind() != Kind::Unparsed);
-+        return pairCount_;
-     }
- 
--    /* Accounts for the "0" (whole match) pair. */
--    size_t pairCount() const            { return getParenCount() + 1; }
-+    RegExpShared::Kind kind() const { return kind_; }
-+
-+    // Use simple string matching for this regexp.
-+    void useAtomMatch(HandleAtom pattern);
-+
-+    // Use the regular expression engine for this regexp.
-+    void useRegExpMatch(size_t parenCount);
-+
-+    static bool initializeNamedCaptures(JSContext* cx,
-+                                        HandleRegExpShared re,
-+                                        HandleNativeObject namedCaptures);
-+    PlainObject* getGroupsTemplate() { return groupsTemplate_; }
-+
-+    void tierUpTick();
-+    bool markedForTierUp(JSContext* cx) const;
-+
-+    void setByteCode(ByteCode* code, bool latin1) { compilation(latin1).byteCode = code; }
-+    ByteCode* getByteCode(bool latin1) const { return compilation(latin1).byteCode; }
-+    void setJitCode(jit::JitCode* code, bool latin1) { compilation(latin1).jitCode = code; }
-+    jit::JitCode* getJitCode(bool latin1) const { return compilation(latin1).jitCode; }
-+    uint32_t getMaxRegisters() const { return maxRegisters_; }
-+    void updateMaxRegisters(uint32_t numRegisters)
-+    {
-+        maxRegisters_ = std::max(maxRegisters_, numRegisters);
-+    }
-+
-+    uint32_t numNamedCaptures() const { return numNamedCaptures_; }
-+    int32_t getNamedCaptureIndex(uint32_t idx) const
-+    {
-+        MOZ_ASSERT(idx < numNamedCaptures());
-+        MOZ_ASSERT(namedCaptureIndices_);
-+        return namedCaptureIndices_[idx];
-+    }
- 
-     JSAtom* getSource() const           { return source; }
--    RegExpFlag getFlags() const         { return flags; }
--    bool ignoreCase() const             { return flags & IgnoreCaseFlag; }
--    bool global() const                 { return flags & GlobalFlag; }
--    bool multiline() const              { return flags & MultilineFlag; }
--    bool sticky() const                 { return flags & StickyFlag; }
--    bool unicode() const                { return flags & UnicodeFlag; }
-+
-+    JSAtom* patternAtom() const         { return patternAtom_; }
-+
-+    JS::RegExpFlags getFlags() const    { return flags; }
- 
--    bool isCompiled(CompilationMode mode, bool latin1,
--                    ForceByteCodeEnum force = DontForceByteCode) const {
--        return compilation(mode, latin1).compiled(force);
-+    bool global() const                 { return flags.global(); }
-+    bool ignoreCase() const             { return flags.ignoreCase(); }
-+    bool multiline() const              { return flags.multiline(); }
-+    bool dotAll() const                 { return flags.dotAll(); }
-+    bool unicode() const                { return flags.unicode(); }
-+    bool sticky() const                 { return flags.sticky(); }
-+
-+    bool isCompiled(bool latin1, CodeKind codeKind = CodeKind::Any) const
-+    {
-+        return compilation(latin1).compiled(codeKind);
-     }
--    bool isCompiled() const {
--        return isCompiled(Normal, true) || isCompiled(Normal, false)
--            || isCompiled(MatchOnly, true) || isCompiled(MatchOnly, false);
--    }
-+    bool isCompiled() const { return isCompiled(true) || isCompiled(false); }
- 
-     void traceChildren(JSTracer* trc);
-     void discardJitCode();
-     void finalize(FreeOp* fop);
- 
-     static size_t offsetOfSource() {
-         return offsetof(RegExpShared, source);
-     }
- 
-+    static size_t offsetOfPatternAtom() {
-+        return offsetof(RegExpShared, patternAtom_);
-+    }
-+
-     static size_t offsetOfFlags() {
-         return offsetof(RegExpShared, flags);
-     }
- 
--    static size_t offsetOfParenCount() {
--        return offsetof(RegExpShared, parenCount);
-+    static size_t offsetOfPairCount() {
-+        return offsetof(RegExpShared, pairCount_);
-     }
- 
--    static size_t offsetOfLatin1JitCode(CompilationMode mode) {
--        return offsetof(RegExpShared, compilationArray)
--             + (CompilationIndex(mode, true) * sizeof(RegExpCompilation))
--             + offsetof(RegExpCompilation, jitCode);
-+    static size_t offsetOfJitCode(bool latin1)
-+    {
-+        return offsetof(RegExpShared, compilationArray) +
-+               (CompilationIndex(latin1) * sizeof(RegExpCompilation)) +
-+               offsetof(RegExpCompilation, jitCode);
-     }
--    static size_t offsetOfTwoByteJitCode(CompilationMode mode) {
--        return offsetof(RegExpShared, compilationArray)
--             + (CompilationIndex(mode, false) * sizeof(RegExpCompilation))
--             + offsetof(RegExpCompilation, jitCode);
-+
-+    static size_t offsetOfGroupsTemplate() {
-+        return offsetof(RegExpShared, groupsTemplate_);
-     }
- 
-     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
- 
- #ifdef DEBUG
--    static bool dumpBytecode(JSContext* cx, MutableHandleRegExpShared res, bool match_only,
-+    static bool dumpBytecode(JSContext* cx,
-+                             MutableHandleRegExpShared res,
-                              HandleLinearString input);
- #endif
- };
- 
- class RegExpZone
- {
--    struct Key {
--        JSAtom* atom;
--        uint16_t flag;
-+    struct Key
-+    {
-+        JSAtom* atom = nullptr;
-+        JS::RegExpFlags flags = JS::RegExpFlag::NoFlags;
- 
--        Key() {}
--        Key(JSAtom* atom, RegExpFlag flag)
--          : atom(atom), flag(flag)
--        { }
-+        Key() = default;
-+        Key(JSAtom* atom, JS::RegExpFlags flags)
-+          : atom(atom)
-+          , flags(flags)
-+        {}
-         MOZ_IMPLICIT Key(const ReadBarriered<RegExpShared*>& shared)
-           : atom(shared.unbarrieredGet()->getSource()),
--            flag(shared.unbarrieredGet()->getFlags())
-+            flags(shared.unbarrieredGet()->getFlags())
-         { }
- 
-         typedef Key Lookup;
-         static HashNumber hash(const Lookup& l) {
-             HashNumber hash = DefaultHasher<JSAtom*>::hash(l.atom);
--            return mozilla::AddToHash(hash, l.flag);
-+            return mozilla::AddToHash(hash, l.flags.value());
-         }
-         static bool match(Key l, Key r) {
--            return l.atom == r.atom && l.flag == r.flag;
-+            return l.atom == r.atom && l.flags == r.flags;
-         }
-     };
- 
-     /*
-      * The set of all RegExpShareds in the zone. On every GC, every RegExpShared
-      * that was not marked is deleted and removed from the set.
-      */
-     using Set = JS::WeakCache<JS::GCHashSet<ReadBarriered<RegExpShared*>, Key, ZoneAllocPolicy>>;
-@@ -267,22 +319,22 @@ class RegExpZone
-     ~RegExpZone() {
-         MOZ_ASSERT_IF(set_.initialized(), set_.empty());
-     }
- 
-     bool init();
- 
-     bool empty() const { return set_.empty(); }
- 
--    RegExpShared* maybeGet(JSAtom* source, RegExpFlag flags) const {
-+    RegExpShared* maybeGet(JSAtom* source, JS::RegExpFlags flags) const {
-         Set::Ptr p = set_.lookup(Key(source, flags));
-         return p ? *p : nullptr;
-     }
- 
--    RegExpShared* get(JSContext* cx, HandleAtom source, RegExpFlag flags);
-+    RegExpShared* get(JSContext* cx, HandleAtom source, JS::RegExpFlags flags);
- 
-     /* Like 'get', but compile 'maybeOpt' (if non-null). */
-     RegExpShared* get(JSContext* cx, HandleAtom source, JSString* maybeOpt);
- 
- #ifdef DEBUG
-     void clear() { set_.clear(); }
- #endif
- 
-@@ -349,16 +401,19 @@ class RegExpCompartment
-     static size_t offsetOfOptimizableRegExpPrototypeShape() {
-         return offsetof(RegExpCompartment, optimizableRegExpPrototypeShape_);
-     }
-     static size_t offsetOfOptimizableRegExpInstanceShape() {
-         return offsetof(RegExpCompartment, optimizableRegExpInstanceShape_);
-     }
- };
- 
-+RegExpRunStatus ExecuteRegExpAtomRaw(RegExpShared* re, JSLinearString* input,
-+                                     size_t start, MatchPairs* matchPairs);
-+
- } /* namespace js */
- 
- namespace JS {
- namespace ubi {
- 
- template <>
- class Concrete<js::RegExpShared> : TracerConcrete<js::RegExpShared>
- {
-diff --git a/js/src/vm/RegExpStatics.cpp b/js/src/vm/RegExpStatics.cpp
---- a/js/src/vm/RegExpStatics.cpp
-+++ b/js/src/vm/RegExpStatics.cpp
-@@ -88,18 +88,17 @@ RegExpStatics::executeLazy(JSContext* cx
- 
-     /*
-      * It is not necessary to call aboutToWrite(): evaluation of
-      * implicit copies is safe.
-      */
- 
-     /* Execute the full regular expression. */
-     RootedLinearString input(cx, matchesInput);
--    RegExpRunStatus status = RegExpShared::execute(cx, &shared, input, lazyIndex, &this->matches,
--                                                   nullptr);
-+    RegExpRunStatus status = RegExpShared::execute(cx, &shared, input, lazyIndex, &this->matches);
-     if (status == RegExpRunStatus_Error)
-         return false;
- 
-     /*
-      * RegExpStatics are only updated on successful (matching) execution.
-      * Re-running the same expression must therefore produce a matching result.
-      */
-     MOZ_ASSERT(status == RegExpRunStatus_Success);
-diff --git a/js/src/vm/RegExpStatics.h b/js/src/vm/RegExpStatics.h
---- a/js/src/vm/RegExpStatics.h
-+++ b/js/src/vm/RegExpStatics.h
-@@ -25,18 +25,18 @@ class RegExpStatics
-     HeapPtr<JSLinearString*>  matchesInput;
- 
-     /*
-      * The previous RegExp input, used to resolve lazy state.
-      * A raw RegExpShared cannot be stored because it may be in
-      * a different compartment via evalcx().
-      */
-     HeapPtr<JSAtom*>          lazySource;
--    RegExpFlag              lazyFlags;
--    size_t                  lazyIndex;
-+    JS::RegExpFlags            lazyFlags;
-+    size_t                    lazyIndex;
- 
-     /* The latest RegExp input, set before execution. */
-     HeapPtr<JSString*>        pendingInput;
- 
-     /*
-      * If non-zero, |matchesInput| and the |lazy*| fields may be used
-      * to replay the last executed RegExp, and |matches| is invalid.
-      */
-@@ -273,17 +273,17 @@ RegExpStatics::updateFromMatchPairs(JSCo
- }
- 
- inline void
- RegExpStatics::clear()
- {
-     matches.forgetArray();
-     matchesInput = nullptr;
-     lazySource = nullptr;
--    lazyFlags = RegExpFlag(0);
-+    lazyFlags = JS::RegExpFlag::NoFlags;
-     lazyIndex = size_t(-1);
-     pendingInput = nullptr;
-     pendingLazyEvaluation = false;
- }
- 
- inline void
- RegExpStatics::setPendingInput(JSString* newInput)
- {
-diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
---- a/js/src/vm/Runtime.h
-+++ b/js/src/vm/Runtime.h
-@@ -22,17 +22,16 @@
- 
- #include "builtin/AtomicsObject.h"
- #include "builtin/intl/SharedIntlData.h"
- #include "builtin/Promise.h"
- #include "frontend/NameCollections.h"
- #include "gc/GCRuntime.h"
- #include "gc/Tracer.h"
- #include "gc/ZoneGroup.h"
--#include "irregexp/RegExpStack.h"
- #include "js/Debug.h"
- #include "js/GCVector.h"
- #include "js/HashTable.h"
- #ifdef DEBUG
- # include "js/Proxy.h" // For AutoEnterPolicy
- #endif
- #include "js/UniquePtr.h"
- #include "js/Vector.h"
-diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
---- a/js/src/vm/SelfHosting.cpp
-+++ b/js/src/vm/SelfHosting.cpp
-@@ -851,16 +851,31 @@ js::intrinsic_NewStringIterator(JSContex
-     JSObject* obj = NewStringIteratorObject(cx);
-     if (!obj)
-         return false;
- 
-     args.rval().setObject(*obj);
-     return true;
- }
- 
-+bool
-+js::intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc, Value* vp) 
-+{
-+  CallArgs args = CallArgsFromVp(argc, vp);
-+  MOZ_ASSERT(args.length() == 0);
-+
-+  JSObject* obj = NewRegExpStringIteratorObject(cx);
-+  if (!obj) {
-+    return false;
-+  }
-+
-+  args.rval().setObject(*obj);
-+  return true;
-+}
-+
- static bool
- intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
- {
-     CallArgs args = CallArgsFromVp(argc, vp);
-     MOZ_ASSERT(args.length() == 2);
- 
-     RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
-     MOZ_ASSERT(fun->isSelfHostedBuiltin());
-@@ -1579,17 +1594,17 @@ intrinsic_RegExpCreate(JSContext* cx, un
- 
-     return RegExpCreate(cx, args[0], args.get(1), args.rval());
- }
- 
- static bool
- intrinsic_RegExpGetSubstitution(JSContext* cx, unsigned argc, Value* vp)
- {
-     CallArgs args = CallArgsFromVp(argc, vp);
--    MOZ_ASSERT(args.length() == 5);
-+    MOZ_ASSERT(args.length() == 6);
- 
-     RootedArrayObject matchResult(cx, &args[0].toObject().as<ArrayObject>());
- 
-     RootedLinearString string(cx, args[1].toString()->ensureLinear(cx));
-     if (!string)
-         return false;
- 
-     int32_t position = int32_t(args[2].toNumber());
-@@ -1597,18 +1612,27 @@ intrinsic_RegExpGetSubstitution(JSContex
- 
-     RootedLinearString replacement(cx, args[3].toString()->ensureLinear(cx));
-     if (!replacement)
-         return false;
- 
-     int32_t firstDollarIndex = int32_t(args[4].toNumber());
-     MOZ_ASSERT(firstDollarIndex >= 0);
- 
--    return RegExpGetSubstitution(cx, matchResult, string, size_t(position), replacement,
--                                 size_t(firstDollarIndex), args.rval());
-+    RootedValue namedCaptures(cx, args[5]);
-+    MOZ_ASSERT(namedCaptures.isUndefined() || namedCaptures.isObject());
-+
-+    return RegExpGetSubstitution(cx,
-+                                 matchResult,
-+                                 string,
-+                                 size_t(position),
-+                                 replacement,
-+                                 size_t(firstDollarIndex),
-+                                 namedCaptures,
-+                                 args.rval());
- }
- 
- static bool
- intrinsic_StringReplaceString(JSContext* cx, unsigned argc, Value* vp)
- {
-     CallArgs args = CallArgsFromVp(argc, vp);
-     MOZ_ASSERT(args.length() == 3);
- 
-@@ -2326,16 +2350,20 @@ static const JSFunctionSpec intrinsic_fu
-                     IntrinsicGuardToMapIterator),
-     JS_INLINABLE_FN("GuardToSetIterator",
-                     intrinsic_GuardToBuiltin<SetIteratorObject>,   1,0,
-                     IntrinsicGuardToSetIterator),
-     JS_INLINABLE_FN("GuardToStringIterator",
-                     intrinsic_GuardToBuiltin<StringIteratorObject>, 1,0,
-                     IntrinsicGuardToStringIterator),
- 
-+    JS_INLINABLE_FN("GuardToRegExpStringIterator",
-+                    intrinsic_IsInstanceOfBuiltin<RegExpStringIteratorObject>, 1,0,
-+                    IntrinsicGuardToRegExpStringIterator),
-+
-     JS_FN("_CreateMapIterationResultPair", intrinsic_CreateMapIterationResultPair, 0, 0),
-     JS_INLINABLE_FN("_GetNextMapEntryForIterator", intrinsic_GetNextMapEntryForIterator, 2,0,
-                     IntrinsicGetNextMapEntryForIterator),
-     JS_FN("CallMapIteratorMethodIfWrapped",
-           CallNonGenericSelfhostedMethod<Is<MapIteratorObject>>,        2,0),
- 
-     JS_FN("_CreateSetIterationResult", intrinsic_CreateSetIterationResult, 0, 0),
-     JS_INLINABLE_FN("_GetNextSetEntryForIterator", intrinsic_GetNextSetEntryForIterator, 2,0,
-@@ -2344,16 +2372,22 @@ static const JSFunctionSpec intrinsic_fu
-           CallNonGenericSelfhostedMethod<Is<SetIteratorObject>>,        2,0),
- 
- 
-     JS_INLINABLE_FN("NewStringIterator", intrinsic_NewStringIterator,   0,0,
-                     IntrinsicNewStringIterator),
-     JS_FN("CallStringIteratorMethodIfWrapped",
-           CallNonGenericSelfhostedMethod<Is<StringIteratorObject>>,     2,0),
- 
-+    JS_INLINABLE_FN("NewRegExpStringIterator",
-+                    intrinsic_NewRegExpStringIterator, 0, 0,
-+                    IntrinsicNewRegExpStringIterator),
-+    JS_FN("CallRegExpStringIteratorMethodIfWrapped",
-+          CallNonGenericSelfhostedMethod<Is<RegExpStringIteratorObject>>, 2, 0),
-+
-     JS_FN("IsGeneratorObject",
-           intrinsic_IsInstanceOfBuiltin<GeneratorObject>,               1,0),
-     JS_FN("GeneratorObjectIsClosed", intrinsic_GeneratorObjectIsClosed, 1,0),
-     JS_FN("IsSuspendedGenerator",    intrinsic_IsSuspendedGenerator,    1,0),
- 
-     JS_FN("GeneratorIsRunning",      intrinsic_GeneratorIsRunning,      1,0),
-     JS_FN("GeneratorSetClosed",      intrinsic_GeneratorSetClosed,      1,0),
- 
-diff --git a/js/src/vm/SelfHosting.h b/js/src/vm/SelfHosting.h
---- a/js/src/vm/SelfHosting.h
-+++ b/js/src/vm/SelfHosting.h
-@@ -49,11 +49,14 @@ bool
- intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, JS::Value* vp);
- 
- bool
- intrinsic_NewStringIterator(JSContext* cx, unsigned argc, JS::Value* vp);
- 
- bool
- intrinsic_IsSuspendedGenerator(JSContext* cx, unsigned argc, JS::Value* vp);
- 
-+bool
-+intrinsic_NewRegExpStringIterator(JSContext* cx, unsigned argc, JS::Value* vp);
-+
- } /* namespace js */
- 
- #endif /* vm_SelfHosting_h_ */
-diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp
---- a/js/src/vm/StructuredClone.cpp
-+++ b/js/src/vm/StructuredClone.cpp
-@@ -24,49 +24,54 @@
-  * So during writing, we add objects to the memory when first encountering
-  * them. When reading a typed array, a placeholder is pushed onto allObjs until
-  * the ArrayBuffer has been read, then it is updated with the actual typed
-  * array object.
-  */
- 
- #include "js/StructuredClone.h"
- 
-+#include "mozilla/Casting.h"
- #include "mozilla/CheckedInt.h"
- #include "mozilla/EndianUtils.h"
- #include "mozilla/FloatingPoint.h"
- 
- #include <algorithm>
- 
- #include "jsapi.h"
- #include "jsdate.h"
- #include "jswrapper.h"
- 
- #include "builtin/DataViewObject.h"
- #include "builtin/MapObject.h"
- #include "js/Date.h"
- #include "js/GCHashTable.h"
-+#include "js/RegExpFlags.h"
- #include "vm/JSContext.h"
- #include "vm/RegExpObject.h"
- #include "vm/SavedFrame.h"
- #include "vm/SharedArrayObject.h"
- #include "vm/TypedArrayObject.h"
- #include "vm/WrapperObject.h"
- #include "wasm/WasmJS.h"
- 
- #include "vm/JSContext-inl.h"
- #include "vm/JSObject-inl.h"
- 
- using namespace js;
- 
-+using mozilla::AssertedCast;
- using mozilla::BitwiseCast;
- using mozilla::IsNaN;
- using mozilla::LittleEndian;
- using mozilla::NativeEndian;
- using mozilla::NumbersAreIdentical;
- using JS::CanonicalizeNaN;
-+using JS::RegExpFlag;
-+using JS::RegExpFlags;
- 
- // When you make updates here, make sure you consider whether you need to bump the
- // value of JS_STRUCTURED_CLONE_VERSION in js/public/StructuredClone.h.  You will
- // likely need to increment the version if anything at all changes in the serialization
- // format.
- //
- // Note that SCTAG_END_OF_KEYS is written into the serialized form and should have
- // a stable ID, it need not be at the end of the list and should not be used for
-@@ -1527,17 +1532,17 @@ JSStructuredCloneWriter::startWrite(Hand
-         ESClass cls;
-         if (!GetBuiltinClass(context(), obj, &cls))
-             return false;
- 
-         if (cls == ESClass::RegExp) {
-             RegExpShared* re = RegExpToShared(context(), obj);
-             if (!re)
-                 return false;
--            return out.writePair(SCTAG_REGEXP_OBJECT, re->getFlags()) &&
-+            return out.writePair(SCTAG_REGEXP_OBJECT, re->getFlags().value()) &&
-                    writeString(SCTAG_STRING, re->getSource());
-         } else if (cls == ESClass::Date) {
-             RootedValue unboxed(context());
-             if (!Unbox(context(), obj, &unboxed))
-                 return false;
-             return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(unboxed.toNumber());
-         } else if (JS_IsTypedArrayObject(obj)) {
-             return writeTypedArray(obj);
-@@ -2199,26 +2204,34 @@ JSStructuredCloneReader::startRead(Mutab
-         JSObject* obj = NewDateObjectMsec(context(), t);
-         if (!obj)
-             return false;
-         vp.setObject(*obj);
-         break;
-       }
- 
-       case SCTAG_REGEXP_OBJECT: {
--        RegExpFlag flags = RegExpFlag(data);
-+        if ((data & RegExpFlag::AllFlags) != data) {
-+          JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
-+                                    JSMSG_SC_BAD_SERIALIZED_DATA, "regexp");
-+          return false;
-+        }
-+
-+        RegExpFlags flags(AssertedCast<uint8_t>(data));
-+
-         uint32_t tag2, stringData;
-         if (!in.readPair(&tag2, &stringData))
-             return false;
-         if (tag2 != SCTAG_STRING) {
-             JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
-                                       JSMSG_SC_BAD_SERIALIZED_DATA,
-                                       "regexp");
-             return false;
-         }
-+
-         JSString* str = readString(stringData);
-         if (!str)
-             return false;
- 
-         RootedAtom atom(context(), AtomizeString(context(), str));
-         if (!atom)
-             return false;
- 
-diff --git a/js/src/vm/UnicodeNonBMP.h b/js/src/vm/UnicodeNonBMP.h
---- a/js/src/vm/UnicodeNonBMP.h
-+++ b/js/src/vm/UnicodeNonBMP.h
-@@ -43,37 +43,9 @@
- #define FOR_EACH_NON_BMP_UPPERCASE(macro) \
-     macro(0x10428, 0x1044f, 0xd801, 0xdc28, 0xdc4f, -40) \
-     macro(0x104d8, 0x104fb, 0xd801, 0xdcd8, 0xdcfb, -40) \
-     macro(0x10cc0, 0x10cf2, 0xd803, 0xdcc0, 0xdcf2, -64) \
-     macro(0x118c0, 0x118df, 0xd806, 0xdcc0, 0xdcdf, -32) \
-     macro(0x16e60, 0x16e7f, 0xd81b, 0xde60, 0xde7f, -32) \
-     macro(0x1e922, 0x1e943, 0xd83a, 0xdd22, 0xdd43, -34)
- 
--// U+10400 DESERET CAPITAL LETTER LONG I .. U+10427 DESERET CAPITAL LETTER EW
--// U+104B0 OSAGE CAPITAL LETTER A .. U+104D3 OSAGE CAPITAL LETTER ZHA
--// U+10C80 OLD HUNGARIAN CAPITAL LETTER A .. U+10CB2 OLD HUNGARIAN CAPITAL LETTER US
--// U+118A0 WARANG CITI CAPITAL LETTER NGAA .. U+118BF WARANG CITI CAPITAL LETTER VIYO
--// U+16E40 MEDEFAIDRIN CAPITAL LETTER M .. U+16E5F MEDEFAIDRIN CAPITAL LETTER Y
--// U+1E900 ADLAM CAPITAL LETTER ALIF .. U+1E921 ADLAM CAPITAL LETTER SHA
--#define FOR_EACH_NON_BMP_CASE_FOLDING(macro) \
--    macro(0x10400, 0x10427, 0xd801, 0xdc00, 0xdc27, 40) \
--    macro(0x104b0, 0x104d3, 0xd801, 0xdcb0, 0xdcd3, 40) \
--    macro(0x10c80, 0x10cb2, 0xd803, 0xdc80, 0xdcb2, 64) \
--    macro(0x118a0, 0x118bf, 0xd806, 0xdca0, 0xdcbf, 32) \
--    macro(0x16e40, 0x16e5f, 0xd81b, 0xde40, 0xde5f, 32) \
--    macro(0x1e900, 0x1e921, 0xd83a, 0xdd00, 0xdd21, 34)
--
--// U+10428 DESERET SMALL LETTER LONG I .. U+1044F DESERET SMALL LETTER EW
--// U+104D8 OSAGE SMALL LETTER A .. U+104FB OSAGE SMALL LETTER ZHA
--// U+10CC0 OLD HUNGARIAN SMALL LETTER A .. U+10CF2 OLD HUNGARIAN SMALL LETTER US
--// U+118C0 WARANG CITI SMALL LETTER NGAA .. U+118DF WARANG CITI SMALL LETTER VIYO
--// U+16E60 MEDEFAIDRIN SMALL LETTER M .. U+16E7F MEDEFAIDRIN SMALL LETTER Y
--// U+1E922 ADLAM SMALL LETTER ALIF .. U+1E943 ADLAM SMALL LETTER SHA
--#define FOR_EACH_NON_BMP_REV_CASE_FOLDING(macro) \
--    macro(0x10428, 0x1044f, 0xd801, 0xdc28, 0xdc4f, -40) \
--    macro(0x104d8, 0x104fb, 0xd801, 0xdcd8, 0xdcfb, -40) \
--    macro(0x10cc0, 0x10cf2, 0xd803, 0xdcc0, 0xdcf2, -64) \
--    macro(0x118c0, 0x118df, 0xd806, 0xdcc0, 0xdcdf, -32) \
--    macro(0x16e60, 0x16e7f, 0xd81b, 0xde60, 0xde7f, -32) \
--    macro(0x1e922, 0x1e943, 0xd83a, 0xdd22, 0xdd43, -34)
--
- #endif /* vm_UnicodeNonBMP_h */
-diff --git a/js/src/vm/make_unicode.py b/js/src/vm/make_unicode.py
---- a/js/src/vm/make_unicode.py
-+++ b/js/src/vm/make_unicode.py
-@@ -398,28 +398,21 @@ def process_case_folding(case_folding):
-     folding_dummy = (0, 0, 0, 0)
-     folding_table = [folding_dummy]
-     folding_cache = {folding_dummy: 0}
-     folding_index = [0] * (MAX_BMP + 1)
- 
-     folding_tests = []
-     folding_codes = set()
- 
--    non_bmp_folding_map = {}
--    non_bmp_rev_folding_map = {}
--
-     for row in read_case_folding(case_folding):
-         code = row[0]
-         mapping = row[2]
-         folding_map[code] = mapping
- 
--        if code > MAX_BMP:
--            non_bmp_folding_map[code] = mapping
--            non_bmp_rev_folding_map[mapping] = code
--
-         if mapping not in rev_folding_map:
-             rev_folding_map[mapping] = [code]
-         else:
-             rev_folding_map[mapping].append(code)
- 
-         folding_codes.add(code)
-         folding_codes.add(mapping)
- 
-@@ -464,17 +457,16 @@ def process_case_folding(case_folding):
-         i = folding_cache.get(item)
-         if i is None:
-             assert item not in folding_table
-             folding_cache[item] = i = len(folding_table)
-             folding_table.append(item)
-         folding_index[code] = i
-     return (
-         folding_table, folding_index,
--        non_bmp_folding_map, non_bmp_rev_folding_map,
-         folding_tests
-     )
- 
- def process_special_casing(special_casing, table, index):
-     # Unconditional special casing.
-     unconditional_tolower = {}
-     unconditional_toupper = {}
- 
-@@ -608,17 +600,16 @@ def process_special_casing(special_casin
- 
-     # Special casing for U+03A3 (GREEK CAPITAL LETTER SIGMA).
-     assert lowerCase(0x03A3) == 0x03C3 and conditional_tolower[0x03A3] == ([0x03C2], 'Final_Sigma');
- 
-     return (unconditional_tolower, unconditional_toupper)
- 
- def make_non_bmp_file(version,
-                       non_bmp_lower_map, non_bmp_upper_map,
--                      non_bmp_folding_map, non_bmp_rev_folding_map,
-                       codepoint_table):
-     file_name = 'UnicodeNonBMP.h';
-     with io.open(file_name, mode='w', encoding='utf-8') as non_bmp_file:
-         non_bmp_file.write(mpl_license)
-         non_bmp_file.write('\n')
-         non_bmp_file.write(warning_message)
-         non_bmp_file.write(unicode_version_message.format(version))
-         non_bmp_file.write("""
-@@ -635,20 +626,16 @@ def make_non_bmp_file(version,
- //     DIFF:       the difference between the code point in the range and
- //                 converted code point
- 
- """)
- 
-         make_non_bmp_convert_macro(non_bmp_file, 'LOWERCASE', non_bmp_lower_map, codepoint_table)
-         non_bmp_file.write('\n')
-         make_non_bmp_convert_macro(non_bmp_file, 'UPPERCASE', non_bmp_upper_map, codepoint_table)
--        non_bmp_file.write('\n')
--        make_non_bmp_convert_macro(non_bmp_file, 'CASE_FOLDING', non_bmp_folding_map, codepoint_table)
--        non_bmp_file.write('\n')
--        make_non_bmp_convert_macro(non_bmp_file, 'REV_CASE_FOLDING', non_bmp_rev_folding_map, codepoint_table)
- 
-         non_bmp_file.write("""
- #endif /* util_UnicodeNonBMP_h */
- """)
- 
- def write_special_casing_methods(unconditional_toupper, codepoint_table, println):
-     def hexlit(n):
-         """ Returns C++ hex-literal for |n|. """
-@@ -1300,215 +1287,16 @@ def splitbins(t):
-     dump(t1, t2, shift, bytes)
- 
-     # exhaustively verify that the decomposition is correct
-     mask = 2**shift - 1
-     for i in range(len(t)):
-         assert t[i] == t2[(t1[i >> shift] << shift) + (i & mask)]
-     return best
- 
--def make_irregexp_tables(version,
--                         table, index,
--                         folding_table, folding_index,
--                         codepoint_table):
--    import string
--
--    MAX_ASCII = 0x7F
--    MAX_LATIN1 = 0xFF
--    LEAD_SURROGATE_MIN = 0xD800
--    TRAIL_SURROGATE_MAX = 0xDFFF
--
--    def hex2(n):
--        assert 0 <= n and n < 16**2
--        return '0x{:02X}'.format(n)
--
--    def hex4(n):
--        assert 0 <= n and n < 16**4
--        return '0x{:04X}'.format(n)
--
--    def uhex4(n):
--        assert 0 <= n and n < 16**4
--        return 'U+{:04X}'.format(n)
--
--    def case_info(code):
--        assert 0 <= code and code <= MAX_BMP
--        (upper, lower, flags) = table[index[code]]
--        return ((code + upper) & 0xffff, (code + lower) & 0xffff, flags)
--
--    def is_space(code):
--        (_, _, flags) = case_info(code)
--        return bool(flags & FLAG_SPACE)
--
--    def to_upper(code):
--        (upper, _, _) = case_info(code)
--        return upper
--
--    def casefold(code):
--        assert 0 <= code and code <= MAX_BMP
--        (folding, _, _, _) = folding_table[folding_index[code]]
--        return (code + folding) & 0xffff
--
--    def casefolds_to_ascii(code):
--        return casefold(code) <= MAX_ASCII
--
--    def casefolds_to_latin1(code):
--        return casefold(code) <= MAX_LATIN1
--
--    def casemaps_to_nonlatin1(code):
--        upper = to_upper(code)
--        return upper > MAX_LATIN1
--
--    def char_name(code):
--        assert 0 <= code and code <= MAX_BMP
--        if code not in codepoint_table:
--            return '<Unused>'
--        if code == LEAD_SURROGATE_MIN:
--            return '<Lead Surrogate Min>'
--        if code == TRAIL_SURROGATE_MAX:
--            return '<Trail Surrogate Max>'
--        (_, _, name, alias) = codepoint_table[code]
--        return name if not name.startswith('<') else alias
--
--    def write_character_range(println, name, characters):
--        char_ranges = list(int_ranges(characters))
--        println('')
--        println('const int js::irregexp::k{}Ranges[] = {{'.format(name))
--        for (start, end) in char_ranges:
--            s_name = char_name(start)
--            e_name = char_name(end)
--            println('    {}, {} + 1, // {}'.format(hex4(start), hex4(end),
--                                                               '{}..{}'.format(s_name, e_name)
--                                                               if start != end else s_name))
--        println('    {} + 1'.format(hex4(MAX_BMP)))
--        println('};')
--        println('const int js::irregexp::k{}RangeCount = {};'.format(name,
--                                                                     len(char_ranges) * 2 + 1))
--
--    def write_character_test(println, test, consequent, default):
--        # Latin1 characters which, when case-mapped through
--        # String.prototype.toUpperCase(), canonicalize to a non-Latin1 character.
--        # ES2017, §21.2.2.8.2 Runtime Semantics: Canonicalize
--        casemapped_to_nonlatin1 = filter(casemaps_to_nonlatin1, range(0, MAX_LATIN1 + 1))
--
--        def casemap_closure(ch):
--            upper = to_upper(ch)
--            return (ch, [c for c in range(MAX_LATIN1 + 1, MAX_BMP + 1) if upper == to_upper(c)])
--
--        # Mapping from Latin1 characters to the list of case map equivalent
--        # non-Latin1 characters.
--        casemap_for_latin1 = dict(chain(map(casemap_closure, casemapped_to_nonlatin1)))
--
--        # Non-latin1 characters which, when Unicode case-folded, canonicalize to
--        # a Latin1 character.
--        # ES2017, §21.2.2.8.2 Runtime Semantics: Canonicalize
--        casefolded_to_latin1 = filter(casefolds_to_latin1, range(MAX_LATIN1 + 1, MAX_BMP + 1))
--
--        println('    if (unicode) {')
--        for ch in casefolded_to_latin1:
--            casefolded = casefold(ch)
--            # Skip if also handled below for case mapping.
--            if casefolded in casemap_for_latin1 and ch in casemap_for_latin1[casefolded]:
--                continue
--            println('        // "{}" case folds to "{}".'.format(char_name(ch),
--                                                                 char_name(casefolded)))
--            println('        if ({}) {{'.format(test(ch)))
--            println('            return {};'.format(consequent(casefolded)))
--            println('        }')
--        println('    }')
--        println('')
--        for (ch, casemapped_chars) in casemap_for_latin1.items():
--            for casemapped in casemapped_chars:
--                println('    // "{}" case maps to "{}".'.format(char_name(casemapped),
--                                                                char_name(ch)))
--            println('    if ({}) {{'.format(' || '.join(map(test, casemapped_chars))))
--            println('        return {};'.format(consequent(ch)))
--            println('    }')
--        println('    return {};'.format(default))
--
--    with io.open('../irregexp/RegExpCharacters-inl.h', 'w', encoding='utf-8') as chars_file:
--        write = partial(print, file=chars_file, sep='', end='')
--        println = partial(write, end='\n')
--
--        write(warning_message)
--        write(unicode_version_message.format(version))
--
--        println('#ifndef V8_JSREGEXPCHARACTERS_INL_H_')
--        println('#define V8_JSREGEXPCHARACTERS_INL_H_')
--        println('')
--        println('namespace js {')
--        println('')
--        println('namespace irregexp {')
--        println('')
--
--        println('static inline bool')
--        println('RangeContainsLatin1Equivalents(CharacterRange range, bool unicode)')
--        println('{')
--        write_character_test(println, lambda ch: 'range.Contains({})'.format(hex4(ch)),
--                             lambda _: 'true', 'false')
--        println('}')
--
--        println('')
--        println('} } // namespace js::irregexp')
--        println('')
--        println('#endif // V8_JSREGEXPCHARACTERS_INL_H_')
--
--    with io.open('../irregexp/RegExpCharacters.cpp', 'w', encoding='utf-8') as chars_file:
--        write = partial(print, file=chars_file, sep='', end='')
--        println = partial(write, end='\n')
--        character_range = partial(write_character_range, println)
--
--        # Characters in \s, 21.2.2.12 CharacterClassEscape.
--        space_chars = [ch for ch in range(0, MAX_BMP + 1) if is_space(ch)]
--
--        # Characters in \d, 21.2.2.12 CharacterClassEscape.
--        digit_chars = [ord(ch) for ch in string.digits]
--        assert all(ch <= MAX_ASCII for ch in digit_chars)
--
--        # Characters in \w, 21.2.2.12 CharacterClassEscape.
--        word_chars = [ord(ch) for ch in string.digits + string.ascii_letters + '_']
--        assert all(ch <= MAX_ASCII for ch in word_chars)
--
--        # Characters which case-fold to characters in \w.
--                                 [ch for ch in range(MAX_ASCII + 1, MAX_BMP + 1)
--                                  if casefolds_to_ascii(ch)])
--
--        # Surrogate characters.
--        surrogate_chars = [ch for ch in range(LEAD_SURROGATE_MIN, TRAIL_SURROGATE_MAX + 1)]
--
--        write(warning_message)
--        write(unicode_version_message.format(version))
--        println('#include "irregexp/RegExpCharacters.h"')
--        println('')
--        println('#include "mozilla/Assertions.h"')
--        println('')
--
--        println('char16_t')
--        println('js::irregexp::ConvertNonLatin1ToLatin1(char16_t c, bool unicode)')
--        println('{')
--        println('    MOZ_ASSERT(c > {}, "Character mustn\'t be Latin1");'.format(hex2(MAX_LATIN1)))
--        write_character_test(println, lambda ch: 'c == {}'.format(hex4(ch)), hex2, '0')
--        println('}')
--
--        character_range('Space', space_chars)
--        character_range('SpaceAndSurrogate', space_chars + surrogate_chars)
--
--        character_range('Word', word_chars)
--        character_range('IgnoreCaseWord', ignorecase_word_chars)
--        character_range('WordAndSurrogate', word_chars + surrogate_chars)
--        character_range('NegatedIgnoreCaseWordAndSurrogate',
--                        set(range(0, MAX_BMP + 1)) - set(ignorecase_word_chars + surrogate_chars))
--
--        character_range('Digit', digit_chars)
--        character_range('DigitAndSurrogate', digit_chars + surrogate_chars)
--
--        character_range('Surrogate', surrogate_chars)
--
--        character_range('LineTerminator', line_terminator)
--        character_range('LineTerminatorAndSurrogate', line_terminator + surrogate_chars)
--
- def update_unicode(args):
-     base_path = os.getcwd()
- 
-     version = args.version
-     if version is not None:
-         baseurl = 'https://unicode.org/Public'
-         if version == 'UNIDATA':
-             url = '%s/%s' % (baseurl, version)
-@@ -1555,17 +1343,16 @@ def update_unicode(args):
-             same_upper_table, same_upper_index,
-             non_bmp_lower_map, non_bmp_upper_map,
-             non_bmp_space_set,
-             non_bmp_id_start_set, non_bmp_id_cont_set,
-             codepoint_table, test_space_table
-         ) = process_unicode_data(unicode_data, derived_core_properties)
-         (
-             folding_table, folding_index,
--            non_bmp_folding_map, non_bmp_rev_folding_map,
-             folding_tests
-         ) = process_case_folding(case_folding)
-         (
-             unconditional_tolower, unconditional_toupper
-         ) = process_special_casing(special_casing, table, index)
- 
-     print('Generating...')
-     make_unicode_file(unicode_version,
-@@ -1573,22 +1360,17 @@ def update_unicode(args):
-                       same_upper_table, same_upper_index,
-                       folding_table, folding_index,
-                       non_bmp_space_set,
-                       non_bmp_id_start_set, non_bmp_id_cont_set,
-                       unconditional_toupper,
-                       codepoint_table)
-     make_non_bmp_file(unicode_version,
-                       non_bmp_lower_map, non_bmp_upper_map,
--                      non_bmp_folding_map, non_bmp_rev_folding_map,
-                       codepoint_table)
--    make_irregexp_tables(unicode_version,
--                         table, index,
--                         folding_table, folding_index,
--                         codepoint_table)
- 
-     make_bmp_mapping_test(unicode_version,
-                           codepoint_table, unconditional_tolower, unconditional_toupper)
-     make_non_bmp_mapping_test(unicode_version, non_bmp_upper_map, non_bmp_lower_map, codepoint_table)
-     make_space_test(unicode_version, test_space_table, codepoint_table)
-     make_regexp_space_test(unicode_version, test_space_table, codepoint_table)
-     make_icase_test(unicode_version, folding_tests, codepoint_table)
- 
-diff --git a/toolkit/components/extensions/MatchPattern.cpp b/toolkit/components/extensions/MatchPattern.cpp
---- a/toolkit/components/extensions/MatchPattern.cpp
-+++ b/toolkit/components/extensions/MatchPattern.cpp
-@@ -1,16 +1,17 @@
- /* -*-  Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
-  * You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #include "mozilla/extensions/MatchPattern.h"
- #include "mozilla/extensions/MatchGlob.h"
- 
-+#include "js/RegExp.h"  // JS::NewUCRegExpObject, JS::ExecuteRegExpNoStatics
- #include "mozilla/dom/ScriptSettings.h"
- #include "mozilla/HoldDropJSObjects.h"
- #include "mozilla/Unused.h"
- 
- #include "nsGkAtoms.h"
- #include "nsIProtocolHandler.h"
- #include "nsIURL.h"
- #include "nsNetUtil.h"
-@@ -692,17 +693,17 @@ MatchGlob::Init(JSContext* aCx, const ns
-     }
-   }
- 
-   escaped.Append('$');
- 
-   // TODO: Switch to the Rust regexp crate, when Rust integration is easier.
-   // It uses a much more efficient, linear time matching algorithm, and
-   // doesn't require special casing for the literal and prefix cases.
--  mRegExp = JS_NewUCRegExpObject(aCx, escaped.get(), escaped.Length(), 0);
-+  mRegExp = JS::NewUCRegExpObject(aCx, escaped.get(), escaped.Length(), 0);
-   if (mRegExp) {
-     mozilla::HoldJSObjects(this);
-   } else {
-     aRv.NoteJSContextException(aCx);
-   }
- }
- 
- bool
-@@ -716,17 +717,17 @@ MatchGlob::Matches(const nsAString& aStr
-     JSAutoCompartment ac(cx, mRegExp);
- 
-     JS::RootedObject regexp(cx, mRegExp);
-     JS::RootedValue result(cx);
- 
-     nsString input(aString);
- 
-     size_t index = 0;
--    if (!JS_ExecuteRegExpNoStatics(cx, regexp, input.BeginWriting(), aString.Length(),
-+    if (!JS::ExecuteRegExpNoStatics(cx, regexp, input.BeginWriting(), aString.Length(),
-                                    &index, true, &result)) {
-       return false;
-     }
- 
-     return result.isBoolean() && result.toBoolean();
-   }
- 
-   if (mIsPrefix) {

+ 0 - 63
frg/work-js/mozilla-release/patches/bbb.patch

@@ -1,63 +0,0 @@
-# HG changeset patch
-# Parent  e3e430717f903cad818bd0ae1332c86dddd82d4b
-
-diff --git a/js/src/irregexp/RegExpAPI.cpp b/js/src/irregexp/RegExpAPI.cpp
---- a/js/src/irregexp/RegExpAPI.cpp
-+++ b/js/src/irregexp/RegExpAPI.cpp
-@@ -355,17 +355,16 @@ class RegExpDepthCheck final : public v8
-     return !!root->Accept(this, nullptr);
-   }
- 
-   // Leaf nodes with no children
- #define LEAF_DEPTH(Kind)                                                \
-   void* Visit##Kind(v8::internal::RegExp##Kind* node, void*) override { \
-     uint8_t padding[FRAME_PADDING];                                     \
-     dummy_ = padding; /* Prevent padding from being optimized away.*/   \
--    AutoCheckRecursionLimit recursion(cx_);                             \
-     return (void*)CheckRecursionLimitDontReport(cx_);                   \
-   }
- 
-   LEAF_DEPTH(Assertion)
-   LEAF_DEPTH(Atom)
-   LEAF_DEPTH(BackReference)
-   LEAF_DEPTH(CharacterClass)
-   LEAF_DEPTH(Empty)
-@@ -388,17 +387,16 @@ class RegExpDepthCheck final : public v8
-   WRAPPER_DEPTH(Lookaround)
-   WRAPPER_DEPTH(Quantifier)
- #undef WRAPPER_DEPTH
- 
-   void* VisitAlternative(v8::internal::RegExpAlternative* node,
-                          void*) override {
-     uint8_t padding[FRAME_PADDING];
-     dummy_ = padding; /* Prevent padding from being optimized away.*/
--    AutoCheckRecursionLimit recursion(cx_);    
-     if (!CheckRecursionLimitDontReport(cx_)) {
-       return nullptr;
-     }
-     for (auto* child : *node->nodes()) {
-       if (!child->Accept(this, nullptr)) {
-         return nullptr;
-       }
-     }
-diff --git a/js/src/irregexp/RegExpShim.cpp b/js/src/irregexp/RegExpShim.cpp
---- a/js/src/irregexp/RegExpShim.cpp
-+++ b/js/src/irregexp/RegExpShim.cpp
-@@ -129,17 +129,16 @@ PseudoHandle<T> Isolate::takeOwnership(v
- PseudoHandle<ByteArrayData> ByteArray::takeOwnership(Isolate* isolate) {
-   PseudoHandle<ByteArrayData> result =
-       isolate->takeOwnership<ByteArrayData>(value().toPrivate());
-   setValue(JS::PrivateValue(nullptr));
-   return result;
- }
- 
- void Isolate::trace(JSTracer* trc) {
--  AssertRootMarkingPhase(trc);
-   for (auto iter = handleArena_.Iter(); !iter.Done(); iter.Next()) {
-     auto& elem = iter.Get();
-     JS::GCPolicy<JS::Value>::trace(trc, &elem, "Isolate handle arena");
-   }
- }
- 
- size_t Isolate::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
-   size_t size = mallocSizeOf(this);

+ 0 - 3043
frg/work-js/mozilla-release/patches/mozilla-central-push_421127.patch

@@ -1,3043 +0,0 @@
-# HG changeset patch
-# User Miko Mynttinen <mikokm@gmail.com>
-# Date 1527868747 -7200
-#      Fri Jun 01 17:59:07 2018 +0200
-# Node ID a0d11b55d5957a488b41420c4f6cc178df7cd2e7
-# Parent  466387c9cc93e4cc150e927735b581ee01151d4b
-Bug 1465060 - Part 1: Fix warnings for std::move() use r=froydnj
-
-MozReview-Commit-ID: HpdFXqQdIOO
-
-diff --git a/accessible/ipc/other/ProxyAccessible.cpp b/accessible/ipc/other/ProxyAccessible.cpp
---- a/accessible/ipc/other/ProxyAccessible.cpp
-+++ b/accessible/ipc/other/ProxyAccessible.cpp
-@@ -73,17 +73,17 @@ ProxyAccessible::RelationByType(Relation
-                                      &targetIDs);
- 
-   size_t targetCount = targetIDs.Length();
-   nsTArray<ProxyAccessible*> targets(targetCount);
-   for (size_t i = 0; i < targetCount; i++)
-     if (ProxyAccessible* proxy = mDoc->GetAccessible(targetIDs[i]))
-       targets.AppendElement(proxy);
- 
--  return std::move(targets);
-+  return targets;
- }
- 
- void
- ProxyAccessible::Relations(nsTArray<RelationType>* aTypes,
-                            nsTArray<nsTArray<ProxyAccessible*>>* aTargetSets)
-   const
- {
-   nsTArray<RelationTargets> ipcRelations;
-diff --git a/devtools/shared/heapsnapshot/DeserializedNode.cpp b/devtools/shared/heapsnapshot/DeserializedNode.cpp
---- a/devtools/shared/heapsnapshot/DeserializedNode.cpp
-+++ b/devtools/shared/heapsnapshot/DeserializedNode.cpp
-@@ -82,18 +82,18 @@ class DeserializedEdgeRange : public Edg
-   void settle() {
-     if (i >= node->edges.length()) {
-       front_ = nullptr;
-       return;
-     }
- 
-     auto& edge = node->edges[i];
-     auto referent = node->getEdgeReferent(edge);
--    currentEdge = std::move(Edge(edge.name ? NS_strdup(edge.name) : nullptr,
--                                     referent));
-+    currentEdge = Edge(edge.name
-+                ? NS_strdup(edge.name) : nullptr, referent);
-     front_ = &currentEdge;
-   }
- 
- public:
-   explicit DeserializedEdgeRange(DeserializedNode& node)
-     : node(&node)
-     , i(0)
-   {
-diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
---- a/docshell/base/nsDocShell.cpp
-+++ b/docshell/base/nsDocShell.cpp
-@@ -2860,17 +2860,17 @@ nsDocShell::MaybeCreateInitialClientSour
- }
- 
- Maybe<ClientInfo>
- nsDocShell::GetInitialClientInfo() const
- {
-   if (mInitialClientSource) {
-     Maybe<ClientInfo> result;
-     result.emplace(mInitialClientSource->Info());
--    return std::move(result);
-+    return result;
-   }
- 
-   nsGlobalWindowInner* innerWindow =
-     mScriptGlobal ? mScriptGlobal->GetCurrentInnerWindowInternal() : nullptr;
-   nsIDocument* doc = innerWindow ? innerWindow->GetExtantDoc() : nullptr;
- 
-   if (!doc || !doc->IsInitialDocument()) {
-     return Maybe<ClientInfo>();
-@@ -14062,20 +14062,20 @@ nsDocShell::NotifyJSRunToCompletionStart
-                                          const uint32_t aLineNumber,
-                                          JS::Handle<JS::Value> aAsyncStack,
-                                          const char* aAsyncCause)
- {
-   // If first start, mark interval start.
-   if (mJSRunToCompletionDepth == 0) {
-     RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
-     if (timelines && timelines->HasConsumer(this)) {
--      timelines->AddMarkerForDocShell(this, std::move(
-+      timelines->AddMarkerForDocShell(this,
-         mozilla::MakeUnique<JavascriptTimelineMarker>(
-           aReason, aFunctionName, aFilename, aLineNumber, MarkerTracingType::START,
--          aAsyncStack, aAsyncCause)));
-+          aAsyncStack, aAsyncCause));
-     }
-   }
- 
-   mJSRunToCompletionDepth++;
- }
- 
- void
- nsDocShell::NotifyJSRunToCompletionStop()
-diff --git a/docshell/base/timeline/AutoRestyleTimelineMarker.cpp b/docshell/base/timeline/AutoRestyleTimelineMarker.cpp
---- a/docshell/base/timeline/AutoRestyleTimelineMarker.cpp
-+++ b/docshell/base/timeline/AutoRestyleTimelineMarker.cpp
-@@ -27,34 +27,34 @@ AutoRestyleTimelineMarker::AutoRestyleTi
-   }
- 
-   RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
-   if (!timelines || !timelines->HasConsumer(aDocShell)) {
-     return;
-   }
- 
-   mDocShell = aDocShell;
--  timelines->AddMarkerForDocShell(mDocShell, std::move(
-+  timelines->AddMarkerForDocShell(mDocShell,
-     MakeUnique<RestyleTimelineMarker>(
-       mIsAnimationOnly,
--      MarkerTracingType::START)));
-+      MarkerTracingType::START));
- }
- 
- AutoRestyleTimelineMarker::~AutoRestyleTimelineMarker()
- {
-   MOZ_ASSERT(NS_IsMainThread());
- 
-   if (!mDocShell) {
-     return;
-   }
- 
-   RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
-   if (!timelines || !timelines->HasConsumer(mDocShell)) {
-     return;
-   }
- 
--  timelines->AddMarkerForDocShell(mDocShell, std::move(
-+  timelines->AddMarkerForDocShell(mDocShell,
-     MakeUnique<RestyleTimelineMarker>(
-       mIsAnimationOnly,
--      MarkerTracingType::END)));
-+      MarkerTracingType::END));
- }
- 
- } // namespace mozilla
-diff --git a/docshell/base/timeline/TimelineConsumers.cpp b/docshell/base/timeline/TimelineConsumers.cpp
---- a/docshell/base/timeline/TimelineConsumers.cpp
-+++ b/docshell/base/timeline/TimelineConsumers.cpp
-@@ -180,30 +180,30 @@ TimelineConsumers::IsEmpty()
- void
- TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
-                                         const char* aName,
-                                         MarkerTracingType aTracingType,
-                                         MarkerStackRequest aStackRequest)
- {
-   MOZ_ASSERT(NS_IsMainThread());
-   if (HasConsumer(aDocShell)) {
--    aDocShell->mObserved->AddMarker(std::move(MakeUnique<TimelineMarker>(aName, aTracingType, aStackRequest)));
-+    aDocShell->mObserved->AddMarker(MakeUnique<TimelineMarker>(aName, aTracingType, aStackRequest));
-   }
- }
- 
- void
- TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
-                                         const char* aName,
-                                         const TimeStamp& aTime,
-                                         MarkerTracingType aTracingType,
-                                         MarkerStackRequest aStackRequest)
- {
-   MOZ_ASSERT(NS_IsMainThread());
-   if (HasConsumer(aDocShell)) {
--    aDocShell->mObserved->AddMarker(std::move(MakeUnique<TimelineMarker>(aName, aTime, aTracingType, aStackRequest)));
-+    aDocShell->mObserved->AddMarker(MakeUnique<TimelineMarker>(aName, aTime, aTracingType, aStackRequest));
-   }
- }
- 
- void
- TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
-                                         UniquePtr<AbstractTimelineMarker>&& aMarker)
- {
-   MOZ_ASSERT(NS_IsMainThread());
-diff --git a/dom/animation/EffectSet.h b/dom/animation/EffectSet.h
---- a/dom/animation/EffectSet.h
-+++ b/dom/animation/EffectSet.h
-@@ -85,17 +85,17 @@ public:
-   // This allows us to avoid exposing mEffects directly and saves the
-   // caller from having to dereference hashtable iterators using
-   // the rather complicated: iter.Get()->GetKey().
-   class Iterator
-   {
-   public:
-     explicit Iterator(EffectSet& aEffectSet)
-       : mEffectSet(aEffectSet)
--      , mHashIterator(std::move(aEffectSet.mEffects.Iter()))
-+      , mHashIterator(aEffectSet.mEffects.Iter())
-       , mIsEndIterator(false)
-     {
- #ifdef DEBUG
-       mEffectSet.mActiveIterators++;
- #endif
-     }
- 
-     Iterator(Iterator&& aOther)
-diff --git a/dom/base/CustomElementRegistry.cpp b/dom/base/CustomElementRegistry.cpp
---- a/dom/base/CustomElementRegistry.cpp
-+++ b/dom/base/CustomElementRegistry.cpp
-@@ -488,17 +488,17 @@ CustomElementRegistry::CreateCustomEleme
- 
-   if (aArgs) {
-     callback->SetArgs(*aArgs);
-   }
- 
-   if (aAdoptedCallbackArgs) {
-     callback->SetAdoptedCallbackArgs(*aAdoptedCallbackArgs);
-   }
--  return std::move(callback);
-+  return callback;
- }
- 
- /* static */ void
- CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
-                                                 Element* aCustomElement,
-                                                 LifecycleCallbackArgs* aArgs,
-                                                 LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
-                                                 CustomElementDefinition* aDefinition)
-diff --git a/dom/base/nsContentPermissionHelper.cpp b/dom/base/nsContentPermissionHelper.cpp
---- a/dom/base/nsContentPermissionHelper.cpp
-+++ b/dom/base/nsContentPermissionHelper.cpp
-@@ -427,17 +427,17 @@ nsContentPermissionUtils::GetContentPerm
- {
-   nsTArray<PContentPermissionRequestParent*> parentArray;
-   for (auto& it : ContentPermissionRequestParentMap()) {
-     if (it.second == aTabId) {
-       parentArray.AppendElement(it.first);
-     }
-   }
- 
--  return std::move(parentArray);
-+  return parentArray;
- }
- 
- /* static */ void
- nsContentPermissionUtils::NotifyRemoveContentPermissionRequestParent(
-   PContentPermissionRequestParent* aParent)
- {
-   auto it = ContentPermissionRequestParentMap().find(aParent);
-   MOZ_ASSERT(it != ContentPermissionRequestParentMap().end());
-@@ -450,17 +450,17 @@ nsContentPermissionUtils::GetContentPerm
- {
-   nsTArray<PContentPermissionRequestChild*> childArray;
-   for (auto& it : ContentPermissionRequestChildMap()) {
-     if (it.second == aTabId) {
-       childArray.AppendElement(it.first);
-     }
-   }
- 
--  return std::move(childArray);
-+  return childArray;
- }
- 
- /* static */ void
- nsContentPermissionUtils::NotifyRemoveContentPermissionRequestChild(
-   PContentPermissionRequestChild* aChild)
- {
-   auto it = ContentPermissionRequestChildMap().find(aChild);
-   MOZ_ASSERT(it != ContentPermissionRequestChildMap().end());
-diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp
---- a/dom/base/nsDocument.cpp
-+++ b/dom/base/nsDocument.cpp
-@@ -5560,39 +5560,39 @@ nsIDocument::GetAnonRootIfInAnonymousCon
-   return nullptr;
- }
- 
- Maybe<ClientInfo>
- nsIDocument::GetClientInfo() const
- {
-   nsPIDOMWindowInner* inner = GetInnerWindow();
-   if (inner) {
--    return std::move(inner->GetClientInfo());
--  }
--  return std::move(Maybe<ClientInfo>());
-+    return inner->GetClientInfo();
-+  }
-+  return Maybe<ClientInfo>();
- }
- 
- Maybe<ClientState>
- nsIDocument::GetClientState() const
- {
-   nsPIDOMWindowInner* inner = GetInnerWindow();
-   if (inner) {
--    return std::move(inner->GetClientState());
--  }
--  return std::move(Maybe<ClientState>());
-+    return inner->GetClientState();
-+  }
-+  return Maybe<ClientState>();
- }
- 
- Maybe<ServiceWorkerDescriptor>
- nsIDocument::GetController() const
- {
-   nsPIDOMWindowInner* inner = GetInnerWindow();
-   if (inner) {
--    return std::move(inner->GetController());
--  }
--  return std::move(Maybe<ServiceWorkerDescriptor>());
-+    return inner->GetController();
-+  }
-+  return Maybe<ServiceWorkerDescriptor>();
- }
- 
- //
- // nsIDocument interface
- //
- DocumentType*
- nsIDocument::GetDoctype() const
- {
-diff --git a/dom/base/nsGlobalWindowInner.cpp b/dom/base/nsGlobalWindowInner.cpp
---- a/dom/base/nsGlobalWindowInner.cpp
-+++ b/dom/base/nsGlobalWindowInner.cpp
-@@ -2315,35 +2315,35 @@ void
- nsPIDOMWindowInner::SyncStateFromParentWindow()
- {
-   nsGlobalWindowInner::Cast(this)->SyncStateFromParentWindow();
- }
- 
- Maybe<ClientInfo>
- nsPIDOMWindowInner::GetClientInfo() const
- {
--  return std::move(nsGlobalWindowInner::Cast(this)->GetClientInfo());
-+  return nsGlobalWindowInner::Cast(this)->GetClientInfo();
- }
- 
- Maybe<ClientState>
- nsPIDOMWindowInner::GetClientState() const
- {
--  return std::move(nsGlobalWindowInner::Cast(this)->GetClientState());
-+  return nsGlobalWindowInner::Cast(this)->GetClientState();
- }
- 
- Maybe<ServiceWorkerDescriptor>
- nsPIDOMWindowInner::GetController() const
- {
--  return std::move(nsGlobalWindowInner::Cast(this)->GetController());
-+  return nsGlobalWindowInner::Cast(this)->GetController();
- }
- 
- RefPtr<mozilla::dom::ServiceWorker>
- nsPIDOMWindowInner::GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor)
- {
--  return std::move(nsGlobalWindowInner::Cast(this)->GetOrCreateServiceWorker(aDescriptor));
-+  return nsGlobalWindowInner::Cast(this)->GetOrCreateServiceWorker(aDescriptor);
- }
- 
- void
- nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
- {
-   nsGlobalWindowInner::Cast(this)->NoteCalledRegisterForServiceWorkerScope(aScope);
- }
- 
-@@ -5493,17 +5493,17 @@ nsGlobalWindowInner::ShowSlowScriptDialo
-   auto getString = [&] (const char* name,
-                         nsContentUtils::PropertiesFile propFile = nsContentUtils::eDOM_PROPERTIES) {
-     nsAutoString result;
-     nsresult rv = nsContentUtils::GetLocalizedString(
-       propFile, name, result);
- 
-     // GetStringFromName can return NS_OK and still give nullptr string
-     failed = failed || NS_FAILED(rv) || result.IsEmpty();
--    return std::move(result);
-+    return result;
-   };
- 
-   bool isAddonScript = !aAddonId.IsEmpty();
-   bool showDebugButton = debugCallback && !isAddonScript;
- 
-   // Get localizable strings
- 
-   nsAutoString title, checkboxMsg, debugButton, msg;
-@@ -6324,43 +6324,43 @@ nsGlobalWindowInner::CallOnChildren(Meth
- Maybe<ClientInfo>
- nsGlobalWindowInner::GetClientInfo() const
- {
-   MOZ_ASSERT(NS_IsMainThread());
-   Maybe<ClientInfo> clientInfo;
-   if (mClientSource) {
-     clientInfo.emplace(mClientSource->Info());
-   }
--  return std::move(clientInfo);
-+  return clientInfo;
- }
- 
- Maybe<ClientState>
- nsGlobalWindowInner::GetClientState() const
- {
-   MOZ_ASSERT(NS_IsMainThread());
-   Maybe<ClientState> clientState;
-   if (mClientSource) {
-     ClientState state;
-     nsresult rv = mClientSource->SnapshotState(&state);
-     if (NS_SUCCEEDED(rv)) {
-       clientState.emplace(state);
-     }
-   }
--  return std::move(clientState);
-+  return clientState;
- }
- 
- Maybe<ServiceWorkerDescriptor>
- nsGlobalWindowInner::GetController() const
- {
-   MOZ_ASSERT(NS_IsMainThread());
-   Maybe<ServiceWorkerDescriptor> controller;
-   if (mClientSource) {
-     controller = mClientSource->GetController();
-   }
--  return std::move(controller);
-+  return controller;
- }
- 
- RefPtr<ServiceWorker>
- nsGlobalWindowInner::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor)
- {
-   MOZ_ASSERT(NS_IsMainThread());
-   RefPtr<ServiceWorker> ref;
-   ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget, bool* aDoneOut) {
-diff --git a/dom/canvas/ImageBitmap.cpp b/dom/canvas/ImageBitmap.cpp
---- a/dom/canvas/ImageBitmap.cpp
-+++ b/dom/canvas/ImageBitmap.cpp
-@@ -799,17 +799,17 @@ ImageBitmap::ToCloneData() const
-   UniquePtr<ImageBitmapCloneData> result(new ImageBitmapCloneData());
-   result->mPictureRect = mPictureRect;
-   result->mAlphaType = mAlphaType;
-   result->mIsCroppingAreaOutSideOfSourceImage = mIsCroppingAreaOutSideOfSourceImage;
-   RefPtr<SourceSurface> surface = mData->GetAsSourceSurface();
-   result->mSurface = surface->GetDataSurface();
-   MOZ_ASSERT(result->mSurface);
- 
--  return std::move(result);
-+  return result;
- }
- 
- /* static */ already_AddRefed<ImageBitmap>
- ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal,
-                                  ImageBitmapCloneData* aData)
- {
-   RefPtr<layers::Image> data = CreateImageFromSurface(aData->mSurface);
- 
-diff --git a/dom/canvas/WebGLFormats.cpp b/dom/canvas/WebGLFormats.cpp
---- a/dom/canvas/WebGLFormats.cpp
-+++ b/dom/canvas/WebGLFormats.cpp
-@@ -822,17 +822,17 @@ FormatUsageAuthority::CreateForWebGL1(gl
-     ptr->AllowRBFormat(LOCAL_GL_DEPTH_STENCIL,
-                        ptr->GetUsage(EffectiveFormat::DEPTH24_STENCIL8));
- 
-     ////////////////////////////////////////////////////////////////////////////
- 
-     if (!AddUnsizedFormats(ptr, gl))
-         return nullptr;
- 
--    return std::move(ret);
-+    return ret;
- }
- 
- UniquePtr<FormatUsageAuthority>
- FormatUsageAuthority::CreateForWebGL2(gl::GLContext* gl)
- {
-     UniquePtr<FormatUsageAuthority> ret(new FormatUsageAuthority);
-     const auto ptr = ret.get();
- 
-@@ -1057,17 +1057,17 @@ FormatUsageAuthority::CreateForWebGL2(gl
-         AddSimpleUnsized(ptr, LOCAL_GL_RGB , LOCAL_GL_FLOAT, EffectiveFormat::RGB32F );
- 
-         AddSimpleUnsized(ptr, LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES, EffectiveFormat::RGBA16F);
-         AddSimpleUnsized(ptr, LOCAL_GL_RGB , LOCAL_GL_HALF_FLOAT_OES, EffectiveFormat::RGB16F );
-     }
- 
-     ////////////////////////////////////
- 
--    return std::move(ret);
-+    return ret;
- }
- 
- //////////////////////////////////////////////////////////////////////////////////////////
- 
- void
- FormatUsageAuthority::AddTexUnpack(FormatUsageInfo* usage, const PackingInfo& pi,
-                                    const DriverUnpackInfo& dui)
- {
-diff --git a/dom/canvas/WebGLTextureUpload.cpp b/dom/canvas/WebGLTextureUpload.cpp
---- a/dom/canvas/WebGLTextureUpload.cpp
-+++ b/dom/canvas/WebGLTextureUpload.cpp
-@@ -222,17 +222,17 @@ FromPboOffset(WebGLContext* webgl, const
-                                              isClientData, ptr, availBufferBytes);
- }
- 
- static UniquePtr<webgl::TexUnpackBlob>
- FromImageBitmap(WebGLContext* webgl, const char* funcName, TexImageTarget target,
-                 uint32_t width, uint32_t height, uint32_t depth,
-                 const dom::ImageBitmap& imageBitmap)
- {
--    UniquePtr<dom::ImageBitmapCloneData> cloneData = std::move(imageBitmap.ToCloneData());
-+    UniquePtr<dom::ImageBitmapCloneData> cloneData = imageBitmap.ToCloneData();
-     if (!cloneData) {
-       return nullptr;
-     }
- 
-     const RefPtr<gfx::DataSourceSurface> surf = cloneData->mSurface;
- 
-     if (!width) {
-         width = surf->GetSize().width;
-@@ -455,17 +455,17 @@ ValidateTexOrSubImage(WebGLContext* webg
-     if (!ValidateViewType(webgl, funcName, pi.type, src))
-         return nullptr;
- 
-     auto blob = webgl->From(funcName, target, rawWidth, rawHeight, rawDepth, border, src,
-                             scopedArr);
-     if (!blob || !blob->Validate(webgl, funcName, pi))
-         return nullptr;
- 
--    return std::move(blob);
-+    return blob;
- }
- 
- void
- WebGLTexture::TexImage(const char* funcName, TexImageTarget target, GLint level,
-                        GLenum internalFormat, GLsizei width, GLsizei height,
-                        GLsizei depth, GLint border, const webgl::PackingInfo& pi,
-                        const TexImageSource& src)
- {
-diff --git a/dom/clients/manager/ClientHandle.cpp b/dom/clients/manager/ClientHandle.cpp
---- a/dom/clients/manager/ClientHandle.cpp
-+++ b/dom/clients/manager/ClientHandle.cpp
-@@ -198,13 +198,13 @@ ClientHandle::OnDetach()
-   if (!mDetachPromise) {
-     mDetachPromise = new GenericPromise::Private(__func__);
-     if (IsShutdown()) {
-       mDetachPromise->Resolve(true, __func__);
-     }
-   }
- 
-   RefPtr<GenericPromise> ref(mDetachPromise);
--  return std::move(ref);
-+  return ref;
- }
- 
- } // namespace dom
- } // namespace mozilla
-diff --git a/dom/clients/manager/ClientInfo.cpp b/dom/clients/manager/ClientInfo.cpp
---- a/dom/clients/manager/ClientInfo.cpp
-+++ b/dom/clients/manager/ClientInfo.cpp
-@@ -140,13 +140,13 @@ ClientInfo::IsPrivateBrowsing() const
-   }
- }
- 
- nsCOMPtr<nsIPrincipal>
- ClientInfo::GetPrincipal() const
- {
-   MOZ_ASSERT(NS_IsMainThread());
-   nsCOMPtr<nsIPrincipal> ref = PrincipalInfoToPrincipal(PrincipalInfo());
--  return std::move(ref);
-+  return ref;
- }
- 
- } // namespace dom
- } // namespace mozilla
-diff --git a/dom/clients/manager/ClientManager.cpp b/dom/clients/manager/ClientManager.cpp
---- a/dom/clients/manager/ClientManager.cpp
-+++ b/dom/clients/manager/ClientManager.cpp
-@@ -131,30 +131,30 @@ ClientManager::CreateSourceInternal(Clie
-   if (NS_WARN_IF(NS_FAILED(rv))) {
-     // If we can't even get a UUID, at least make sure not to use a garbage
-     // value.  Instead return a shutdown ClientSource with a zero'd id.
-     // This should be exceptionally rare, if it happens at all.
-     id.Clear();
-     ClientSourceConstructorArgs args(id, aType, aPrincipal, TimeStamp::Now());
-     UniquePtr<ClientSource> source(new ClientSource(this, aEventTarget, args));
-     source->Shutdown();
--    return std::move(source);
-+    return source;
-   }
- 
-   ClientSourceConstructorArgs args(id, aType, aPrincipal, TimeStamp::Now());
-   UniquePtr<ClientSource> source(new ClientSource(this, aEventTarget, args));
- 
-   if (IsShutdown()) {
-     source->Shutdown();
--    return std::move(source);
-+    return source;
-   }
- 
-   source->Activate(GetActor());
- 
--  return std::move(source);
-+  return source;
- }
- 
- already_AddRefed<ClientHandle>
- ClientManager::CreateHandleInternal(const ClientInfo& aClientInfo,
-                                     nsISerialEventTarget* aSerialEventTarget)
- {
-   NS_ASSERT_OWNINGTHREAD(ClientManager);
-   MOZ_DIAGNOSTIC_ASSERT(aSerialEventTarget);
-diff --git a/dom/clients/manager/ClientManagerService.cpp b/dom/clients/manager/ClientManagerService.cpp
---- a/dom/clients/manager/ClientManagerService.cpp
-+++ b/dom/clients/manager/ClientManagerService.cpp
-@@ -433,18 +433,18 @@ ClientManagerService::MatchAll(const Cli
- 
-       if(controller.ref().Id() != swd.Id() ||
-          controller.ref().Scope() != swd.Scope()) {
-         continue;
-       }
-     }
- 
-     promiseList->AddPromise(
--      source->StartOp(std::move(ClientGetInfoAndStateArgs(source->Info().Id(),
--                                                     source->Info().PrincipalInfo()))));
-+      source->StartOp(ClientGetInfoAndStateArgs(source->Info().Id(),
-+                                                source->Info().PrincipalInfo())));
-   }
- 
-   // Maybe finish the promise now in case we didn't find any matching clients.
-   promiseList->MaybeFinish();
- 
-   return promiseList->GetResultPromise();
- }
- 
-diff --git a/dom/console/Console.cpp b/dom/console/Console.cpp
---- a/dom/console/Console.cpp
-+++ b/dom/console/Console.cpp
-@@ -2882,36 +2882,36 @@ Console::MonotonicTimer(JSContext* aCx, 
-         return false;
-       }
- 
-       nsAutoJSString key;
-       if (!key.init(aCx, jsString)) {
-         return false;
-       }
- 
--      timelines->AddMarkerForDocShell(docShell, std::move(
--        MakeUnique<TimestampTimelineMarker>(key)));
-+      timelines->AddMarkerForDocShell(docShell,
-+        MakeUnique<TimestampTimelineMarker>(key));
-     }
-     // For `console.time(foo)` and `console.timeEnd(foo)`.
-     else if (isTimelineRecording && aData.Length() == 1) {
-       JS::Rooted<JS::Value> value(aCx, aData[0]);
-       JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, value));
-       if (!jsString) {
-         return false;
-       }
- 
-       nsAutoJSString key;
-       if (!key.init(aCx, jsString)) {
-         return false;
-       }
- 
--      timelines->AddMarkerForDocShell(docShell, std::move(
-+      timelines->AddMarkerForDocShell(docShell,
-         MakeUnique<ConsoleTimelineMarker>(
-           key, aMethodName == MethodTime ? MarkerTracingType::START
--                                         : MarkerTracingType::END)));
-+                                         : MarkerTracingType::END));
-     }
- 
-     return true;
-   }
- 
-   if (NS_IsMainThread()) {
-     *aTimeStamp = (TimeStamp::Now() - mCreationTimeStamp).ToMilliseconds();
-     return true;
-diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp
---- a/dom/events/EventListenerManager.cpp
-+++ b/dom/events/EventListenerManager.cpp
-@@ -1240,19 +1240,19 @@ EventListenerManager::HandleEventInterna
-                 listener->mListenerType != Listener::eNativeListener) {
-               docShell = nsContentUtils::GetDocShellForEventTarget(mTarget);
-               if (docShell) {
-                 if (timelines && timelines->HasConsumer(docShell)) {
-                   needsEndEventMarker = true;
-                   nsAutoString typeStr;
-                   (*aDOMEvent)->GetType(typeStr);
-                   uint16_t phase = (*aDOMEvent)->EventPhase();
--                  timelines->AddMarkerForDocShell(docShell, std::move(
-+                  timelines->AddMarkerForDocShell(docShell,
-                     MakeUnique<EventTimelineMarker>(
--                      typeStr, phase, MarkerTracingType::START)));
-+                      typeStr, phase, MarkerTracingType::START));
-                 }
-               }
-             }
- 
-             aEvent->mFlags.mInPassiveListener = listener->mFlags.mPassive;
-             Maybe<Listener> listenerHolder;
-             if (listener->mFlags.mOnce) {
-               // Move the listener to the stack before handling the event.
-diff --git a/dom/file/uri/BlobURLProtocolHandler.cpp b/dom/file/uri/BlobURLProtocolHandler.cpp
---- a/dom/file/uri/BlobURLProtocolHandler.cpp
-+++ b/dom/file/uri/BlobURLProtocolHandler.cpp
-@@ -541,17 +541,17 @@ private:
-   {
-     nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
-     NS_ENSURE_TRUE(!!svc, nullptr);
- 
-     nsCOMPtr<nsIAsyncShutdownClient> phase;
-     nsresult rv = svc->GetXpcomWillShutdown(getter_AddRefs(phase));
-     NS_ENSURE_SUCCESS(rv, nullptr);
- 
--    return std::move(phase);
-+    return phase;
-   }
- 
-   nsCString mURI;
-   bool mBroadcastToOtherProcesses;
- 
-   nsCOMPtr<nsITimer> mTimer;
- };
- 
-diff --git a/dom/geolocation/nsGeolocation.cpp b/dom/geolocation/nsGeolocation.cpp
---- a/dom/geolocation/nsGeolocation.cpp
-+++ b/dom/geolocation/nsGeolocation.cpp
-@@ -1159,17 +1159,17 @@ void
- Geolocation::GetCurrentPosition(PositionCallback& aCallback,
-                                 PositionErrorCallback* aErrorCallback,
-                                 const PositionOptions& aOptions,
-                                 CallerType aCallerType,
-                                 ErrorResult& aRv)
- {
-   nsresult rv = GetCurrentPosition(GeoPositionCallback(&aCallback),
-                                    GeoPositionErrorCallback(aErrorCallback),
--                                   std::move(CreatePositionOptionsCopy(aOptions)),
-+                                   CreatePositionOptionsCopy(aOptions),
-                                    aCallerType);
- 
-   if (NS_FAILED(rv)) {
-     aRv.Throw(rv);
-   }
- }
- 
- static nsIEventTarget* MainThreadTarget(Geolocation* geo)
-@@ -1237,17 +1237,17 @@ Geolocation::WatchPosition(PositionCallb
-                            PositionErrorCallback* aErrorCallback,
-                            const PositionOptions& aOptions,
-                            CallerType aCallerType,
-                            ErrorResult& aRv)
- {
-   int32_t ret = 0;
-   nsresult rv = WatchPosition(GeoPositionCallback(&aCallback),
-                               GeoPositionErrorCallback(aErrorCallback),
--                              std::move(CreatePositionOptionsCopy(aOptions)),
-+                              CreatePositionOptionsCopy(aOptions),
-                               aCallerType,
-                               &ret);
- 
-   if (NS_FAILED(rv)) {
-     aRv.Throw(rv);
-   }
- 
-   return ret;
-diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp
---- a/dom/ipc/ContentParent.cpp
-+++ b/dom/ipc/ContentParent.cpp
-@@ -4464,18 +4464,18 @@ ContentParent::RecvNotifyTabDestroying(c
- {
-   NotifyTabDestroying(aTabId, aCpId);
-   return IPC_OK();
- }
- 
- nsTArray<TabContext>
- ContentParent::GetManagedTabContext()
- {
--  return std::move(ContentProcessManager::GetSingleton()->
--          GetTabContextByContentProcess(this->ChildID()));
-+  return ContentProcessManager::GetSingleton()->
-+    GetTabContextByContentProcess(this->ChildID());
- }
- 
- mozilla::docshell::POfflineCacheUpdateParent*
- ContentParent::AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI,
-                                               const URIParams& aDocumentURI,
-                                               const PrincipalInfo& aLoadingPrincipalInfo,
-                                               const bool& aStickDocument)
- {
-diff --git a/dom/ipc/ContentProcessManager.cpp b/dom/ipc/ContentProcessManager.cpp
---- a/dom/ipc/ContentProcessManager.cpp
-+++ b/dom/ipc/ContentProcessManager.cpp
-@@ -120,26 +120,26 @@ nsTArray<ContentParentId>
- ContentProcessManager::GetAllChildProcessById(const ContentParentId& aParentCpId)
- {
-   MOZ_ASSERT(NS_IsMainThread());
- 
-   nsTArray<ContentParentId> cpIdArray;
-   auto iter = mContentParentMap.find(aParentCpId);
-   if (NS_WARN_IF(iter == mContentParentMap.end())) {
-     ASSERT_UNLESS_FUZZING();
--    return std::move(cpIdArray);
-+    return cpIdArray;
-   }
- 
-   for (auto cpIter = iter->second.mChildrenCpId.begin();
-        cpIter != iter->second.mChildrenCpId.end();
-        ++cpIter) {
-     cpIdArray.AppendElement(*cpIter);
-   }
- 
--  return std::move(cpIdArray);
-+  return cpIdArray;
- }
- 
- bool
- ContentProcessManager::RegisterRemoteFrame(const TabId& aTabId,
-                                            const ContentParentId& aOpenerCpId,
-                                            const TabId& aOpenerTabId,
-                                            const IPCTabContext& aContext,
-                                            const ContentParentId& aChildCpId)
-@@ -231,26 +231,26 @@ nsTArray<TabContext>
- ContentProcessManager::GetTabContextByContentProcess(const ContentParentId& aChildCpId)
- {
-   MOZ_ASSERT(NS_IsMainThread());
- 
-   nsTArray<TabContext> tabContextArray;
-   auto iter = mContentParentMap.find(aChildCpId);
-   if (NS_WARN_IF(iter == mContentParentMap.end())) {
-     ASSERT_UNLESS_FUZZING();
--    return std::move(tabContextArray);
-+    return tabContextArray;
-   }
- 
-   for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
-        remoteFrameIter != iter->second.mRemoteFrames.end();
-        ++remoteFrameIter) {
-     tabContextArray.AppendElement(remoteFrameIter->second.mContext);
-   }
- 
--  return std::move(tabContextArray);
-+  return tabContextArray;
- }
- 
- bool
- ContentProcessManager::GetRemoteFrameOpenerTabId(const ContentParentId& aChildCpId,
-                                                  const TabId& aChildTabId,
-                                                  /*out*/ContentParentId* aOpenerCpId,
-                                                  /*out*/TabId* aOpenerTabId)
- {
-@@ -332,26 +332,26 @@ nsTArray<TabId>
- ContentProcessManager::GetTabParentsByProcessId(const ContentParentId& aChildCpId)
- {
-   MOZ_ASSERT(NS_IsMainThread());
- 
-   nsTArray<TabId> tabIdList;
-   auto iter = mContentParentMap.find(aChildCpId);
-   if (NS_WARN_IF(iter == mContentParentMap.end())) {
-     ASSERT_UNLESS_FUZZING();
--    return std::move(tabIdList);
-+    return tabIdList;
-   }
- 
-   for (auto remoteFrameIter = iter->second.mRemoteFrames.begin();
-       remoteFrameIter != iter->second.mRemoteFrames.end();
-       ++remoteFrameIter) {
-     tabIdList.AppendElement(remoteFrameIter->first);
-   }
- 
--  return std::move(tabIdList);
-+  return tabIdList;
- }
- 
- uint32_t
- ContentProcessManager::GetTabParentCountByProcessId(const ContentParentId& aChildCpId)
- {
-   MOZ_ASSERT(NS_IsMainThread());
- 
-   auto iter = mContentParentMap.find(aChildCpId);
-diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp
---- a/dom/media/MediaStreamGraph.cpp
-+++ b/dom/media/MediaStreamGraph.cpp
-@@ -2587,17 +2587,17 @@ MediaStream::SetTrackEnabledImpl(TrackID
-     }
-   } else {
-     for (const DisabledTrack& t : mDisabledTracks) {
-       if (aTrackID == t.mTrackID) {
-         NS_ERROR("Changing disabled track mode for a track is not allowed");
-         return;
-       }
-     }
--    mDisabledTracks.AppendElement(std::move(DisabledTrack(aTrackID, aMode)));
-+    mDisabledTracks.AppendElement(DisabledTrack(aTrackID, aMode));
-   }
- }
- 
- DisabledTrackMode
- MediaStream::GetDisabledTrackMode(TrackID aTrackID)
- {
-   for (const DisabledTrack& t : mDisabledTracks) {
-     if (t.mTrackID == aTrackID) {
-diff --git a/dom/media/eme/MediaKeySystemAccess.cpp b/dom/media/eme/MediaKeySystemAccess.cpp
---- a/dom/media/eme/MediaKeySystemAccess.cpp
-+++ b/dom/media/eme/MediaKeySystemAccess.cpp
-@@ -759,17 +759,17 @@ GetSupportedCapabilities(
-     if (!supportedCapabilities.AppendElement(capabilities, mozilla::fallible)) {
-       NS_WARNING("GetSupportedCapabilities: Malloc failure");
-       return Sequence<MediaKeySystemMediaCapability>();
-     }
- 
-     // Note: omitting steps 3.13.2, our robustness is not sophisticated enough
-     // to require considering all requirements together.
-   }
--  return std::move(supportedCapabilities);
-+  return supportedCapabilities;
- }
- 
- // "Get Supported Configuration and Consent" algorithm, steps 4-7 for
- // distinctive identifier, and steps 8-11 for persistent state. The steps
- // are the same for both requirements/features, so we factor them out into
- // a single function.
- static bool
- CheckRequirement(const MediaKeysRequirement aRequirement,
-diff --git a/dom/media/gmp/ChromiumCDMParent.cpp b/dom/media/gmp/ChromiumCDMParent.cpp
---- a/dom/media/gmp/ChromiumCDMParent.cpp
-+++ b/dom/media/gmp/ChromiumCDMParent.cpp
-@@ -1073,17 +1073,17 @@ ChromiumCDMParent::RecvDrainComplete()
- {
-   if (mIsShutdown) {
-     MOZ_ASSERT(mDecodePromise.IsEmpty());
-     return IPC_OK();
-   }
- 
-   MediaDataDecoder::DecodedData samples;
-   while (!mReorderQueue.IsEmpty()) {
--    samples.AppendElement(std::move(mReorderQueue.Pop()));
-+    samples.AppendElement(mReorderQueue.Pop());
-   }
- 
-   mDecodePromise.ResolveIfExists(std::move(samples), __func__);
-   return IPC_OK();
- }
- RefPtr<ShutdownPromise>
- ChromiumCDMParent::ShutdownVideoDecoder()
- {
-diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp
---- a/dom/media/gmp/GMPParent.cpp
-+++ b/dom/media/gmp/GMPParent.cpp
-@@ -941,17 +941,17 @@ GMPParent::GetGMPContentParent(UniquePtr
-     }
-   }
- }
- 
- already_AddRefed<GMPContentParent>
- GMPParent::ForgetGMPContentParent()
- {
-   MOZ_ASSERT(mGetContentParentPromises.IsEmpty());
--  return std::move(mGMPContentParent.forget());
-+  return mGMPContentParent.forget();
- }
- 
- bool
- GMPParent::EnsureProcessLoaded(base::ProcessId* aID)
- {
-   if (!EnsureProcessLoaded()) {
-     return false;
-   }
-diff --git a/dom/media/gmp/GMPServiceParent.cpp b/dom/media/gmp/GMPServiceParent.cpp
---- a/dom/media/gmp/GMPServiceParent.cpp
-+++ b/dom/media/gmp/GMPServiceParent.cpp
-@@ -1880,17 +1880,17 @@ GMPServiceParent::ActorDestroy(ActorDest
-   // Make sure the IPC channel is closed before destroying mToDelete.
-   MonitorAutoLock lock(monitor);
-   RefPtr<Runnable> task = NewNonOwningRunnableMethod<Monitor*, bool*>(
-     "gmp::GMPServiceParent::CloseTransport",
-     this,
-     &GMPServiceParent::CloseTransport,
-     &monitor,
-     &completed);
--  XRE_GetIOMessageLoop()->PostTask(std::move(task.forget()));
-+  XRE_GetIOMessageLoop()->PostTask(task.forget());
- 
-   while (!completed) {
-     lock.Wait();
-   }
- 
-   // Dispatch a task to the current thread to ensure we don't delete the
-   // GMPServiceParent until the current calling context is finished with
-   // the object.
-diff --git a/dom/media/gmp/GMPStorageChild.cpp b/dom/media/gmp/GMPStorageChild.cpp
---- a/dom/media/gmp/GMPStorageChild.cpp
-+++ b/dom/media/gmp/GMPStorageChild.cpp
-@@ -21,17 +21,17 @@
-     } \
-   } while(false)
- 
- static nsTArray<uint8_t>
- ToArray(const uint8_t* aData, uint32_t aDataSize)
- {
-   nsTArray<uint8_t> data;
-   data.AppendElements(aData, aDataSize);
--  return std::move(data);
-+  return data;
- }
- 
- namespace mozilla {
- namespace gmp {
- 
- GMPRecordImpl::GMPRecordImpl(GMPStorageChild* aOwner,
-                              const nsCString& aName,
-                              GMPRecordClient* aClient)
-diff --git a/dom/media/ipc/VideoDecoderManagerParent.cpp b/dom/media/ipc/VideoDecoderManagerParent.cpp
---- a/dom/media/ipc/VideoDecoderManagerParent.cpp
-+++ b/dom/media/ipc/VideoDecoderManagerParent.cpp
-@@ -39,17 +39,17 @@ using namespace gfx;
- SurfaceDescriptorGPUVideo
- VideoDecoderManagerParent::StoreImage(Image* aImage, TextureClient* aTexture)
- {
-   SurfaceDescriptorGPUVideo ret;
-   aTexture->GPUVideoDesc(&ret);
- 
-   mImageMap[ret.handle()] = aImage;
-   mTextureMap[ret.handle()] = aTexture;
--  return std::move(ret);
-+  return ret;
- }
- 
- StaticRefPtr<nsIThread> sVideoDecoderManagerThread;
- StaticRefPtr<TaskQueue> sManagerTaskQueue;
- 
- class VideoDecoderManagerThreadHolder
- {
-   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderManagerThreadHolder)
-diff --git a/dom/media/platforms/apple/AppleVTDecoder.cpp b/dom/media/platforms/apple/AppleVTDecoder.cpp
---- a/dom/media/platforms/apple/AppleVTDecoder.cpp
-+++ b/dom/media/platforms/apple/AppleVTDecoder.cpp
-@@ -252,17 +252,17 @@ AppleVTDecoder::ProcessDrain()
-   AssertOnTaskQueueThread();
-   nsresult rv = WaitForAsynchronousFrames();
-   if (NS_FAILED(rv)) {
-     LOG("AppleVTDecoder::Drain failed waiting for platform decoder");
-   }
-   MonitorAutoLock mon(mMonitor);
-   DecodedData samples;
-   while (!mReorderQueue.IsEmpty()) {
--    samples.AppendElement(std::move(mReorderQueue.Pop()));
-+    samples.AppendElement(mReorderQueue.Pop());
-   }
-   return DecodePromise::CreateAndResolve(std::move(samples), __func__);
- }
- 
- AppleVTDecoder::AppleFrameRef*
- AppleVTDecoder::CreateAppleFrameRef(const MediaRawData* aSample)
- {
-   MOZ_ASSERT(aSample);
-diff --git a/dom/media/platforms/omx/OmxPlatformLayer.cpp b/dom/media/platforms/omx/OmxPlatformLayer.cpp
---- a/dom/media/platforms/omx/OmxPlatformLayer.cpp
-+++ b/dom/media/platforms/omx/OmxPlatformLayer.cpp
-@@ -168,17 +168,17 @@ ConfigForMime(const nsACString& aMimeTyp
-                 aMimeType.EqualsLiteral("audio/mpeg")) {
-       conf.reset(new OmxMp3Config());
-     } else if (aMimeType.EqualsLiteral("audio/3gpp")) {
-       conf.reset(new OmxAmrConfig<OmxAmrSampleRate::kNarrowBand>());
-     } else if (aMimeType.EqualsLiteral("audio/amr-wb")) {
-       conf.reset(new OmxAmrConfig<OmxAmrSampleRate::kWideBand>());
-     }
-   }
--  return std::move(conf);
-+  return conf;
- }
- 
- // There should be a better way to calculate it.
- #define MIN_VIDEO_INPUT_BUFFER_SIZE 64 * 1024
- 
- class OmxCommonVideoConfig : public OmxVideoConfig
- {
- public:
-@@ -226,17 +226,17 @@ template<>
- UniquePtr<OmxVideoConfig>
- ConfigForMime(const nsACString& aMimeType)
- {
-   UniquePtr<OmxVideoConfig> conf;
- 
-   if (OmxPlatformLayer::SupportsMimeType(aMimeType)) {
-     conf.reset(new OmxCommonVideoConfig());
-   }
--  return std::move(conf);
-+  return conf;
- }
- 
- OMX_ERRORTYPE
- OmxPlatformLayer::Config()
- {
-   MOZ_ASSERT(mInfo);
- 
-   OMX_PORT_PARAM_TYPE portParam;
-diff --git a/dom/serviceworkers/ServiceWorkerDescriptor.cpp b/dom/serviceworkers/ServiceWorkerDescriptor.cpp
---- a/dom/serviceworkers/ServiceWorkerDescriptor.cpp
-+++ b/dom/serviceworkers/ServiceWorkerDescriptor.cpp
-@@ -98,17 +98,17 @@ ServiceWorkerDescriptor::PrincipalInfo()
-   return mData->principalInfo();
- }
- 
- nsCOMPtr<nsIPrincipal>
- ServiceWorkerDescriptor::GetPrincipal() const
- {
-   AssertIsOnMainThread();
-   nsCOMPtr<nsIPrincipal> ref =  PrincipalInfoToPrincipal(mData->principalInfo());
--  return std::move(ref);
-+  return ref;
- }
- 
- const nsCString&
- ServiceWorkerDescriptor::Scope() const
- {
-   return mData->scope();
- }
- 
-diff --git a/dom/serviceworkers/ServiceWorkerManager.cpp b/dom/serviceworkers/ServiceWorkerManager.cpp
---- a/dom/serviceworkers/ServiceWorkerManager.cpp
-+++ b/dom/serviceworkers/ServiceWorkerManager.cpp
-@@ -319,51 +319,51 @@ ServiceWorkerManager::StartControllingCl
-   const ServiceWorkerDescriptor& active =
-     aRegistrationInfo->GetActive()->Descriptor();
- 
-   auto entry = mControlledClients.LookupForAdd(aClientInfo.Id());
-   if (entry) {
-     RefPtr<ServiceWorkerRegistrationInfo> old =
-       entry.Data()->mRegistrationInfo.forget();
- 
--    ref = std::move(entry.Data()->mClientHandle->Control(active));
-+    ref = entry.Data()->mClientHandle->Control(active);
-     entry.Data()->mRegistrationInfo = aRegistrationInfo;
- 
-     if (old != aRegistrationInfo) {
-       StopControllingRegistration(old);
-       aRegistrationInfo->StartControllingClient();
-     }
- 
-     Telemetry::Accumulate(Telemetry::SERVICE_WORKER_CONTROLLED_DOCUMENTS, 1);
- 
--    return std::move(ref);
-+    return ref;
-   }
- 
-   RefPtr<ClientHandle> clientHandle =
-     ClientManager::CreateHandle(aClientInfo,
-                                 SystemGroup::EventTargetFor(TaskCategory::Other));
- 
--  ref = std::move(clientHandle->Control(active));
-+  ref = clientHandle->Control(active);
- 
-   aRegistrationInfo->StartControllingClient();
- 
-   entry.OrInsert([&] {
-     return new ControlledClientData(clientHandle, aRegistrationInfo);
-   });
- 
-   RefPtr<ServiceWorkerManager> self(this);
-   clientHandle->OnDetach()->Then(
-     SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
-     [self = std::move(self), aClientInfo] {
-       self->StopControllingClient(aClientInfo);
-     });
- 
-   Telemetry::Accumulate(Telemetry::SERVICE_WORKER_CONTROLLED_DOCUMENTS, 1);
- 
--  return std::move(ref);
-+  return ref;
- }
- 
- void
- ServiceWorkerManager::StopControllingClient(const ClientInfo& aClientInfo)
- {
-   auto entry = mControlledClients.Lookup(aClientInfo.Id());
-   if (!entry) {
-     return;
-diff --git a/dom/serviceworkers/ServiceWorkerRegistrar.cpp b/dom/serviceworkers/ServiceWorkerRegistrar.cpp
---- a/dom/serviceworkers/ServiceWorkerRegistrar.cpp
-+++ b/dom/serviceworkers/ServiceWorkerRegistrar.cpp
-@@ -1276,17 +1276,17 @@ ServiceWorkerRegistrar::GetShutdownPhase
-   // memory), and there's no point in continuing startup. Include as much
-   // information as possible in the crash report.
-   RELEASE_ASSERT_SUCCEEDED(rv, "async shutdown service");
- 
- 
-   nsCOMPtr<nsIAsyncShutdownClient> client;
-   rv = svc->GetProfileBeforeChange(getter_AddRefs(client));
-   RELEASE_ASSERT_SUCCEEDED(rv, "profileBeforeChange shutdown blocker");
--  return std::move(client);
-+  return client;
- }
- 
- #undef RELEASE_ASSERT_SUCCEEDED
- 
- void
- ServiceWorkerRegistrar::Shutdown()
- {
-   AssertIsOnBackgroundThread();
-diff --git a/dom/serviceworkers/ServiceWorkerRegistrationDescriptor.cpp b/dom/serviceworkers/ServiceWorkerRegistrationDescriptor.cpp
---- a/dom/serviceworkers/ServiceWorkerRegistrationDescriptor.cpp
-+++ b/dom/serviceworkers/ServiceWorkerRegistrationDescriptor.cpp
-@@ -22,17 +22,17 @@ ServiceWorkerRegistrationDescriptor::New
-   Maybe<IPCServiceWorkerDescriptor> result;
-   if (mData->installing().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
-     result.emplace(mData->installing().get_IPCServiceWorkerDescriptor());
-   } else if (mData->waiting().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
-     result.emplace(mData->waiting().get_IPCServiceWorkerDescriptor());
-   } else if (mData->active().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
-     result.emplace(mData->active().get_IPCServiceWorkerDescriptor());
-   }
--  return std::move(result);
-+  return result;
- }
- 
- ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor(
-                                     uint64_t aId,
-                                     nsIPrincipal* aPrincipal,
-                                     const nsACString& aScope,
-                                     ServiceWorkerUpdateViaCache aUpdateViaCache)
-   : mData(MakeUnique<IPCServiceWorkerRegistrationDescriptor>())
-@@ -133,17 +133,17 @@ ServiceWorkerRegistrationDescriptor::Pri
-   return mData->principalInfo();
- }
- 
- nsCOMPtr<nsIPrincipal>
- ServiceWorkerRegistrationDescriptor::GetPrincipal() const
- {
-   AssertIsOnMainThread();
-   nsCOMPtr<nsIPrincipal> ref =  PrincipalInfoToPrincipal(mData->principalInfo());
--  return std::move(ref);
-+  return ref;
- }
- 
- const nsCString&
- ServiceWorkerRegistrationDescriptor::Scope() const
- {
-   return mData->scope();
- }
- 
-@@ -152,54 +152,54 @@ ServiceWorkerRegistrationDescriptor::Get
- {
-   Maybe<ServiceWorkerDescriptor> result;
- 
-   if (mData->installing().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
-     result.emplace(ServiceWorkerDescriptor(
-       mData->installing().get_IPCServiceWorkerDescriptor()));
-   }
- 
--  return std::move(result);
-+  return result;
- }
- 
- Maybe<ServiceWorkerDescriptor>
- ServiceWorkerRegistrationDescriptor::GetWaiting() const
- {
-   Maybe<ServiceWorkerDescriptor> result;
- 
-   if (mData->waiting().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
-     result.emplace(ServiceWorkerDescriptor(
-       mData->waiting().get_IPCServiceWorkerDescriptor()));
-   }
- 
--  return std::move(result);
-+  return result;
- }
- 
- Maybe<ServiceWorkerDescriptor>
- ServiceWorkerRegistrationDescriptor::GetActive() const
- {
-   Maybe<ServiceWorkerDescriptor> result;
- 
-   if (mData->active().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
-     result.emplace(ServiceWorkerDescriptor(
-       mData->active().get_IPCServiceWorkerDescriptor()));
-   }
- 
--  return std::move(result);
-+  return result;
- }
- 
- Maybe<ServiceWorkerDescriptor>
- ServiceWorkerRegistrationDescriptor::Newest() const
- {
-   Maybe<ServiceWorkerDescriptor> result;
-   Maybe<IPCServiceWorkerDescriptor> newest(NewestInternal());
-   if (newest.isSome()) {
-     result.emplace(ServiceWorkerDescriptor(newest.ref()));
-   }
--  return std::move(result);
-+  return result;
- }
- 
- namespace {
- 
- bool
- IsValidWorker(const OptionalIPCServiceWorkerDescriptor& aWorker,
-               const nsACString& aScope,
-               const mozilla::ipc::ContentPrincipalInfo& aContentPrincipal)
-diff --git a/dom/u2f/U2F.cpp b/dom/u2f/U2F.cpp
---- a/dom/u2f/U2F.cpp
-+++ b/dom/u2f/U2F.cpp
-@@ -272,17 +272,17 @@ U2F::Register(const nsAString& aAppId,
-                                   adjustedAppId,
-                                   challenge,
-                                   clientData,
-                                   adjustedTimeoutMillis,
-                                   excludeList,
-                                   null_t() /* no extra info for U2F */);
- 
-   MOZ_ASSERT(mTransaction.isNothing());
--  mTransaction = Some(U2FTransaction(std::move(AsVariant(callback))));
-+  mTransaction = Some(U2FTransaction(AsVariant(callback)));
-   mChild->SendRequestRegister(mTransaction.ref().mId, info);
- }
- 
- void
- U2F::FinishMakeCredential(const uint64_t& aTransactionId,
-                           const WebAuthnMakeCredentialResult& aResult)
- {
-   MOZ_ASSERT(NS_IsMainThread());
-@@ -418,17 +418,17 @@ U2F::Sign(const nsAString& aAppId,
-                                 adjustedAppId,
-                                 challenge,
-                                 clientData,
-                                 adjustedTimeoutMillis,
-                                 permittedList,
-                                 null_t() /* no extra info for U2F */);
- 
-   MOZ_ASSERT(mTransaction.isNothing());
--  mTransaction = Some(U2FTransaction(std::move(AsVariant(callback))));
-+  mTransaction = Some(U2FTransaction(AsVariant(callback)));
-   mChild->SendRequestSign(mTransaction.ref().mId, info);
- }
- 
- void
- U2F::FinishGetAssertion(const uint64_t& aTransactionId,
-                         const WebAuthnGetAssertionResult& aResult)
- {
-   MOZ_ASSERT(NS_IsMainThread());
-diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp
---- a/dom/workers/WorkerPrivate.cpp
-+++ b/dom/workers/WorkerPrivate.cpp
-@@ -3492,30 +3492,30 @@ WorkerPrivate::EnsurePerformanceStorage(
- 
- Maybe<ClientInfo>
- WorkerPrivate::GetClientInfo() const
- {
-   AssertIsOnWorkerThread();
-   Maybe<ClientInfo> clientInfo;
-   if (!mClientSource) {
-     MOZ_DIAGNOSTIC_ASSERT(mStatus >= Terminating);
--    return std::move(clientInfo);
-+    return clientInfo;
-   }
-   clientInfo.emplace(mClientSource->Info());
--  return std::move(clientInfo);
-+  return clientInfo;
- }
- 
- const ClientState
- WorkerPrivate::GetClientState() const
- {
-   AssertIsOnWorkerThread();
-   MOZ_DIAGNOSTIC_ASSERT(mClientSource);
-   ClientState state;
-   mClientSource->SnapshotState(&state);
--  return std::move(state);
-+  return state;
- }
- 
- const Maybe<ServiceWorkerDescriptor>
- WorkerPrivate::GetController()
- {
-   AssertIsOnWorkerThread();
-   {
-     MutexAutoLock lock(mMutex);
-diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp
---- a/dom/workers/WorkerScope.cpp
-+++ b/dom/workers/WorkerScope.cpp
-@@ -543,17 +543,17 @@ WorkerGlobalScope::GetClientInfo() const
-   return mWorkerPrivate->GetClientInfo();
- }
- 
- Maybe<ClientState>
- WorkerGlobalScope::GetClientState() const
- {
-   Maybe<ClientState> state;
-   state.emplace(mWorkerPrivate->GetClientState());
--  return std::move(state);
-+  return state;
- }
- 
- Maybe<ServiceWorkerDescriptor>
- WorkerGlobalScope::GetController() const
- {
-   return mWorkerPrivate->GetController();
- }
- 
-diff --git a/editor/libeditor/HTMLAnonymousNodeEditor.cpp b/editor/libeditor/HTMLAnonymousNodeEditor.cpp
---- a/editor/libeditor/HTMLAnonymousNodeEditor.cpp
-+++ b/editor/libeditor/HTMLAnonymousNodeEditor.cpp
-@@ -225,17 +225,17 @@ HTMLEditor::CreateAnonymousElement(nsAto
-   // sort of ok.
-   newContent->SetProperty(nsGkAtoms::restylableAnonymousNode,
- 			  reinterpret_cast<void*>(true));
- #endif // DEBUG
- 
-   // display the element
-   ps->PostRecreateFramesFor(newContent);
- 
--  return std::move(newContent);
-+  return newContent;
- }
- 
- // Removes event listener and calls DeleteRefToAnonymousNode.
- void
- HTMLEditor::RemoveListenerAndDeleteRef(const nsAString& aEvent,
-                                        nsIDOMEventListener* aListener,
-                                        bool aUseCapture,
-                                        ManualNACPtr aElement,
-diff --git a/editor/libeditor/HTMLEditRules.cpp b/editor/libeditor/HTMLEditRules.cpp
---- a/editor/libeditor/HTMLEditRules.cpp
-+++ b/editor/libeditor/HTMLEditRules.cpp
-@@ -6016,18 +6016,17 @@ HTMLEditRules::CreateStyleForInsertText(
-   int32_t offset = firstRange->StartOffset();
- 
-   RefPtr<Element> rootElement = aDocument.GetRootElement();
-   if (NS_WARN_IF(!rootElement)) {
-     return NS_ERROR_FAILURE;
-   }
- 
-   // process clearing any styles first
--  UniquePtr<PropItem> item =
--    std::move(HTMLEditorRef().mTypeInState->TakeClearProperty());
-+  UniquePtr<PropItem> item = HTMLEditorRef().mTypeInState->TakeClearProperty();
- 
-   {
-     // Transactions may set selection, but we will set selection if necessary.
-     AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
- 
-     while (item && node != rootElement) {
-       // XXX If we redesign ClearStyle(), we can use EditorDOMPoint in this
-       //     method.
-@@ -6035,24 +6034,24 @@ HTMLEditRules::CreateStyleForInsertText(
-         HTMLEditorRef().ClearStyle(address_of(node), &offset,
-                                    item->tag, item->attr);
-       if (NS_WARN_IF(!CanHandleEditAction())) {
-         return NS_ERROR_EDITOR_DESTROYED;
-       }
-       if (NS_WARN_IF(NS_FAILED(rv))) {
-         return rv;
-       }
--      item = std::move(HTMLEditorRef().mTypeInState->TakeClearProperty());
-+      item = HTMLEditorRef().mTypeInState->TakeClearProperty();
-       weDidSomething = true;
-     }
-   }
- 
-   // then process setting any styles
-   int32_t relFontSize = HTMLEditorRef().mTypeInState->TakeRelativeFontSize();
--  item = std::move(HTMLEditorRef().mTypeInState->TakeSetProperty());
-+  item = HTMLEditorRef().mTypeInState->TakeSetProperty();
- 
-   if (item || relFontSize) {
-     // we have at least one style to add; make a new text node to insert style
-     // nodes above.
-     if (RefPtr<Text> text = node->GetAsText()) {
-       // if we are in a text node, split it
-       SplitNodeResult splitTextNodeResult =
-         HTMLEditorRef().SplitNodeDeepWithTransaction(
-diff --git a/editor/libeditor/HTMLEditorObjectResizer.cpp b/editor/libeditor/HTMLEditorObjectResizer.cpp
---- a/editor/libeditor/HTMLEditorObjectResizer.cpp
-+++ b/editor/libeditor/HTMLEditorObjectResizer.cpp
-@@ -140,17 +140,17 @@ HTMLEditor::CreateResizer(int16_t aLocat
-     case nsIHTMLObjectResizer::eBottomRight:
-       locationStr = kBottomRight;
-       break;
-   }
- 
-   nsresult rv =
-     ret->SetAttr(kNameSpaceID_None, nsGkAtoms::anonlocation, locationStr, true);
-   NS_ENSURE_SUCCESS(rv, nullptr);
--  return std::move(ret);
-+  return ret;
- }
- 
- ManualNACPtr
- HTMLEditor::CreateShadow(nsIContent& aParentContent,
-                          Element& aOriginalObject)
- {
-   // let's create an image through the element factory
-   RefPtr<nsAtom> name;
-diff --git a/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp b/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
---- a/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
-+++ b/extensions/spellcheck/hunspell/glue/RemoteSpellCheckEngineChild.cpp
-@@ -34,17 +34,17 @@ RemoteSpellcheckEngineChild::SetCurrentD
-   if (!SendSetDictionaryFromList(
-          aList,
-          reinterpret_cast<intptr_t>(promiseHolder.get()))) {
-     return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
-   }
-   RefPtr<GenericPromise> result = promiseHolder->Ensure(__func__);
-   // promiseHolder will removed by receive message
-   mResponsePromises.AppendElement(std::move(promiseHolder));
--  return std::move(result);
-+  return result;
- }
- 
- mozilla::ipc::IPCResult
- RemoteSpellcheckEngineChild::RecvNotifyOfCurrentDictionary(
-                                const nsString& aDictionary,
-                                const intptr_t& aId)
- {
-   MozPromiseHolder<GenericPromise>* promiseHolder =
-diff --git a/gfx/2d/SFNTData.cpp b/gfx/2d/SFNTData.cpp
---- a/gfx/2d/SFNTData.cpp
-+++ b/gfx/2d/SFNTData.cpp
-@@ -134,25 +134,25 @@ SFNTData::Create(const uint8_t *aFontDat
-     const BigEndianUint32* endOfOffsets = offset + numFonts;
-     while (offset != endOfOffsets) {
-       if (!sfntData->AddFont(aFontData, aDataLength, *offset)) {
-         return nullptr;
-       }
-       ++offset;
-     }
- 
--    return std::move(sfntData);
-+    return sfntData;
-   }
- 
-   UniquePtr<SFNTData> sfntData(new SFNTData);
-   if (!sfntData->AddFont(aFontData, aDataLength, 0)) {
-     return nullptr;
-   }
- 
--  return std::move(sfntData);
-+  return sfntData;
- }
- 
- /* static */
- uint64_t
- SFNTData::GetUniqueKey(const uint8_t *aFontData, uint32_t aDataLength,
-                        uint32_t aVarDataSize, const void* aVarData)
- {
-   uint64_t hash;
-diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp
---- a/gfx/gl/GLScreenBuffer.cpp
-+++ b/gfx/gl/GLScreenBuffer.cpp
-@@ -43,28 +43,28 @@ UniquePtr<GLScreenBuffer>
- GLScreenBuffer::Create(GLContext* gl,
-                        const gfx::IntSize& size,
-                        const SurfaceCaps& caps)
- {
-     UniquePtr<GLScreenBuffer> ret;
-     if (caps.antialias &&
-         !gl->IsSupported(GLFeature::framebuffer_multisample))
-     {
--        return std::move(ret);
-+        return ret;
-     }
- 
-     layers::TextureFlags flags = layers::TextureFlags::ORIGIN_BOTTOM_LEFT;
-     if (!caps.premultAlpha) {
-         flags |= layers::TextureFlags::NON_PREMULTIPLIED;
-     }
- 
-     UniquePtr<SurfaceFactory> factory = MakeUnique<SurfaceFactory_Basic>(gl, caps, flags);
- 
-     ret.reset( new GLScreenBuffer(gl, caps, std::move(factory)) );
--    return std::move(ret);
-+    return ret;
- }
- 
- /* static */ UniquePtr<SurfaceFactory>
- GLScreenBuffer::CreateFactory(GLContext* gl,
-                               const SurfaceCaps& caps,
-                               KnowsCompositor* compositorConnection,
-                               const layers::TextureFlags& flags)
- {
-@@ -948,17 +948,17 @@ ReadBuffer::Create(GLContext* gl,
-     const bool isComplete = gl->IsFramebufferComplete(fb);
-     if (needsAcquire) {
-         surf->ProducerReadRelease();
-     }
- 
-     if (!isComplete)
-         return nullptr;
- 
--    return std::move(ret);
-+    return ret;
- }
- 
- ReadBuffer::~ReadBuffer()
- {
-     if (!mGL->MakeCurrent())
-         return;
- 
-     GLuint fb = mFB;
-diff --git a/gfx/gl/MozFramebuffer.cpp b/gfx/gl/MozFramebuffer.cpp
---- a/gfx/gl/MozFramebuffer.cpp
-+++ b/gfx/gl/MozFramebuffer.cpp
-@@ -129,17 +129,17 @@ MozFramebuffer::CreateWith(GLContext* co
-     }
- 
-     const auto status = gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
-     if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
-         MOZ_ASSERT(false);
-         return nullptr;
-     }
- 
--    return std::move(mozFB);
-+    return mozFB;
- }
- 
- ////////////////////
- 
- MozFramebuffer::MozFramebuffer(GLContext* const gl, const gfx::IntSize& size,
-                                const uint32_t samples, const bool depthStencil,
-                                const GLenum colorTarget, const GLuint colorName)
-     : mWeakGL(gl)
-diff --git a/gfx/gl/SharedSurface.cpp b/gfx/gl/SharedSurface.cpp
---- a/gfx/gl/SharedSurface.cpp
-+++ b/gfx/gl/SharedSurface.cpp
-@@ -327,17 +327,17 @@ SurfaceFactory::NewTexClient(const gfx::
-         if (cur->Surf()->mSize == size) {
-             cur->Surf()->WaitForBufferOwnership();
-             return cur.forget();
-         }
- 
-         StopRecycling(cur);
-     }
- 
--    UniquePtr<SharedSurface> surf = std::move(CreateShared(size));
-+    UniquePtr<SharedSurface> surf = CreateShared(size);
-     if (!surf)
-         return nullptr;
- 
-     RefPtr<layers::SharedSurfaceTextureClient> ret;
-     ret = layers::SharedSurfaceTextureClient::Create(std::move(surf), this, mAllocator, mFlags);
- 
-     StartRecycling(ret);
- 
-diff --git a/gfx/gl/SharedSurfaceEGL.cpp b/gfx/gl/SharedSurfaceEGL.cpp
---- a/gfx/gl/SharedSurfaceEGL.cpp
-+++ b/gfx/gl/SharedSurfaceEGL.cpp
-@@ -25,37 +25,37 @@ SharedSurface_EGLImage::Create(GLContext
- {
-     GLLibraryEGL* egl = &sEGLLibrary;
-     MOZ_ASSERT(egl);
-     MOZ_ASSERT(context);
- 
-     UniquePtr<SharedSurface_EGLImage> ret;
- 
-     if (!HasExtensions(egl, prodGL)) {
--        return std::move(ret);
-+        return ret;
-     }
- 
-     MOZ_ALWAYS_TRUE(prodGL->MakeCurrent());
-     GLuint prodTex = CreateTextureForOffscreen(prodGL, formats, size);
-     if (!prodTex) {
--        return std::move(ret);
-+        return ret;
-     }
- 
-     EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(uintptr_t(prodTex));
-     EGLImage image = egl->fCreateImage(egl->Display(), context,
-                                        LOCAL_EGL_GL_TEXTURE_2D, buffer,
-                                        nullptr);
-     if (!image) {
-         prodGL->fDeleteTextures(1, &prodTex);
--        return std::move(ret);
-+        return ret;
-     }
- 
-     ret.reset( new SharedSurface_EGLImage(prodGL, egl, size, hasAlpha,
-                                           formats, prodTex, image) );
--    return std::move(ret);
-+    return ret;
- }
- 
- bool
- SharedSurface_EGLImage::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
- {
-     return egl->HasKHRImageBase() &&
-            egl->IsExtensionSupported(GLLibraryEGL::KHR_gl_texture_2D_image) &&
-            (gl->IsExtensionSupported(GLContext::OES_EGL_image_external) ||
-@@ -172,17 +172,17 @@ SurfaceFactory_EGLImage::Create(GLContex
-     typedef SurfaceFactory_EGLImage ptrT;
-     UniquePtr<ptrT> ret;
- 
-     GLLibraryEGL* egl = &sEGLLibrary;
-     if (SharedSurface_EGLImage::HasExtensions(egl, prodGL)) {
-         ret.reset( new ptrT(prodGL, caps, allocator, flags, context) );
-     }
- 
--    return std::move(ret);
-+    return ret;
- }
- 
- ////////////////////////////////////////////////////////////////////////
- 
- #ifdef MOZ_WIDGET_ANDROID
- 
- /*static*/ UniquePtr<SharedSurface_SurfaceTexture>
- SharedSurface_SurfaceTexture::Create(GLContext* prodGL,
-@@ -195,22 +195,22 @@ SharedSurface_SurfaceTexture::Create(GLC
- 
-     UniquePtr<SharedSurface_SurfaceTexture> ret;
- 
-     AndroidNativeWindow window(surface);
-     GLContextEGL* egl = GLContextEGL::Cast(prodGL);
-     MOZ_ASSERT(egl);
-     EGLSurface eglSurface = egl->CreateCompatibleSurface(window.NativeWindow());
-     if (!eglSurface) {
--        return std::move(ret);
-+        return ret;
-     }
- 
-     ret.reset(new SharedSurface_SurfaceTexture(prodGL, size, hasAlpha,
-                                                formats, surface, eglSurface));
--    return std::move(ret);
-+    return ret;
- }
- 
- SharedSurface_SurfaceTexture::SharedSurface_SurfaceTexture(GLContext* gl,
-                                                            const gfx::IntSize& size,
-                                                            bool hasAlpha,
-                                                            const GLFormats& formats,
-                                                            java::GeckoSurface::Param surface,
-                                                            EGLSurface eglSurface)
-@@ -287,17 +287,17 @@ SharedSurface_SurfaceTexture::ToSurfaceD
- 
- /*static*/ UniquePtr<SurfaceFactory_SurfaceTexture>
- SurfaceFactory_SurfaceTexture::Create(GLContext* prodGL, const SurfaceCaps& caps,
-                                       const RefPtr<layers::LayersIPCChannel>& allocator,
-                                       const layers::TextureFlags& flags)
- {
-     UniquePtr<SurfaceFactory_SurfaceTexture> ret(
-         new SurfaceFactory_SurfaceTexture(prodGL, caps, allocator, flags));
--    return std::move(ret);
-+    return ret;
- }
- 
- UniquePtr<SharedSurface>
- SurfaceFactory_SurfaceTexture::CreateShared(const gfx::IntSize& size)
- {
-     bool hasAlpha = mReadCaps.alpha;
- 
-     jni::Object::LocalRef surface = java::SurfaceAllocator::AcquireSurface(size.width, size.height, true);
-diff --git a/gfx/gl/SharedSurfaceGL.cpp b/gfx/gl/SharedSurfaceGL.cpp
---- a/gfx/gl/SharedSurfaceGL.cpp
-+++ b/gfx/gl/SharedSurfaceGL.cpp
-@@ -28,35 +28,35 @@ SharedSurface_Basic::Create(GLContext* g
- 
-     GLContext::LocalErrorScope localError(*gl);
-     GLuint tex = CreateTextureForOffscreen(gl, formats, size);
- 
-     GLenum err = localError.GetError();
-     MOZ_ASSERT_IF(err != LOCAL_GL_NO_ERROR, err == LOCAL_GL_OUT_OF_MEMORY);
-     if (err) {
-         gl->fDeleteTextures(1, &tex);
--        return std::move(ret);
-+        return ret;
-     }
- 
-     bool ownsTex = true;
-     ret.reset( new SharedSurface_Basic(gl, size, hasAlpha, tex, ownsTex) );
--    return std::move(ret);
-+    return ret;
- }
- 
- 
- /*static*/ UniquePtr<SharedSurface_Basic>
- SharedSurface_Basic::Wrap(GLContext* gl,
-                           const IntSize& size,
-                           bool hasAlpha,
-                           GLuint tex)
- {
-     bool ownsTex = false;
-     UniquePtr<SharedSurface_Basic> ret( new SharedSurface_Basic(gl, size, hasAlpha, tex,
-                                                                 ownsTex) );
--    return std::move(ret);
-+    return ret;
- }
- 
- SharedSurface_Basic::SharedSurface_Basic(GLContext* gl,
-                                          const IntSize& size,
-                                          bool hasAlpha,
-                                          GLuint tex,
-                                          bool ownsTex)
-     : SharedSurface(SharedSurfaceType::Basic,
-@@ -121,22 +121,22 @@ SharedSurface_GLTexture::Create(GLContex
-     GLContext::LocalErrorScope localError(*prodGL);
- 
-     GLuint tex = CreateTextureForOffscreen(prodGL, formats, size);
- 
-     GLenum err = localError.GetError();
-     MOZ_ASSERT_IF(err, err == LOCAL_GL_OUT_OF_MEMORY);
-     if (err) {
-         prodGL->fDeleteTextures(1, &tex);
--        return std::move(ret);
-+        return ret;
-     }
- 
-     ret.reset(new SharedSurface_GLTexture(prodGL, size,
-                                           hasAlpha, tex));
--    return std::move(ret);
-+    return ret;
- }
- 
- SharedSurface_GLTexture::~SharedSurface_GLTexture()
- {
-     if (!mGL->MakeCurrent())
-         return;
- 
-     if (mTex) {
-diff --git a/gfx/gl/SharedSurfaceGLX.cpp b/gfx/gl/SharedSurfaceGLX.cpp
---- a/gfx/gl/SharedSurfaceGLX.cpp
-+++ b/gfx/gl/SharedSurfaceGLX.cpp
-@@ -32,17 +32,17 @@ SharedSurface_GLXDrawable::Create(GLCont
-     Screen* screen = XDefaultScreenOfDisplay(display);
-     Visual* visual = gfxXlibSurface::FindVisual(screen, gfx::SurfaceFormat::A8R8G8B8_UINT32);
- 
-     RefPtr<gfxXlibSurface> surf = gfxXlibSurface::Create(screen, visual, size);
-     if (!deallocateClient)
-         surf->ReleasePixmap();
- 
-     ret.reset(new SharedSurface_GLXDrawable(prodGL, size, inSameProcess, surf));
--    return std::move(ret);
-+    return ret;
- }
- 
- 
- SharedSurface_GLXDrawable::SharedSurface_GLXDrawable(GLContext* gl,
-                                                      const gfx::IntSize& size,
-                                                      bool inSameProcess,
-                                                      const RefPtr<gfxXlibSurface>& xlibSurface)
-     : SharedSurface(SharedSurfaceType::GLXDrawable,
-@@ -124,17 +124,17 @@ SurfaceFactory_GLXDrawable::Create(GLCon
-                                    const RefPtr<layers::LayersIPCChannel>& allocator,
-                                    const layers::TextureFlags& flags)
- {
-     MOZ_ASSERT(caps.alpha, "GLX surfaces require an alpha channel!");
- 
-     typedef SurfaceFactory_GLXDrawable ptrT;
-     UniquePtr<ptrT> ret(new ptrT(prodGL, caps, allocator,
-                                  flags & ~layers::TextureFlags::ORIGIN_BOTTOM_LEFT));
--    return std::move(ret);
-+    return ret;
- }
- 
- UniquePtr<SharedSurface>
- SurfaceFactory_GLXDrawable::CreateShared(const gfx::IntSize& size)
- {
-     bool deallocateClient = !!(mFlags & layers::TextureFlags::DEALLOCATE_CLIENT);
-     return SharedSurface_GLXDrawable::Create(mGL, mCaps, size, deallocateClient,
-                                              mAllocator->IsSameProcess());
-diff --git a/gfx/gl/SharedSurfaceIO.cpp b/gfx/gl/SharedSurfaceIO.cpp
---- a/gfx/gl/SharedSurfaceIO.cpp
-+++ b/gfx/gl/SharedSurfaceIO.cpp
-@@ -21,17 +21,17 @@ SharedSurface_IOSurface::Create(const Re
- {
-     MOZ_ASSERT(ioSurf);
-     MOZ_ASSERT(gl);
- 
-     auto size = gfx::IntSize::Truncate(ioSurf->GetWidth(), ioSurf->GetHeight());
- 
-     typedef SharedSurface_IOSurface ptrT;
-     UniquePtr<ptrT> ret( new ptrT(ioSurf, gl, size, hasAlpha) );
--    return std::move(ret);
-+    return ret;
- }
- 
- void
- SharedSurface_IOSurface::ProducerReleaseImpl()
- {
-     mGL->MakeCurrent();
-     mGL->fFlush();
- }
-@@ -214,17 +214,17 @@ SurfaceFactory_IOSurface::Create(GLConte
-                                  const RefPtr<layers::LayersIPCChannel>& allocator,
-                                  const layers::TextureFlags& flags)
- {
-     auto maxDims = gfx::IntSize::Truncate(MacIOSurface::GetMaxWidth(),
-                                           MacIOSurface::GetMaxHeight());
- 
-     typedef SurfaceFactory_IOSurface ptrT;
-     UniquePtr<ptrT> ret( new ptrT(gl, caps, allocator, flags, maxDims) );
--    return std::move(ret);
-+    return ret;
- }
- 
- UniquePtr<SharedSurface>
- SurfaceFactory_IOSurface::CreateShared(const gfx::IntSize& size)
- {
-     if (size.width > mMaxDims.width ||
-         size.height > mMaxDims.height)
-     {
-diff --git a/gfx/layers/AnimationHelper.cpp b/gfx/layers/AnimationHelper.cpp
---- a/gfx/layers/AnimationHelper.cpp
-+++ b/gfx/layers/AnimationHelper.cpp
-@@ -108,17 +108,17 @@ CompositorAnimationStorage::SetAnimatedV
- void
- CompositorAnimationStorage::SetAnimatedValue(uint64_t aId,
-                                              gfx::Matrix4x4&& aTransformInDevSpace)
- {
-   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-   const TransformData dontCare = {};
-   SetAnimatedValue(aId,
-                    std::move(aTransformInDevSpace),
--                   std::move(gfx::Matrix4x4()),
-+                   gfx::Matrix4x4(),
-                    dontCare);
- }
- 
- void
- CompositorAnimationStorage::SetAnimatedValue(uint64_t aId,
-                                              const float& aOpacity)
- {
-   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-@@ -576,18 +576,18 @@ AnimationHelper::SetAnimations(
-     data->mTiming = TimingParams {
-       animation.duration(),
-       animation.delay(),
-       animation.endDelay(),
-       animation.iterations(),
-       animation.iterationStart(),
-       static_cast<dom::PlaybackDirection>(animation.direction()),
-       static_cast<dom::FillMode>(animation.fillMode()),
--      std::move(AnimationUtils::TimingFunctionToComputedTimingFunction(
--           animation.easingFunction()))
-+      AnimationUtils::TimingFunctionToComputedTimingFunction(
-+           animation.easingFunction())
-     };
-     InfallibleTArray<Maybe<ComputedTimingFunction>>& functions =
-       data->mFunctions;
-     InfallibleTArray<RefPtr<RawServoAnimationValue>>& startValues =
-       data->mStartValues;
-     InfallibleTArray<RefPtr<RawServoAnimationValue>>& endValues =
-       data->mEndValues;
- 
-diff --git a/gfx/layers/LayerTreeInvalidation.cpp b/gfx/layers/LayerTreeInvalidation.cpp
---- a/gfx/layers/LayerTreeInvalidation.cpp
-+++ b/gfx/layers/LayerTreeInvalidation.cpp
-@@ -341,17 +341,17 @@ struct ContainerLayerProperties : public
- {
-   explicit ContainerLayerProperties(ContainerLayer* aLayer)
-     : LayerPropertiesBase(aLayer)
-     , mPreXScale(aLayer->GetPreXScale())
-     , mPreYScale(aLayer->GetPreYScale())
-   {
-     for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) {
-       child->CheckCanary();
--      mChildren.AppendElement(std::move(CloneLayerTreePropertiesInternal(child)));
-+      mChildren.AppendElement(CloneLayerTreePropertiesInternal(child));
-     }
-   }
- 
- protected:
-   ContainerLayerProperties(const ContainerLayerProperties& a) = delete;
-   ContainerLayerProperties& operator=(const ContainerLayerProperties& a) = delete;
- 
- public:
-diff --git a/gfx/layers/ipc/CompositorVsyncScheduler.cpp b/gfx/layers/ipc/CompositorVsyncScheduler.cpp
---- a/gfx/layers/ipc/CompositorVsyncScheduler.cpp
-+++ b/gfx/layers/ipc/CompositorVsyncScheduler.cpp
-@@ -139,17 +139,17 @@ CompositorVsyncScheduler::PostVRTask(Tim
-   MonitorAutoLock lockVR(mCurrentVRListenerTaskMonitor);
-   if (mCurrentVRListenerTask == nullptr && VRListenerThreadHolder::Loop()) {
-     RefPtr<Runnable> task = NewRunnableMethod<TimeStamp>(
-       "layers::CompositorVsyncScheduler::DispatchVREvents",
-       this,
-       &CompositorVsyncScheduler::DispatchVREvents,
-       aTimestamp);
-     mCurrentVRListenerTask = task;
--    VRListenerThreadHolder::Loop()->PostDelayedTask(std::move(task.forget()), 0);
-+    VRListenerThreadHolder::Loop()->PostDelayedTask(task.forget(), 0);
-   }
- }
- 
- void
- CompositorVsyncScheduler::ScheduleComposition()
- {
-   MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
-   if (!mVsyncObserver) {
-diff --git a/gfx/layers/ipc/UiCompositorControllerParent.cpp b/gfx/layers/ipc/UiCompositorControllerParent.cpp
---- a/gfx/layers/ipc/UiCompositorControllerParent.cpp
-+++ b/gfx/layers/ipc/UiCompositorControllerParent.cpp
-@@ -24,17 +24,17 @@ typedef CompositorBridgeParent::LayerTre
- /* static */ RefPtr<UiCompositorControllerParent>
- UiCompositorControllerParent::GetFromRootLayerTreeId(const LayersId& aRootLayerTreeId)
- {
-   RefPtr<UiCompositorControllerParent> controller;
-   CompositorBridgeParent::CallWithIndirectShadowTree(aRootLayerTreeId,
-     [&](LayerTreeState& aState) -> void {
-       controller = aState.mUiControllerParent;
-     });
--  return std::move(controller);
-+  return controller;
- }
- 
- /* static */ RefPtr<UiCompositorControllerParent>
- UiCompositorControllerParent::Start(const LayersId& aRootLayerTreeId, Endpoint<PUiCompositorControllerParent>&& aEndpoint)
- {
-   RefPtr<UiCompositorControllerParent> parent = new UiCompositorControllerParent(aRootLayerTreeId);
- 
-   RefPtr<Runnable> task =
-diff --git a/gfx/layers/wr/WebRenderCommandBuilder.cpp b/gfx/layers/wr/WebRenderCommandBuilder.cpp
---- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
-+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
-@@ -1538,17 +1538,17 @@ PaintByLayer(nsDisplayItem* aItem,
-              nsDisplayListBuilder* aDisplayListBuilder,
-              const RefPtr<BasicLayerManager>& aManager,
-              gfxContext* aContext,
-              const gfx::Size& aScale,
-              const std::function<void()>& aPaintFunc)
- {
-   UniquePtr<LayerProperties> props;
-   if (aManager->GetRoot()) {
--    props = std::move(LayerProperties::CloneFrom(aManager->GetRoot()));
-+    props = LayerProperties::CloneFrom(aManager->GetRoot());
-   }
-   FrameLayerBuilder* layerBuilder = new FrameLayerBuilder();
-   layerBuilder->Init(aDisplayListBuilder, aManager, nullptr, true);
-   layerBuilder->DidBeginRetainedLayerTransaction(aManager);
- 
-   aManager->SetDefaultTarget(aContext);
-   aManager->BeginTransactionWithTarget(aContext);
-   bool isInvalidated = false;
-diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp
---- a/gfx/thebes/gfxFont.cpp
-+++ b/gfx/thebes/gfxFont.cpp
-@@ -2549,17 +2549,17 @@ gfxFont::Measure(const gfxTextRun *aText
- {
-     // If aBoundingBoxType is TIGHT_HINTED_OUTLINE_EXTENTS
-     // and the underlying cairo font may be antialiased,
-     // we need to create a copy in order to avoid getting cached extents.
-     // This is only used by MathML layout at present.
-     if (aBoundingBoxType == TIGHT_HINTED_OUTLINE_EXTENTS &&
-         mAntialiasOption != kAntialiasNone) {
-         if (!mNonAAFont) {
--            mNonAAFont = std::move(CopyWithAntialiasOption(kAntialiasNone));
-+            mNonAAFont = CopyWithAntialiasOption(kAntialiasNone);
-         }
-         // if font subclass doesn't implement CopyWithAntialiasOption(),
-         // it will return null and we'll proceed to use the existing font
-         if (mNonAAFont) {
-             return mNonAAFont->Measure(aTextRun, aStart, aEnd,
-                                        TIGHT_HINTED_OUTLINE_EXTENTS,
-                                        aRefDrawTarget, aSpacing, aOrientation);
-         }
-diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp
---- a/gfx/thebes/gfxPlatform.cpp
-+++ b/gfx/thebes/gfxPlatform.cpp
-@@ -1829,17 +1829,17 @@ gfxPlatform::GetBackendPrefs() const
-   data.mContentBitmask = BackendTypeBit(BackendType::CAIRO);
- #ifdef USE_SKIA
-   data.mCanvasBitmask |= BackendTypeBit(BackendType::SKIA);
-   data.mContentBitmask |= BackendTypeBit(BackendType::SKIA);
- #endif
-   data.mCanvasDefault = BackendType::CAIRO;
-   data.mContentDefault = BackendType::CAIRO;
- 
--  return std::move(data);
-+  return data;
- }
- 
- void
- gfxPlatform::InitBackendPrefs(BackendPrefsData&& aPrefsData)
- {
-     mPreferredCanvasBackend = GetCanvasBackendPref(aPrefsData.mCanvasBitmask);
-     if (mPreferredCanvasBackend == BackendType::NONE) {
-         mPreferredCanvasBackend = aPrefsData.mCanvasDefault;
-diff --git a/gfx/thebes/gfxPlatformMac.cpp b/gfx/thebes/gfxPlatformMac.cpp
---- a/gfx/thebes/gfxPlatformMac.cpp
-+++ b/gfx/thebes/gfxPlatformMac.cpp
-@@ -98,17 +98,17 @@ gfxPlatformMac::GetBackendPrefs() const
- {
-   BackendPrefsData data;
- 
-   data.mCanvasBitmask = BackendTypeBit(BackendType::SKIA);
-   data.mContentBitmask = BackendTypeBit(BackendType::SKIA);
-   data.mCanvasDefault = BackendType::SKIA;
-   data.mContentDefault = BackendType::SKIA;
- 
--  return std::move(data);
-+  return data;
- }
- 
- bool
- gfxPlatformMac::UsesTiling() const
- {
-     // The non-tiling ContentClient requires CrossProcessSemaphore which
-     // isn't implemented for OSX.
-     return true;
-diff --git a/image/decoders/nsICODecoder.cpp b/image/decoders/nsICODecoder.cpp
---- a/image/decoders/nsICODecoder.cpp
-+++ b/image/decoders/nsICODecoder.cpp
-@@ -198,17 +198,17 @@ LexerTransition<ICOState>
- nsICODecoder::IterateUnsizedDirEntry()
- {
-   MOZ_ASSERT(!mUnsizedDirEntries.IsEmpty());
- 
-   if (!mDirEntry) {
-     // The first time we are here, there is no entry selected. We must prepare a
-     // new iterator for the contained decoder to advance as it wills. Cloning at
-     // this point ensures it will begin at the end of the dir entries.
--    mReturnIterator = std::move(mLexer.Clone(*mIterator, SIZE_MAX));
-+    mReturnIterator = mLexer.Clone(*mIterator, SIZE_MAX);
-     if (mReturnIterator.isNothing()) {
-       // If we cannot read further than this point, then there is no resource
-       // data to read.
-       return Transition::TerminateFailure();
-     }
-   } else {
-     // We have already selected an entry which means a metadata decoder has
-     // finished. Verify the size is valid and if so, add to the discovered
-@@ -218,17 +218,17 @@ nsICODecoder::IterateUnsizedDirEntry()
-     }
- 
-     // Remove the entry from the unsized list either way.
-     mDirEntry = nullptr;
-     mUnsizedDirEntries.RemoveElementAt(0);
- 
-     // Our iterator is at an unknown point, so reset it to the point that we
-     // saved.
--    mIterator = std::move(mLexer.Clone(*mReturnIterator, SIZE_MAX));
-+    mIterator = mLexer.Clone(*mReturnIterator, SIZE_MAX);
-     if (mIterator.isNothing()) {
-       MOZ_ASSERT_UNREACHABLE("Cannot re-clone return iterator");
-       return Transition::TerminateFailure();
-     }
-   }
- 
-   // There are no more unsized entries, so we can finally decide which entry to
-   // select for decoding.
-diff --git a/image/test/gtest/TestADAM7InterpolatingFilter.cpp b/image/test/gtest/TestADAM7InterpolatingFilter.cpp
---- a/image/test/gtest/TestADAM7InterpolatingFilter.cpp
-+++ b/image/test/gtest/TestADAM7InterpolatingFilter.cpp
-@@ -236,18 +236,18 @@ WriteUninterpolatedPixels(SurfaceFilter*
-                           uint8_t aPass,
-                           const vector<BGRAColor>& aColors)
- {
-   WriteState result = WriteState::NEED_MORE_DATA;
- 
-   for (int32_t row = 0; row < aSize.height; ++row) {
-     // Compute uninterpolated pixels for this row.
-     vector<BGRAColor> pixels =
--      std::move(ADAM7HorizontallyInterpolatedRow(aPass, row, aSize.width,
--                                            ShouldInterpolate::eNo, aColors));
-+      ADAM7HorizontallyInterpolatedRow(aPass, row, aSize.width,
-+                                       ShouldInterpolate::eNo, aColors);
- 
-     // Write them to the surface.
-     auto pixelIterator = pixels.cbegin();
-     result = aFilter->WritePixelsToRow<uint32_t>([&]{
-       return AsVariant((*pixelIterator++).AsPixel());
-     });
- 
-     if (result != WriteState::NEED_MORE_DATA) {
-@@ -270,18 +270,18 @@ CheckHorizontallyInterpolatedImage(Decod
-   for (int32_t row = 0; row < aSize.height; ++row) {
-     if (!IsImportantRow(row, aPass)) {
-       continue;  // Don't check rows which aren't important on this pass.
-     }
- 
-     // Compute the expected pixels, *with* interpolation to match what the
-     // filter should have done.
-     vector<BGRAColor> expectedPixels =
--      std::move(ADAM7HorizontallyInterpolatedRow(aPass, row, aSize.width,
--                                            ShouldInterpolate::eYes, aColors));
-+      ADAM7HorizontallyInterpolatedRow(aPass, row, aSize.width,
-+                                       ShouldInterpolate::eYes, aColors);
- 
-     if (!RowHasPixels(surface, row, expectedPixels)) {
-       return false;
-     }
-   }
- 
-   return true;
- }
-diff --git a/image/test/gtest/TestAnimationFrameBuffer.cpp b/image/test/gtest/TestAnimationFrameBuffer.cpp
---- a/image/test/gtest/TestAnimationFrameBuffer.cpp
-+++ b/image/test/gtest/TestAnimationFrameBuffer.cpp
-@@ -23,17 +23,17 @@ CreateEmptyFrame()
- }
- 
- static bool
- Fill(AnimationFrameBuffer& buffer, size_t aLength)
- {
-   bool keepDecoding = false;
-   for (size_t i = 0; i < aLength; ++i) {
-     RawAccessFrameRef frame = CreateEmptyFrame();
--    keepDecoding = buffer.Insert(std::move(frame->RawAccessRef()));
-+    keepDecoding = buffer.Insert(frame->RawAccessRef());
-   }
-   return keepDecoding;
- }
- 
- static void
- CheckFrames(const AnimationFrameBuffer& buffer, size_t aStart, size_t aEnd, bool aExpected)
- {
-   for (size_t i = aStart; i < aEnd; ++i) {
-@@ -128,17 +128,17 @@ TEST_F(ImageAnimationFrameBuffer, Finish
-   buffer.Initialize(kThreshold, kBatch, 0);
-   const auto& frames = buffer.Frames();
- 
-   EXPECT_EQ(kBatch * 2, buffer.PendingDecode());
- 
-   RawAccessFrameRef firstFrame;
-   for (size_t i = 0; i < 5; ++i) {
-     RawAccessFrameRef frame = CreateEmptyFrame();
--    bool keepDecoding = buffer.Insert(std::move(frame->RawAccessRef()));
-+    bool keepDecoding = buffer.Insert(frame->RawAccessRef());
-     EXPECT_TRUE(keepDecoding);
-     EXPECT_FALSE(buffer.SizeKnown());
- 
-     if (i == 4) {
-       EXPECT_EQ(size_t(15), buffer.PendingDecode());
-       keepDecoding = buffer.MarkComplete();
-       EXPECT_FALSE(keepDecoding);
-       EXPECT_TRUE(buffer.SizeKnown());
-diff --git a/image/test/gtest/TestSourceBuffer.cpp b/image/test/gtest/TestSourceBuffer.cpp
---- a/image/test/gtest/TestSourceBuffer.cpp
-+++ b/image/test/gtest/TestSourceBuffer.cpp
-@@ -608,30 +608,32 @@ TEST_F(ImageSourceBuffer, SourceBufferIt
-   auto GetIterator = [&]{
-     SourceBufferIterator lambdaIterator = mSourceBuffer->Iterator();
-     CheckedAdvanceIterator(lambdaIterator, chunkLength);
-     return lambdaIterator;
-   };
- 
-   // Move-construct |movedIterator| from the iterator returned from
-   // GetIterator() and check that its state is as we expect.
--  SourceBufferIterator movedIterator = std::move(GetIterator());
-+  SourceBufferIterator tmpIterator = GetIterator();
-+  SourceBufferIterator movedIterator(std::move(tmpIterator));
-   EXPECT_TRUE(movedIterator.Data());
-   EXPECT_EQ(chunkLength, movedIterator.Length());
-   ExpectChunkAndByteCount(movedIterator, 1, chunkLength);
- 
-   // Make sure that we can advance the iterator.
-   CheckedAdvanceIterator(movedIterator, chunkLength, 2, totalLength);
- 
-   // Make sure that the iterator handles completion properly.
-   CheckIteratorIsComplete(movedIterator, 2, totalLength);
- 
-   // Move-assign |movedIterator| from the iterator returned from
-   // GetIterator() and check that its state is as we expect.
--  movedIterator = std::move(GetIterator());
-+  tmpIterator = GetIterator();
-+  movedIterator = std::move(tmpIterator);
-   EXPECT_TRUE(movedIterator.Data());
-   EXPECT_EQ(chunkLength, movedIterator.Length());
-   ExpectChunkAndByteCount(movedIterator, 1, chunkLength);
- 
-   // Make sure that we can advance the iterator.
-   CheckedAdvanceIterator(movedIterator, chunkLength, 2, totalLength);
- 
-   // Make sure that the iterator handles completion properly.
-diff --git a/image/test/gtest/TestSurfacePipeIntegration.cpp b/image/test/gtest/TestSurfacePipeIntegration.cpp
---- a/image/test/gtest/TestSurfacePipeIntegration.cpp
-+++ b/image/test/gtest/TestSurfacePipeIntegration.cpp
-@@ -21,17 +21,17 @@ namespace mozilla {
- namespace image {
- 
- class TestSurfacePipeFactory
- {
- public:
-   static SurfacePipe SimpleSurfacePipe()
-   {
-     SurfacePipe pipe;
--    return std::move(pipe);
-+    return pipe;
-   }
- 
-   template <typename T>
-   static SurfacePipe SurfacePipeFromPipeline(T&& aPipeline)
-   {
-     return SurfacePipe { std::move(aPipeline) };
-   }
- 
-diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
---- a/js/src/builtin/TestingFunctions.cpp
-+++ b/js/src/builtin/TestingFunctions.cpp
-@@ -3522,17 +3522,17 @@ struct FindPathHandler {
-         if (!first)
-             return true;
- 
-         // Record how we reached this node. This is the last edge on a
-         // shortest path to this node.
-         EdgeName edgeName = DuplicateString(cx, edge.name.get());
-         if (!edgeName)
-             return false;
--        *backEdge = std::move(BackEdge(origin, std::move(edgeName)));
-+        *backEdge = BackEdge(origin, std::move(edgeName));
- 
-         // Have we reached our final target node?
-         if (edge.referent == target) {
-             // Record the path that got us here, which must be a shortest path.
-             if (!recordPath(traversal))
-                 return false;
-             foundPath = true;
-             traversal.stop();
-diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp
---- a/js/src/ctypes/CTypes.cpp
-+++ b/js/src/ctypes/CTypes.cpp
-@@ -5753,17 +5753,17 @@ ArrayType::BuildFFIType(JSContext* cx, J
-     JS_ReportAllocationOverflow(cx);
-     return nullptr;
-   }
- 
-   for (size_t i = 0; i < length; ++i)
-     ffiType->elements[i] = ffiBaseType;
-   ffiType->elements[length] = nullptr;
- 
--  return std::move(ffiType);
-+  return ffiType;
- }
- 
- bool
- ArrayType::IsArrayType(HandleValue v)
- {
-   if (!v.isObject())
-     return false;
-   JSObject* obj = &v.toObject();
-@@ -6301,17 +6301,17 @@ StructType::BuildFFIType(JSContext* cx, 
-   // Fill in the ffi_type's size and align fields. This makes libffi treat the
-   // type as initialized; it will not recompute the values. (We assume
-   // everything agrees; if it doesn't, we really want to know about it, which
-   // is the purpose of the above debug-only check.)
-   ffiType->size = structSize;
-   ffiType->alignment = structAlign;
- #endif
- 
--  return std::move(ffiType);
-+  return ffiType;
- }
- 
- bool
- StructType::Define(JSContext* cx, unsigned argc, Value* vp)
- {
-   CallArgs args = CallArgsFromVp(argc, vp);
-   RootedObject obj(cx, GetThisObject(cx, args, "StructType.prototype.define"));
-   if (!obj)
-diff --git a/js/src/ds/LifoAlloc.cpp b/js/src/ds/LifoAlloc.cpp
---- a/js/src/ds/LifoAlloc.cpp
-+++ b/js/src/ds/LifoAlloc.cpp
-@@ -46,21 +46,21 @@ BumpChunk::canAlloc(size_t n)
- 
- } // namespace detail
- } // namespace js
- 
- void
- LifoAlloc::freeAll()
- {
-     while (!chunks_.empty()) {
--        BumpChunk bc = std::move(chunks_.popFirst());
-+        BumpChunk bc = chunks_.popFirst();
-         decrementCurSize(bc->computedSizeOfIncludingThis());
-     }
-     while (!unused_.empty()) {
--        BumpChunk bc = std::move(unused_.popFirst());
-+        BumpChunk bc = unused_.popFirst();
-         decrementCurSize(bc->computedSizeOfIncludingThis());
-     }
- 
-     // Nb: maintaining curSize_ correctly isn't easy.  Fortunately, this is an
-     // excellent sanity check.
-     MOZ_ASSERT(curSize_ == 0);
- }
- 
-@@ -100,27 +100,27 @@ LifoAlloc::newChunkWithCapacity(size_t n
- bool
- LifoAlloc::getOrCreateChunk(size_t n)
- {
-     // Look for existing unused BumpChunks to satisfy the request, and pick the
-     // first one which is large enough, and move it into the list of used
-     // chunks.
-     if (!unused_.empty()) {
-         if (unused_.begin()->canAlloc(n)) {
--            chunks_.append(std::move(unused_.popFirst()));
-+            chunks_.append(unused_.popFirst());
-             return true;
-         }
- 
-         BumpChunkList::Iterator e(unused_.end());
-         for (BumpChunkList::Iterator i(unused_.begin()); i->next() != e.get(); ++i) {
-             detail::BumpChunk* elem = i->next();
-             MOZ_ASSERT(elem->empty());
-             if (elem->canAlloc(n)) {
--                BumpChunkList temp = std::move(unused_.splitAfter(i.get()));
--                chunks_.append(std::move(temp.popFirst()));
-+                BumpChunkList temp = unused_.splitAfter(i.get());
-+                chunks_.append(temp.popFirst());
-                 unused_.appendAll(std::move(temp));
-                 return true;
-             }
-         }
-     }
- 
-     // Allocate a new BumpChunk with enough space for the next allocation.
-     BumpChunk newChunk = newChunkWithCapacity(n);
-diff --git a/js/src/ds/LifoAlloc.h b/js/src/ds/LifoAlloc.h
---- a/js/src/ds/LifoAlloc.h
-+++ b/js/src/ds/LifoAlloc.h
-@@ -706,17 +706,17 @@ class LifoAlloc
-     void release(Mark mark) {
-         markCount--;
- 
-         // Move the blocks which are after the mark to the set of unused chunks.
-         BumpChunkList released;
-         if (!mark.markedChunk())
-             released = std::move(chunks_);
-         else
--            released = std::move(chunks_.splitAfter(mark.markedChunk()));
-+            released = chunks_.splitAfter(mark.markedChunk());
- 
-         // Release the content of all the blocks which are after the marks.
-         for (detail::BumpChunk& bc : released)
-             bc.release();
-         unused_.appendAll(std::move(released));
- 
-         // Release everything which follows the mark in the last chunk.
-         if (!chunks_.empty())
-diff --git a/js/src/vm/CodeCoverage.cpp b/js/src/vm/CodeCoverage.cpp
---- a/js/src/vm/CodeCoverage.cpp
-+++ b/js/src/vm/CodeCoverage.cpp
-@@ -511,17 +511,17 @@ LCovRealm::lookupOrAdd(JS::Realm* realm,
- 
-     char* source_name = js_strdup(name);
-     if (!source_name) {
-         outTN_.reportOutOfMemory();
-         return nullptr;
-     }
- 
-     // Allocate a new LCovSource for the current top-level.
--    if (!sources_->append(std::move(LCovSource(&alloc_, source_name)))) {
-+    if (!sources_->append(LCovSource(&alloc_, source_name))) {
-         outTN_.reportOutOfMemory();
-         return nullptr;
-     }
- 
-     return &sources_->back();
- }
- 
- void
-diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp
---- a/js/src/vm/UbiNode.cpp
-+++ b/js/src/vm/UbiNode.cpp
-@@ -262,17 +262,17 @@ class EdgeVectorTracer : public JS::Call
-                 name16[i] = name[i];
-             name16[i] = '\0';
-         }
- 
-         // The simplest code is correct! The temporary Edge takes
-         // ownership of name; if the append succeeds, the vector element
-         // then takes ownership; if the append fails, then the temporary
-         // retains it, and its destructor will free it.
--        if (!vec->append(std::move(Edge(name16, Node(thing))))) {
-+        if (!vec->append(Edge(name16, Node(thing)))) {
-             okay = false;
-             return;
-         }
-     }
- 
-   public:
-     // True if no errors (OOM, say) have yet occurred.
-     bool okay;
-@@ -543,17 +543,17 @@ RootList::addRoot(Node node, const char1
- 
-     UniqueTwoByteChars name;
-     if (edgeName) {
-         name = js::DuplicateString(edgeName);
-         if (!name)
-             return false;
-     }
- 
--    return edges.append(std::move(Edge(name.release(), node)));
-+    return edges.append(Edge(name.release(), node));
- }
- 
- const char16_t Concrete<RootList>::concreteTypeName[] = u"JS::ubi::RootList";
- 
- UniquePtr<EdgeRange>
- Concrete<RootList>::edges(JSContext* cx, bool wantNames) const {
-     MOZ_ASSERT_IF(wantNames, get().wantNames);
-     return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
-diff --git a/js/src/vm/UbiNodeShortestPaths.cpp b/js/src/vm/UbiNodeShortestPaths.cpp
---- a/js/src/vm/UbiNodeShortestPaths.cpp
-+++ b/js/src/vm/UbiNodeShortestPaths.cpp
-@@ -23,17 +23,17 @@ BackEdge::clone() const
-         return nullptr;
- 
-     clone->predecessor_ = predecessor();
-     if (name()) {
-         clone->name_ = js::DuplicateString(name().get());
-         if (!clone->name_)
-             return nullptr;
-     }
--    return std::move(clone);
-+    return clone;
- }
- 
- #ifdef DEBUG
- 
- static void
- dumpNode(const JS::ubi::Node& node)
- {
-     fprintf(stderr, "    %p ", (void*) node.identifier());
-diff --git a/js/src/wasm/WasmValidate.cpp b/js/src/wasm/WasmValidate.cpp
---- a/js/src/wasm/WasmValidate.cpp
-+++ b/js/src/wasm/WasmValidate.cpp
-@@ -1596,17 +1596,17 @@ DecodeExportName(Decoder& d, CStringSet*
-     if (p) {
-         d.fail("duplicate export");
-         return nullptr;
-     }
- 
-     if (!dupSet->add(p, exportName.get()))
-         return nullptr;
- 
--    return std::move(exportName);
-+    return exportName;
- }
- 
- static bool
- DecodeExport(Decoder& d, ModuleEnvironment* env, CStringSet* dupSet)
- {
-     UniqueChars fieldName = DecodeExportName(d, dupSet);
-     if (!fieldName)
-         return false;
-diff --git a/js/xpconnect/loader/URLPreloader.cpp b/js/xpconnect/loader/URLPreloader.cpp
---- a/js/xpconnect/loader/URLPreloader.cpp
-+++ b/js/xpconnect/loader/URLPreloader.cpp
-@@ -619,21 +619,21 @@ URLPreloader::ShallowSizeOfIncludingThis
- 
- Result<FileLocation, nsresult>
- URLPreloader::CacheKey::ToFileLocation()
- {
-     if (mType == TypeFile) {
-         nsCOMPtr<nsIFile> file;
-         MOZ_TRY(NS_NewLocalFile(NS_ConvertUTF8toUTF16(mPath), false,
-                                 getter_AddRefs(file)));
--        return std::move(FileLocation(file));
-+        return FileLocation(file);
-     }
- 
-     RefPtr<nsZipArchive> zip = Archive();
--    return std::move(FileLocation(zip, mPath.get()));
-+    return FileLocation(zip, mPath.get());
- }
- 
- Result<const nsCString, nsresult>
- URLPreloader::URLEntry::Read()
- {
-     FileLocation location;
-     MOZ_TRY_VAR(location, ToFileLocation());
- 
-diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
---- a/layout/base/PresShell.cpp
-+++ b/layout/base/PresShell.cpp
-@@ -6248,17 +6248,17 @@ PresShell::Paint(nsView*         aViewTo
-       bool computeInvalidRect = computeInvalidFunc ||
-                                 (layerManager->GetBackendType() == LayersBackend::LAYERS_BASIC);
- 
-       UniquePtr<LayerProperties> props;
-       // For WR, the layermanager has no root layer. We want to avoid
-       // calling ComputeDifferences in that case because it assumes non-null
-       // and crashes.
-       if (computeInvalidRect && layerManager->GetRoot()) {
--        props = std::move(LayerProperties::CloneFrom(layerManager->GetRoot()));
-+        props = LayerProperties::CloneFrom(layerManager->GetRoot());
-       }
- 
-       MaybeSetupTransactionIdAllocator(layerManager, presContext);
- 
-       if (layerManager->EndEmptyTransaction((aFlags & PAINT_COMPOSITE) ?
-             LayerManager::END_DEFAULT : LayerManager::END_NO_COMPOSITE)) {
-         nsIntRegion invalid;
-         bool areaOverflowed = false;
-diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp
---- a/layout/painting/FrameLayerBuilder.cpp
-+++ b/layout/painting/FrameLayerBuilder.cpp
-@@ -6613,18 +6613,18 @@ FrameLayerBuilder::DrawPaintedLayer(Pain
-     FlashPaint(aContext);
-   }
- 
-   if (presContext->GetDocShell() && isActiveLayerManager) {
-     nsDocShell* docShell = static_cast<nsDocShell*>(presContext->GetDocShell());
-     RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
- 
-     if (timelines && timelines->HasConsumer(docShell)) {
--      timelines->AddMarkerForDocShell(docShell, std::move(
--        MakeUnique<LayerTimelineMarker>(aRegionToDraw)));
-+      timelines->AddMarkerForDocShell(docShell,
-+        MakeUnique<LayerTimelineMarker>(aRegionToDraw));
-     }
-   }
- 
-   if (!aRegionToInvalidate.IsEmpty()) {
-     aLayer->AddInvalidRect(aRegionToInvalidate.GetBounds());
-   }
- }
- 
-diff --git a/layout/painting/RetainedDisplayListBuilder.cpp b/layout/painting/RetainedDisplayListBuilder.cpp
---- a/layout/painting/RetainedDisplayListBuilder.cpp
-+++ b/layout/painting/RetainedDisplayListBuilder.cpp
-@@ -509,17 +509,17 @@ RetainedDisplayListBuilder::MergeDisplay
- {
-   MergeState merge(this, *aOldList, aOuterKey);
- 
-   Maybe<MergedListIndex> previousItemIndex;
-   while (nsDisplayItem* item = aNewList->RemoveBottom()) {
-     previousItemIndex = Some(merge.ProcessItemFromNewList(item, previousItemIndex));
-   }
- 
--  *aOutList = std::move(merge.Finalize());
-+  *aOutList = merge.Finalize();
-   aOutContainerASR = merge.mContainerASR;
-   return merge.mResultIsModified;
- }
- 
- static void
- TakeAndAddModifiedAndFramesWithPropsFromRootFrame(
-   nsTArray<nsIFrame*>* aModifiedFrames,
-   nsTArray<nsIFrame*>* aFramesWithProps,
-diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp
---- a/layout/painting/nsDisplayList.cpp
-+++ b/layout/painting/nsDisplayList.cpp
-@@ -2728,17 +2728,17 @@ already_AddRefed<LayerManager> nsDisplay
- 
-   UniquePtr<LayerProperties> props;
- 
-   bool computeInvalidRect = (computeInvalidFunc ||
-                              (!layerManager->IsCompositingCheap() && layerManager->NeedsWidgetInvalidation())) &&
-                             widgetTransaction;
- 
-   if (computeInvalidRect) {
--    props = std::move(LayerProperties::CloneFrom(layerManager->GetRoot()));
-+    props = LayerProperties::CloneFrom(layerManager->GetRoot());
-   }
- 
-   if (doBeginTransaction) {
-     if (aCtx) {
-       if (!layerManager->BeginTransactionWithTarget(aCtx)) {
-         return nullptr;
-       }
-     } else {
-diff --git a/layout/style/StyleSheet.cpp b/layout/style/StyleSheet.cpp
---- a/layout/style/StyleSheet.cpp
-+++ b/layout/style/StyleSheet.cpp
-@@ -1041,17 +1041,17 @@ StyleSheet::ParseSheet(css::Loader* aLoa
-     Servo_StyleSheet_FromUTF8BytesAsync(loadDataHolder,
-                                         Inner().mURLData,
-                                         &aBytes,
-                                         mParsingMode,
-                                         aLoadData->mLineNumber,
-                                         aLoader->GetCompatibilityMode());
-   }
- 
--  return std::move(p);
-+  return p;
- }
- 
- void
- StyleSheet::FinishAsyncParse(already_AddRefed<RawServoStyleSheetContents> aSheetContents)
- {
-   MOZ_ASSERT(NS_IsMainThread());
-   MOZ_ASSERT(!mParsePromise.IsEmpty());
-   Inner().mContents = aSheetContents;
-diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp
---- a/layout/style/nsTransitionManager.cpp
-+++ b/layout/style/nsTransitionManager.cpp
-@@ -601,17 +601,17 @@ AppendKeyframe(double aOffset,
- {
-   Keyframe& frame = *aKeyframes.AppendElement();
-   frame.mOffset.emplace(aOffset);
- 
-   if (aValue.mServo) {
-     RefPtr<RawServoDeclarationBlock> decl =
-       Servo_AnimationValue_Uncompute(aValue.mServo).Consume();
-     frame.mPropertyValues.AppendElement(
--      std::move(PropertyValuePair(aProperty, std::move(decl))));
-+      PropertyValuePair(aProperty, std::move(decl)));
-   } else {
-     MOZ_CRASH("old style system disabled");
-   }
-   return frame;
- }
- 
- static nsTArray<Keyframe>
- GetTransitionKeyframes(nsCSSPropertyID aProperty,
-diff --git a/media/webrtc/signaling/gtest/sdp_unittests.cpp b/media/webrtc/signaling/gtest/sdp_unittests.cpp
---- a/media/webrtc/signaling/gtest/sdp_unittests.cpp
-+++ b/media/webrtc/signaling/gtest/sdp_unittests.cpp
-@@ -1506,39 +1506,39 @@ class NewSdpTest : public ::testing::Tes
-                    public ::testing::WithParamInterface<
-                      ::testing::tuple<bool, bool> > {
-   public:
-     NewSdpTest() {}
- 
-     void ParseSdp(const std::string &sdp, bool expectSuccess = true) {
-       if (::testing::get<1>(GetParam())) {
-         mSdpErrorHolder = &mSipccParser;
--        mSdp = std::move(mSipccParser.Parse(sdp));
-+        mSdp = mSipccParser.Parse(sdp);
-       } else {
-         mSdpErrorHolder = &mRustParser;
--        mSdp = std::move(mRustParser.Parse(sdp));
-+        mSdp = mRustParser.Parse(sdp);
-       }
- 
-       // Are we configured to do a parse and serialize before actually
-       // running the test?
-       if (::testing::get<0>(GetParam())) {
-         std::stringstream os;
- 
-         if (expectSuccess) {
-           ASSERT_TRUE(!!mSdp) << "Parse failed on first pass: "
-                               << GetParseErrors();
-         }
- 
-         if (mSdp) {
-           // Serialize and re-parse
-           mSdp->Serialize(os);
-           if (::testing::get<1>(GetParam())) {
--            mSdp = std::move(mSipccParser.Parse(os.str()));
-+            mSdp = mSipccParser.Parse(os.str());
-           } else {
--            mSdp = std::move(mRustParser.Parse(os.str()));
-+            mSdp = mRustParser.Parse(os.str());
-           }
- 
-           // Whether we expected the parse to work or not, it should
-           // succeed the second time if it succeeded the first.
-           ASSERT_TRUE(!!mSdp) << "Parse failed on second pass, SDP was: "
-             << std::endl << os.str() <<  std::endl
-             << "Errors were: " << GetParseErrors();
- 
-diff --git a/mfbt/tests/TestUniquePtr.cpp b/mfbt/tests/TestUniquePtr.cpp
---- a/mfbt/tests/TestUniquePtr.cpp
-+++ b/mfbt/tests/TestUniquePtr.cpp
-@@ -70,17 +70,17 @@ ReturnUniqueA()
- {
-   return UniqueA(new B);
- }
- 
- static UniqueA
- ReturnLocalA()
- {
-   UniqueA a(new A);
--  return std::move(a);
-+  return a;
- }
- 
- static void
- TestDeleterType()
- {
-   // Make sure UniquePtr will use its deleter's pointer type if it defines one.
-   typedef int* Ptr;
-   struct Deleter {
-@@ -363,17 +363,17 @@ SetMallocedInt(UniquePtr<int, FreeSignat
- }
- 
- static UniquePtr<int, FreeSignature>
- MallocedInt(int aI)
- {
-   UniquePtr<int, FreeSignature>
-     ptr(static_cast<int*>(malloc(sizeof(int))), free);
-   *ptr = aI;
--  return std::move(ptr);
-+  return ptr;
- }
- static bool
- TestFunctionReferenceDeleter()
- {
-   // Look for allocator mismatches and leaks to verify these bits
-   UniquePtr<int, FreeSignature> i1(MallocedInt(17));
-   CHECK(*i1 == 17);
- 
-diff --git a/security/certverifier/tests/gtest/CTSerializationTest.cpp b/security/certverifier/tests/gtest/CTSerializationTest.cpp
---- a/security/certverifier/tests/gtest/CTSerializationTest.cpp
-+++ b/security/certverifier/tests/gtest/CTSerializationTest.cpp
-@@ -178,18 +178,18 @@ TEST_F(CTSerializationTest, FailsDecodin
- }
- 
- TEST_F(CTSerializationTest, EncodesSCTList)
- {
-   const uint8_t SCT_1[] = { 0x61, 0x62, 0x63 };
-   const uint8_t SCT_2[] = { 0x64, 0x65, 0x66 };
- 
-   Vector<Input> list;
--  ASSERT_TRUE(list.append(std::move(Input(SCT_1))));
--  ASSERT_TRUE(list.append(std::move(Input(SCT_2))));
-+  ASSERT_TRUE(list.append(Input(SCT_1)));
-+  ASSERT_TRUE(list.append(Input(SCT_2)));
- 
-   Buffer encodedList;
-   ASSERT_EQ(Success, EncodeSCTList(list, encodedList));
- 
-   Reader listReader;
-   ASSERT_EQ(Success, DecodeSCTList(InputForBuffer(encodedList), listReader));
- 
-   Input decoded1;
-diff --git a/security/manager/ssl/nsPKCS12Blob.cpp b/security/manager/ssl/nsPKCS12Blob.cpp
---- a/security/manager/ssl/nsPKCS12Blob.cpp
-+++ b/security/manager/ssl/nsPKCS12Blob.cpp
-@@ -297,17 +297,17 @@ nsPKCS12Blob::newPKCS12FilePassword(uint
-   bool pressedOK = false;
-   rv = certDialogs->SetPKCS12FilePassword(mUIContext, password, &pressedOK);
-   if (NS_FAILED(rv)) {
-     return rv;
-   }
-   if (!pressedOK) {
-     return NS_OK;
-   }
--  passwordBuffer = std::move(stringToBigEndianBytes(password, passwordBufferLength));
-+  passwordBuffer = stringToBigEndianBytes(password, passwordBufferLength);
-   return NS_OK;
- }
- 
- // Launch a dialog requesting the user for the password to a PKCS#12 file.
- // Handle user canceled by returning null password (caller must catch).
- nsresult
- nsPKCS12Blob::getPKCS12FilePassword(uint32_t& passwordBufferLength,
-                                     UniquePtr<uint8_t[]>& passwordBuffer)
-@@ -323,17 +323,17 @@ nsPKCS12Blob::getPKCS12FilePassword(uint
-   bool pressedOK = false;
-   rv = certDialogs->GetPKCS12FilePassword(mUIContext, password, &pressedOK);
-   if (NS_FAILED(rv)) {
-     return rv;
-   }
-   if (!pressedOK) {
-     return NS_OK;
-   }
--  passwordBuffer = std::move(stringToBigEndianBytes(password, passwordBufferLength));
-+  passwordBuffer = stringToBigEndianBytes(password, passwordBufferLength);
-   return NS_OK;
- }
- 
- // Given a decoder, read bytes from file and input them to the decoder.
- nsresult
- nsPKCS12Blob::inputToDecoder(UniqueSEC_PKCS12DecoderContext& dcx, nsIFile* file,
-                              PRErrorCode& nssError)
- {
-diff --git a/security/sandbox/linux/broker/SandboxBroker.cpp b/security/sandbox/linux/broker/SandboxBroker.cpp
---- a/security/sandbox/linux/broker/SandboxBroker.cpp
-+++ b/security/sandbox/linux/broker/SandboxBroker.cpp
-@@ -72,17 +72,17 @@ SandboxBroker::Create(UniquePtr<const Po
-   // Can't use MakeUnique here because the constructor is private.
-   UniquePtr<SandboxBroker> rv(new SandboxBroker(std::move(aPolicy), aChildPid,
-                                                 clientFd));
-   if (clientFd < 0) {
-     rv = nullptr;
-   } else {
-     aClientFdOut = ipc::FileDescriptor(clientFd);
-   }
--  return std::move(rv);
-+  return rv;
- }
- 
- SandboxBroker::~SandboxBroker() {
-   // If the constructor failed, there's nothing to be done here.
-   if (mFileDesc < 0) {
-     return;
-   }
- 
-diff --git a/security/sandbox/linux/reporter/SandboxReporter.cpp b/security/sandbox/linux/reporter/SandboxReporter.cpp
---- a/security/sandbox/linux/reporter/SandboxReporter.cpp
-+++ b/security/sandbox/linux/reporter/SandboxReporter.cpp
-@@ -284,16 +284,12 @@ SandboxReporter::GetSnapshot()
-   snapshot.mOffset = start;
-   snapshot.mReports.Clear();
-   snapshot.mReports.SetCapacity(mCount - start);
-   for (size_t i = start; i < mCount; ++i) {
-     const SandboxReport* rep = &mBuffer[i % kSandboxReporterBufferSize];
-     MOZ_ASSERT(rep->IsValid());
-     snapshot.mReports.AppendElement(*rep);
-   }
--  // Named Return Value Optimization would apply here, but C++11
--  // doesn't require it; so, instead of possibly copying the entire
--  // array contents, invoke the move constructor and copy at most a
--  // few words.
--  return std::move(snapshot);
-+  return snapshot;
- }
- 
- } // namespace mozilla
-diff --git a/toolkit/components/extensions/webrequest/WebRequestService.cpp b/toolkit/components/extensions/webrequest/WebRequestService.cpp
---- a/toolkit/components/extensions/webrequest/WebRequestService.cpp
-+++ b/toolkit/components/extensions/webrequest/WebRequestService.cpp
-@@ -42,17 +42,17 @@ UniquePtr<WebRequestChannelEntry>
- WebRequestService::RegisterChannel(ChannelWrapper* aChannel)
- {
-   UniquePtr<ChannelEntry> entry(new ChannelEntry(aChannel));
- 
-   auto key = mChannelEntries.LookupForAdd(entry->mChannelId);
-   MOZ_DIAGNOSTIC_ASSERT(!key);
-   key.OrInsert([&entry]() { return entry.get(); });
- 
--  return std::move(entry);
-+  return entry;
- 
- }
- 
- already_AddRefed<nsITraceableChannel>
- WebRequestService::GetTraceableChannel(uint64_t aChannelId,
-                                        nsAtom* aAddonId,
-                                        nsIContentParent* aContentParent)
- {
-diff --git a/toolkit/components/url-classifier/tests/gtest/TestClassifier.cpp b/toolkit/components/url-classifier/tests/gtest/TestClassifier.cpp
---- a/toolkit/components/url-classifier/tests/gtest/TestClassifier.cpp
-+++ b/toolkit/components/url-classifier/tests/gtest/TestClassifier.cpp
-@@ -17,17 +17,17 @@ GetClassifier()
- {
-   nsCOMPtr<nsIFile> file;
-   NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
- 
-   UniquePtr<Classifier> classifier = MakeUnique<Classifier>();
-   nsresult rv = classifier->Open(*file);
-   EXPECT_TRUE(rv == NS_OK);
- 
--  return std::move(classifier);
-+  return classifier;
- }
- 
- static nsresult
- SetupLookupCacheV4(Classifier* classifier,
-                    const _PrefixArray& aPrefixArray,
-                    const nsACString& aTable)
- {
-   LookupCacheV4* lookupCache =
-diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp
---- a/tools/profiler/core/platform.cpp
-+++ b/tools/profiler/core/platform.cpp
-@@ -1787,17 +1787,17 @@ CollectJavaThreadProfileData()
-       if (!frameName) {
-         break;
-       }
-       buffer->CollectCodeLocation("", frameName->ToCString().get(), -1,
-                                   Nothing());
-     }
-     sampleId++;
-   }
--  return std::move(buffer);
-+  return buffer;
- }
- #endif
- 
- static void
- locked_profiler_stream_json_for_this_process(PSLockRef aLock,
-                                              SpliceableJSONWriter& aWriter,
-                                              double aSinceTime,
-                                              bool aIsShuttingDown)
-diff --git a/widget/android/nsAppShell.h b/widget/android/nsAppShell.h
---- a/widget/android/nsAppShell.h
-+++ b/widget/android/nsAppShell.h
-@@ -239,28 +239,28 @@ protected:
-                 nsAppShell::RecordLatencies();
- #endif
-                 lock.Wait();
-             }
- 
-             // Ownership of event object transfers to the return value.
-             mozilla::UniquePtr<Event> event(mQueue.popFirst());
-             if (!event || !event->mPostTime) {
--                return std::move(event);
-+                return event;
-             }
- 
- #ifdef EARLY_BETA_OR_EARLIER
-             const size_t latencyType = (event->ActivityType() ==
-                     Event::Type::kUIActivity) ? LATENCY_UI : LATENCY_OTHER;
-             const uint64_t latency = Event::GetTime() - event->mPostTime;
- 
-             sLatencyCount[latencyType]++;
-             sLatencyTime[latencyType] += latency;
- #endif
--            return std::move(event);
-+            return event;
-         }
- 
-     } mEventQueue;
- 
-     mozilla::CondVar mSyncRunFinished;
-     bool mSyncRunQuit;
- 
-     bool mAllowCoalescingTouches;
-diff --git a/xpcom/tests/gtest/TestPLDHash.cpp b/xpcom/tests/gtest/TestPLDHash.cpp
---- a/xpcom/tests/gtest/TestPLDHash.cpp
-+++ b/xpcom/tests/gtest/TestPLDHash.cpp
-@@ -192,17 +192,24 @@ static const PLDHashTableOps trivialOps 
- 
- TEST(PLDHashTableTest, MoveSemantics)
- {
-   PLDHashTable t1(&trivialOps, sizeof(PLDHashEntryStub));
-   t1.Add((const void*)88);
-   PLDHashTable t2(&trivialOps, sizeof(PLDHashEntryStub));
-   t2.Add((const void*)99);
- 
-+#if defined(__clang__)
-+#pragma clang diagnostic push
-+#pragma clang diagnostic ignored "-Wself-move"
-+#endif
-   t1 = std::move(t1);   // self-move
-+#if defined(__clang__)
-+#pragma clang diagnostic pop
-+#endif
- 
-   t1 = std::move(t2);   // empty overwritten with empty
- 
-   PLDHashTable t3(&trivialOps, sizeof(PLDHashEntryStub));
-   PLDHashTable t4(&trivialOps, sizeof(PLDHashEntryStub));
-   t3.Add((const void*)88);
- 
-   t3 = std::move(t4);   // non-empty overwritten with empty
-diff --git a/xpcom/tests/gtest/TestTArray.cpp b/xpcom/tests/gtest/TestTArray.cpp
---- a/xpcom/tests/gtest/TestTArray.cpp
-+++ b/xpcom/tests/gtest/TestTArray.cpp
-@@ -133,18 +133,26 @@ TEST(TArray, Assign)
- 
- TEST(TArray, AssignmentOperatorSelfAssignment)
- {
-   nsTArray<int> array;
-   array = DummyArray();
- 
-   array = *&array;
-   ASSERT_EQ(DummyArray(), array);
--  array = std::move(array);
-+
-+#if defined(__clang__)
-+#pragma clang diagnostic push
-+#pragma clang diagnostic ignored "-Wself-move"
-+#endif
-+  array = std::move(array); // self-move
-   ASSERT_EQ(DummyArray(), array);
-+#if defined(__clang__)
-+#pragma clang diagnostic pop
-+#endif
- }
- 
- TEST(TArray, CopyOverlappingForwards)
- {
-   const size_t rangeLength = 8;
-   const size_t initialLength = 2 * rangeLength;
-   uint32_t destructionCounters[initialLength];
-   nsTArray<Movable> array;

+ 0 - 60
frg/work-js/mozilla-release/patches/mozilla-central-push_422049.patch

@@ -1,60 +0,0 @@
-# HG changeset patch
-# User Steve Fink <sfink@mozilla.com>
-# Date 1528239816 25200
-#      Tue Jun 05 16:03:36 2018 -0700
-# Node ID bdf9bd1db757904ed0323367fdee278ff94567f8
-# Parent  ad337f9e2fcf85ddff068a4a1afe0739ef8a6220
-Bug 1466387 - Set up the gray root tracer on worker thread, r=jonco
-
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -3590,16 +3590,17 @@ WorkerMain(void* arg)
-         sc->markObservers.reset();
-         JS_DestroyContext(cx);
-         js_delete(sc);
-         js_delete(input);
-     });
- 
-     sc->isWorker = true;
-     JS_SetContextPrivate(cx, sc);
-+    JS_SetGrayGCRootsTracer(cx, TraceGrayRoots, nullptr);
-     SetWorkerContextOptions(cx);
-     JS::SetBuildIdOp(cx, ShellBuildId);
- 
-     JS_SetFutexCanWait(cx);
-     JS::SetWarningReporter(cx, WarningReporter);
-     js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
-     JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
- 
-diff --git a/js/src/tests/non262/regress/regress-1466387-worker-grayroot.js b/js/src/tests/non262/regress/regress-1466387-worker-grayroot.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/tests/non262/regress/regress-1466387-worker-grayroot.js
-@@ -0,0 +1,26 @@
-+var BUGNUMBER = 1466387;
-+var summary = 'grayRoot() testing on worker thread';
-+
-+// Before bug 1466387, the gray root tracer was not set up on worker threads,
-+// but the grayRoot() function was still available. This resulted in a GC
-+// collecting the gray root, then a read barrier firing on the dead object.
-+//
-+// This is a crashtest. If it does not crash, it will throw a ReferenceError,
-+// but that's ok.
-+
-+print('BUGNUMBER: ' + BUGNUMBER);
-+print("STATUS: " + summary);
-+
-+evalInWorker(`
-+  var wm = new WeakMap();
-+  grayRoot().map = wm;
-+  gczeal(4,10);
-+  evaluate(\`
-+  grayRoot().map = __v_1173;
-+  if (!class i   { constructor() { } }  ()) {
-+    (function __f_252( get       ,    )  {})();
-+  }
-+  \`);
-+`);
-+
-+this.reportCompare && reportCompare(true, true, summary);

+ 0 - 55
frg/work-js/mozilla-release/patches/mozilla-central-push_422050.patch

@@ -1,55 +0,0 @@
-# HG changeset patch
-# User Steve Fink <sfink@mozilla.com>
-# Date 1528245672 25200
-#      Tue Jun 05 17:41:12 2018 -0700
-# Node ID 17bb0a45975b93c4003e4436706e3caf7c44d9fd
-# Parent  bdf9bd1db757904ed0323367fdee278ff94567f8
-Bug 1466633 - GCManagedDeletePolicy: do not clear edges during GC, r=jonco
-
-diff --git a/js/src/gc/DeletePolicy.h b/js/src/gc/DeletePolicy.h
---- a/js/src/gc/DeletePolicy.h
-+++ b/js/src/gc/DeletePolicy.h
-@@ -2,16 +2,17 @@
-  * vim: set ts=8 sts=4 et sw=4 tw=99:
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #ifndef gc_DeletePolicy_h
- #define gc_DeletePolicy_h
- 
-+#include "gc/Barrier.h"
- #include "js/TracingAPI.h"
- #ifdef ENABLE_BIGINT
- #include "vm/BigIntType.h"
- #endif
- 
- namespace js {
- namespace gc {
- 
-@@ -68,18 +69,23 @@ IsClearEdgesTracer(JSTracer *trc)
-  * into the object and make it safe to delete.
-  */
- template <typename T>
- struct GCManagedDeletePolicy
- {
-     void operator()(const T* constPtr) {
-         if (constPtr) {
-             auto ptr = const_cast<T*>(constPtr);
--            gc::ClearEdgesTracer trc;
--            ptr->trace(&trc);
-+            if (JS::CurrentThreadIsHeapCollecting()) {
-+                MOZ_ASSERT(js::CurrentThreadIsGCSweeping());
-+                // Do not attempt to clear out storebuffer edges.
-+            } else {
-+                gc::ClearEdgesTracer trc;
-+                ptr->trace(&trc);
-+            }
-             js_delete(ptr);
-         }
-     }
- };
- 
- } // namespace js
- 
- #endif // gc_DeletePolicy_h

+ 0 - 38
frg/work-js/mozilla-release/patches/mozilla-central-push_422053.patch

@@ -1,38 +0,0 @@
-# HG changeset patch
-# User Steve Fink <sfink@mozilla.com>
-# Date 1528258134 25200
-#      Tue Jun 05 21:08:54 2018 -0700
-# Node ID 4ede0210acdbfeeaf7ec13e445618f94540eccf1
-# Parent  aacc6666a49af6cd48972eec8ad62040b8ab20ae
-Bug 1467249 - Upload JS shell test failure output, r=nbp
-
-diff --git a/js/src/devtools/automation/autospider.py b/js/src/devtools/automation/autospider.py
---- a/js/src/devtools/automation/autospider.py
-+++ b/js/src/devtools/automation/autospider.py
-@@ -481,16 +481,26 @@ if use_minidump:
-     # Set up later js invocations to run with the breakpad injector loaded.
-     # Originally, I intended for this to be used with LD_PRELOAD, but when
-     # cross-compiling from 64- to 32-bit, that will fail and produce stderr
-     # output when running any 64-bit commands, which breaks eg mozconfig
-     # processing. So use the --dll command line mechanism universally.
-     for v in ('JSTESTS_EXTRA_ARGS', 'JITTEST_EXTRA_ARGS'):
-         env[v] = "--args='--dll %s' %s" % (injector_lib, env.get(v, ''))
- 
-+# Store all failure output to an uploaded log file. This could be done in each
-+# individual variant, but it's verbose and we want it across the board.
-+if AUTOMATION:
-+    env['JSTESTS_EXTRA_ARGS'] = "--show-output --show-cmd --failed-only --output-file={MOZ_UPLOAD_DIR}/jstests.fail.txt {old}".format(
-+        MOZ_UPLOAD_DIR=env.get('MOZ_UPLOAD_DIR', '/tmp'),
-+        old = env.get('JSTESTS_EXTRA_ARGS', ''))
-+    env['JITTEST_EXTRA_ARGS'] = "--write-failures={MOZ_UPLOAD_DIR}/jit-tests.fail.txt --write-failure-output {old}".format(
-+        MOZ_UPLOAD_DIR=env.get('MOZ_UPLOAD_DIR', '/tmp'),
-+        old = env.get('JITTEST_EXTRA_ARGS', ''))
-+
- # Always run all enabled tests, even if earlier ones failed. But return the
- # first failed status.
- results = []
- 
- if 'checks' in test_suites:
-     results.append(run_test_command([MAKE, 'check']))
- 
- if 'jittest' in test_suites:

+ 0 - 149
frg/work-js/mozilla-release/patches/mozilla-central-push_422054.patch

@@ -1,149 +0,0 @@
-# HG changeset patch
-# User shindli <shindli@mozilla.com>
-# Date 1528505462 -10800
-#      Sat Jun 09 03:51:02 2018 +0300
-# Node ID a8231f7c5073c597ab8bb21cee441f4e54f21c52
-# Parent  4ede0210acdbfeeaf7ec13e445618f94540eccf1
-Backed out 3 changesets (bug 1466633, bug 1467248, bug 1466387) for spidermonkey bustages in non262/regress/regress-1466387-worker-grayroot.js on a CLOSED TREE
-
-Backed out changeset 1e833c6a3ba2 (bug 1467248)
-Backed out changeset 17bb0a45975b (bug 1466633)
-Backed out changeset bdf9bd1db757 (bug 1466387)
-
-diff --git a/js/src/gc/DeletePolicy.h b/js/src/gc/DeletePolicy.h
---- a/js/src/gc/DeletePolicy.h
-+++ b/js/src/gc/DeletePolicy.h
-@@ -2,17 +2,16 @@
-  * vim: set ts=8 sts=4 et sw=4 tw=99:
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- #ifndef gc_DeletePolicy_h
- #define gc_DeletePolicy_h
- 
--#include "gc/Barrier.h"
- #include "js/TracingAPI.h"
- #ifdef ENABLE_BIGINT
- #include "vm/BigIntType.h"
- #endif
- 
- namespace js {
- namespace gc {
- 
-@@ -69,23 +68,18 @@ IsClearEdgesTracer(JSTracer *trc)
-  * into the object and make it safe to delete.
-  */
- template <typename T>
- struct GCManagedDeletePolicy
- {
-     void operator()(const T* constPtr) {
-         if (constPtr) {
-             auto ptr = const_cast<T*>(constPtr);
--            if (JS::CurrentThreadIsHeapCollecting()) {
--                MOZ_ASSERT(js::CurrentThreadIsGCSweeping());
--                // Do not attempt to clear out storebuffer edges.
--            } else {
--                gc::ClearEdgesTracer trc;
--                ptr->trace(&trc);
--            }
-+            gc::ClearEdgesTracer trc;
-+            ptr->trace(&trc);
-             js_delete(ptr);
-         }
-     }
- };
- 
- } // namespace js
- 
- #endif // gc_DeletePolicy_h
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -3590,17 +3590,16 @@ WorkerMain(void* arg)
-         sc->markObservers.reset();
-         JS_DestroyContext(cx);
-         js_delete(sc);
-         js_delete(input);
-     });
- 
-     sc->isWorker = true;
-     JS_SetContextPrivate(cx, sc);
--    JS_SetGrayGCRootsTracer(cx, TraceGrayRoots, nullptr);
-     SetWorkerContextOptions(cx);
-     JS::SetBuildIdOp(cx, ShellBuildId);
- 
-     JS_SetFutexCanWait(cx);
-     JS::SetWarningReporter(cx, WarningReporter);
-     js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
-     JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
- 
-diff --git a/js/src/tests/non262/regress/regress-1466387-worker-grayroot.js b/js/src/tests/non262/regress/regress-1466387-worker-grayroot.js
-deleted file mode 100644
---- a/js/src/tests/non262/regress/regress-1466387-worker-grayroot.js
-+++ /dev/null
-@@ -1,26 +0,0 @@
--var BUGNUMBER = 1466387;
--var summary = 'grayRoot() testing on worker thread';
--
--// Before bug 1466387, the gray root tracer was not set up on worker threads,
--// but the grayRoot() function was still available. This resulted in a GC
--// collecting the gray root, then a read barrier firing on the dead object.
--//
--// This is a crashtest. If it does not crash, it will throw a ReferenceError,
--// but that's ok.
--
--print('BUGNUMBER: ' + BUGNUMBER);
--print("STATUS: " + summary);
--
--evalInWorker(`
--  var wm = new WeakMap();
--  grayRoot().map = wm;
--  gczeal(4,10);
--  evaluate(\`
--  grayRoot().map = __v_1173;
--  if (!class i   { constructor() { } }  ()) {
--    (function __f_252( get       ,    )  {})();
--  }
--  \`);
--`);
--
--this.reportCompare && reportCompare(true, true, summary);
-diff --git a/taskcluster/ci/spidermonkey/linux.yml b/taskcluster/ci/spidermonkey/linux.yml
---- a/taskcluster/ci/spidermonkey/linux.yml
-+++ b/taskcluster/ci/spidermonkey/linux.yml
-@@ -24,32 +24,32 @@ sm-mozjs-sys-linux64/debug:
-     description: "Build js/src as the mozjs_sys Rust crate"
-     index:
-         job-name: sm-mozjs-sys-linux64-debug
-     treeherder:
-         platform: linux64/debug
-         symbol: SM(mozjs-crate)
-     run:
-         using: spidermonkey-mozjs-crate
--        spidermonkey-variant: plaindebug
-+        spidermonkey-variant: plain
-     run-on-projects: ['integration', 'release', 'try']
- 
- sm-rust-bindings-linux64/debug:
-     description: "Build and test the Rust bindings for SpiderMonkey"
-     index:
-         job-name: sm-rust-bindings-linux64-debug
-     treeherder:
-         symbol: SM(rust)
-         tier: 2
-         platform: linux64/debug
-     worker:
-         docker-image: {in-tree: debian7-mozjs-rust-build}
-     run:
-         using: spidermonkey-rust-bindings
--        spidermonkey-variant: plaindebug
-+        spidermonkey-variant: plain
-     run-on-projects: ['integration', 'release', 'try']
- 
- sm-plain-linux64/debug:
-     description: "Spidermonkey Plain"
-     index:
-         job-name: sm-plain-linux64-debug
-     treeherder:
-         platform: linux64/debug

+ 0 - 38
frg/work-js/mozilla-release/patches/mozilla-central-push_422055.patch

@@ -1,38 +0,0 @@
-# HG changeset patch
-# User shindli <shindli@mozilla.com>
-# Date 1528505549 -10800
-#      Sat Jun 09 03:52:29 2018 +0300
-# Node ID 0ffe269f5e96c70120a935cf322397e3baf6103b
-# Parent  a8231f7c5073c597ab8bb21cee441f4e54f21c52
-Backed out changeset 4ede0210acdb (bug 1467249) for linting failures in /builds/worker/checkouts/gecko/js/src/devtools/automation/autospider.py on a CLOSED TREE
-
-diff --git a/js/src/devtools/automation/autospider.py b/js/src/devtools/automation/autospider.py
---- a/js/src/devtools/automation/autospider.py
-+++ b/js/src/devtools/automation/autospider.py
-@@ -481,26 +481,16 @@ if use_minidump:
-     # Set up later js invocations to run with the breakpad injector loaded.
-     # Originally, I intended for this to be used with LD_PRELOAD, but when
-     # cross-compiling from 64- to 32-bit, that will fail and produce stderr
-     # output when running any 64-bit commands, which breaks eg mozconfig
-     # processing. So use the --dll command line mechanism universally.
-     for v in ('JSTESTS_EXTRA_ARGS', 'JITTEST_EXTRA_ARGS'):
-         env[v] = "--args='--dll %s' %s" % (injector_lib, env.get(v, ''))
- 
--# Store all failure output to an uploaded log file. This could be done in each
--# individual variant, but it's verbose and we want it across the board.
--if AUTOMATION:
--    env['JSTESTS_EXTRA_ARGS'] = "--show-output --show-cmd --failed-only --output-file={MOZ_UPLOAD_DIR}/jstests.fail.txt {old}".format(
--        MOZ_UPLOAD_DIR=env.get('MOZ_UPLOAD_DIR', '/tmp'),
--        old = env.get('JSTESTS_EXTRA_ARGS', ''))
--    env['JITTEST_EXTRA_ARGS'] = "--write-failures={MOZ_UPLOAD_DIR}/jit-tests.fail.txt --write-failure-output {old}".format(
--        MOZ_UPLOAD_DIR=env.get('MOZ_UPLOAD_DIR', '/tmp'),
--        old = env.get('JITTEST_EXTRA_ARGS', ''))
--
- # Always run all enabled tests, even if earlier ones failed. But return the
- # first failed status.
- results = []
- 
- if 'checks' in test_suites:
-     results.append(run_test_command([MAKE, 'check']))
- 
- if 'jittest' in test_suites:

+ 0 - 84
frg/work-js/mozilla-release/patches/mozilla-central-push_423356.patch

@@ -1,84 +0,0 @@
-# HG changeset patch
-# User Jeff Walden <jwalden@mit.edu>
-# Date 1529348150 25200
-#      Mon Jun 18 11:55:50 2018 -0700
-# Node ID efab409f73352a925744a2c9be5a61e741788b0d
-# Parent  04563090db37e5a627c05219cf0ddfd1d65bb25c
-Bug 1468877 - Remove TokenStreamShared::ntokens as being duplicative in meaning of TokenStreamShared::maxLookahead.  r=jorendorff
-
-diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h
---- a/js/src/frontend/TokenStream.h
-+++ b/js/src/frontend/TokenStream.h
-@@ -445,25 +445,21 @@ class TokenStreamPosition;
- 
- /**
-  * TokenStream types and constants that are used in both TokenStreamAnyChars
-  * and TokenStreamSpecific.  Do not add any non-static data members to this
-  * class!
-  */
- class TokenStreamShared
- {
--  protected:
--    static constexpr size_t ntokens = 4; // 1 current + 2 lookahead, rounded
--                                         // to power of 2 to avoid divmod by 3
--
--    static constexpr unsigned ntokensMask = ntokens - 1;
--
--    template<typename CharT> friend class TokenStreamPosition;
--
-   public:
-+    /**
-+     * Max lookahead accommodates one gotten token and one peeked-ahead (ergo
-+     * temporarily gotten) token.
-+     */
-     static constexpr unsigned maxLookahead = 2;
- 
-     static constexpr uint32_t NoOffset = UINT32_MAX;
- 
-     using Modifier = Token::Modifier;
-     static constexpr Modifier None = Token::None;
-     static constexpr Modifier Operand = Token::Operand;
-     static constexpr Modifier TemplateTail = Token::TemplateTail;
-@@ -493,16 +489,23 @@ class TokenStreamShared
-                 return;
-         }
- 
-         MOZ_ASSERT_UNREACHABLE("this token was previously looked up with a "
-                                "different modifier, potentially making "
-                                "tokenization non-deterministic");
- #endif
-     }
-+
-+  protected:
-+    static_assert(mozilla::IsPowerOfTwo(maxLookahead),
-+                  "maxLookahead must be a power of two to mask this way");
-+    static constexpr unsigned ntokensMask = maxLookahead - 1;
-+
-+    template<typename CharT> friend class TokenStreamPosition;
- };
- 
- static_assert(mozilla::IsEmpty<TokenStreamShared>::value,
-               "TokenStreamShared shouldn't bloat classes that inherit from it");
- 
- template<typename CharT, class AnyCharsAccess>
- class TokenStreamSpecific;
- 
-@@ -840,17 +843,17 @@ class TokenStreamAnyChars
-     const char* getFilename() const {
-         return filename_;
-     }
- 
-   protected:
-     // Options used for parsing/tokenizing.
-     const ReadOnlyCompileOptions& options_;
- 
--    Token               tokens[ntokens];    // circular token buffer
-+    Token               tokens[maxLookahead]; // circular token buffer
-   private:
-     unsigned            cursor_;            // index of last parsed token
-   protected:
-     unsigned            lookahead;          // count of lookahead tokens
-     unsigned            lineno;             // current line number
-     TokenStreamFlags    flags;              // flags -- see above
-     size_t              linebase;           // start of current line
-     size_t              prevLinebase;       // start of previous line;  size_t(-1) if on the first line

+ 0 - 84
frg/work-js/mozilla-release/patches/mozilla-central-push_423358.patch

@@ -1,84 +0,0 @@
-# HG changeset patch
-# User Jeff Walden <jwalden@mit.edu>
-# Date 1529648599 25200
-#      Thu Jun 21 23:23:19 2018 -0700
-# Node ID 6e75896cb76c94fa2e8d89d7a7a1ed0237575f52
-# Parent  ca13bbbbb8c53dfc84f31dcddac8342fbbc09264
-Backed out changeset efab409f7335.  r=bustage in a CLOSED TREE
-
-diff --git a/js/src/frontend/TokenStream.h b/js/src/frontend/TokenStream.h
---- a/js/src/frontend/TokenStream.h
-+++ b/js/src/frontend/TokenStream.h
-@@ -445,21 +445,25 @@ class TokenStreamPosition;
- 
- /**
-  * TokenStream types and constants that are used in both TokenStreamAnyChars
-  * and TokenStreamSpecific.  Do not add any non-static data members to this
-  * class!
-  */
- class TokenStreamShared
- {
-+  protected:
-+    static constexpr size_t ntokens = 4; // 1 current + 2 lookahead, rounded
-+                                         // to power of 2 to avoid divmod by 3
-+
-+    static constexpr unsigned ntokensMask = ntokens - 1;
-+
-+    template<typename CharT> friend class TokenStreamPosition;
-+
-   public:
--    /**
--     * Max lookahead accommodates one gotten token and one peeked-ahead (ergo
--     * temporarily gotten) token.
--     */
-     static constexpr unsigned maxLookahead = 2;
- 
-     static constexpr uint32_t NoOffset = UINT32_MAX;
- 
-     using Modifier = Token::Modifier;
-     static constexpr Modifier None = Token::None;
-     static constexpr Modifier Operand = Token::Operand;
-     static constexpr Modifier TemplateTail = Token::TemplateTail;
-@@ -489,23 +493,16 @@ class TokenStreamShared
-                 return;
-         }
- 
-         MOZ_ASSERT_UNREACHABLE("this token was previously looked up with a "
-                                "different modifier, potentially making "
-                                "tokenization non-deterministic");
- #endif
-     }
--
--  protected:
--    static_assert(mozilla::IsPowerOfTwo(maxLookahead),
--                  "maxLookahead must be a power of two to mask this way");
--    static constexpr unsigned ntokensMask = maxLookahead - 1;
--
--    template<typename CharT> friend class TokenStreamPosition;
- };
- 
- static_assert(mozilla::IsEmpty<TokenStreamShared>::value,
-               "TokenStreamShared shouldn't bloat classes that inherit from it");
- 
- template<typename CharT, class AnyCharsAccess>
- class TokenStreamSpecific;
- 
-@@ -843,17 +840,17 @@ class TokenStreamAnyChars
-     const char* getFilename() const {
-         return filename_;
-     }
- 
-   protected:
-     // Options used for parsing/tokenizing.
-     const ReadOnlyCompileOptions& options_;
- 
--    Token               tokens[maxLookahead]; // circular token buffer
-+    Token               tokens[ntokens];    // circular token buffer
-   private:
-     unsigned            cursor_;            // index of last parsed token
-   protected:
-     unsigned            lookahead;          // count of lookahead tokens
-     unsigned            lineno;             // current line number
-     TokenStreamFlags    flags;              // flags -- see above
-     size_t              linebase;           // start of current line
-     size_t              prevLinebase;       // start of previous line;  size_t(-1) if on the first line

+ 0 - 1293
frg/work-js/mozilla-release/patches/mozilla-central_419570.patch

@@ -1,1293 +0,0 @@
-# HG changeset patch
-# User Jon Coppeard <jcoppeard@mozilla.com>
-# Date 1527061648 -3600
-#      Wed May 23 08:47:28 2018 +0100
-# Node ID 277bd9cf9edc37653b8931349b1c9a232987fd57
-# Parent  66f6b8d84e5d35d0de8d07d3e9de44a9cce913f2
-Bug 1427610 - Implement import.meta in the JS frontent r=jorendorff
-
-diff --git a/js/src/builtin/ReflectParse.cpp b/js/src/builtin/ReflectParse.cpp
---- a/js/src/builtin/ReflectParse.cpp
-+++ b/js/src/builtin/ReflectParse.cpp
-@@ -28,22 +28,16 @@
- 
- using namespace js;
- using namespace js::frontend;
- 
- using JS::AutoValueArray;
- using mozilla::DebugOnly;
- using mozilla::Forward;
- 
--enum class ParseTarget
--{
--    Script,
--    Module
--};
--
- enum ASTType {
-     AST_ERROR = -1,
- #define ASTDEF(ast, str, method) ast,
- #include "jsast.tbl"
- #undef ASTDEF
-     AST_LIMIT
- };
- 
-@@ -2923,31 +2917,40 @@ ASTSerializer::expression(ParseNode* pn,
-         return optExpression(pn->pn_kid, &arg) &&
-                builder.yieldExpression(arg, NotDelegating, &pn->pn_pos, dst);
-       }
- 
-       case ParseNodeKind::Class:
-         return classDefinition(pn, true, dst);
- 
-       case ParseNodeKind::NewTarget:
-+      case ParseNodeKind::ImportMeta:
-       {
-         MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PosHolder));
-         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_left->pn_pos));
-         MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PosHolder));
-         MOZ_ASSERT(pn->pn_pos.encloses(pn->pn_right->pn_pos));
- 
--        RootedValue newIdent(cx);
--        RootedValue targetIdent(cx);
--
--        RootedAtom newStr(cx, cx->names().new_);
--        RootedAtom targetStr(cx, cx->names().target);
--
--        return identifier(newStr, &pn->pn_left->pn_pos, &newIdent) &&
--               identifier(targetStr, &pn->pn_right->pn_pos, &targetIdent) &&
--               builder.metaProperty(newIdent, targetIdent, &pn->pn_pos, dst);
-+        RootedValue firstIdent(cx);
-+        RootedValue secondIdent(cx);
-+
-+        RootedAtom firstStr(cx);
-+        RootedAtom secondStr(cx);
-+
-+        if (pn->getKind() == ParseNodeKind::NewTarget) {
-+            firstStr = cx->names().new_;
-+            secondStr = cx->names().target;
-+        } else {
-+            firstStr = cx->names().import;
-+            secondStr = cx->names().meta;
-+        }
-+
-+        return identifier(firstStr, &pn->pn_left->pn_pos, &firstIdent) &&
-+               identifier(secondStr, &pn->pn_right->pn_pos, &secondIdent) &&
-+               builder.metaProperty(firstIdent, secondIdent, &pn->pn_pos, dst);
-       }
- 
-       case ParseNodeKind::SetThis:
-         // SETTHIS is used to assign the result of a super() call to |this|.
-         // It's not part of the original AST, so just forward to the call.
-         MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::Name));
-         return expression(pn->pn_right, dst);
- 
-@@ -3349,17 +3352,17 @@ reflect_parse(JSContext* cx, uint32_t ar
-     RootedString src(cx, ToString<CanGC>(cx, args[0]));
-     if (!src)
-         return false;
- 
-     ScopedJSFreePtr<char> filename;
-     uint32_t lineno = 1;
-     bool loc = true;
-     RootedObject builder(cx);
--    ParseTarget target = ParseTarget::Script;
-+    ParseGoal target = ParseGoal::Script;
- 
-     RootedValue arg(cx, args.get(1));
- 
-     if (!arg.isNullOrUndefined()) {
-         if (!arg.isObject()) {
-             ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE,
-                                   JSDVG_SEARCH_STACK, arg, nullptr,
-                                   "not an object", nullptr);
-@@ -3437,19 +3440,19 @@ reflect_parse(JSContext* cx, uint32_t ar
-         bool isModule = false;
-         if (!EqualStrings(cx, stringProp, cx->names().script, &isScript))
-             return false;
- 
-         if (!EqualStrings(cx, stringProp, cx->names().module, &isModule))
-             return false;
- 
-         if (isScript) {
--            target = ParseTarget::Script;
-+            target = ParseGoal::Script;
-         } else if (isModule) {
--            target = ParseTarget::Module;
-+            target = ParseGoal::Module;
-         } else {
-             JS_ReportErrorASCII(cx, "Bad target value, expected 'script' or 'module'");
-             return false;
-         }
-     }
- 
-     /* Extract the builder methods first to report errors before parsing. */
-     ASTSerializer serialize(cx, loc, filename, lineno);
-@@ -3462,38 +3465,38 @@ reflect_parse(JSContext* cx, uint32_t ar
- 
-     AutoStableStringChars linearChars(cx);
-     if (!linearChars.initTwoByte(cx, linear))
-         return false;
- 
-     CompileOptions options(cx);
-     options.setFileAndLine(filename, lineno);
-     options.setCanLazilyParse(false);
--    options.allowHTMLComments = target == ParseTarget::Script;
-+    options.allowHTMLComments = target == ParseGoal::Script;
-     mozilla::Range<const char16_t> chars = linearChars.twoByteRange();
-     UsedNameTracker usedNames(cx);
-     if (!usedNames.init())
-         return false;
- 
-     RootedScriptSourceObject sourceObject(cx, frontend::CreateScriptSourceObject(cx, options,
-                                                                                  mozilla::Nothing()));
-     if (!sourceObject)
-         return false;
- 
-     Parser<FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options,
-                                               chars.begin().get(), chars.length(),
-                                               /* foldConstants = */ false, usedNames, nullptr,
--                                              nullptr, sourceObject);
-+                                              nullptr, sourceObject, target);
-     if (!parser.checkOptions())
-         return false;
- 
-     serialize.setParser(&parser);
- 
-     ParseNode* pn;
--    if (target == ParseTarget::Script) {
-+    if (target == ParseGoal::Script) {
-         pn = parser.parse();
-         if (!pn)
-             return false;
-     } else {
-         if (!GlobalObject::ensureModulePrototypesCreated(cx, cx->global()))
-             return false;
- 
-         Rooted<ModuleObject*> module(cx, ModuleObject::create(cx));
-diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp
---- a/js/src/frontend/BytecodeCompiler.cpp
-+++ b/js/src/frontend/BytecodeCompiler.cpp
-@@ -54,18 +54,19 @@ class MOZ_STACK_CLASS BytecodeCompiler
- 
-     ScriptSourceObject* sourceObjectPtr() const;
- 
-   private:
-     JSScript* compileScript(HandleObject environment, SharedContext* sc);
-     bool checkLength();
-     bool createScriptSource(const Maybe<uint32_t>& parameterListEnd);
-     bool canLazilyParse();
--    bool createParser();
--    bool createSourceAndParser(const Maybe<uint32_t>& parameterListEnd = Nothing());
-+    bool createParser(ParseGoal goal);
-+    bool createSourceAndParser(ParseGoal goal,
-+                               const Maybe<uint32_t>& parameterListEnd = Nothing());
- 
-     // If toString{Start,End} are not explicitly passed, assume the script's
-     // offsets in the source used to parse it are the same as what should be
-     // used to compute its Function.prototype.toString() value.
-     bool createScript();
-     bool createScript(uint32_t toStringStart, uint32_t toStringEnd);
- 
-     using TokenStreamPosition = frontend::TokenStreamPosition<char16_t>;
-@@ -210,42 +211,43 @@ BytecodeCompiler::canLazilyParse()
-     return options.canLazilyParse &&
-            !cx->realm()->behaviors().disableLazyParsing() &&
-            !cx->realm()->behaviors().discardSource() &&
-            !options.sourceIsLazy &&
-            !cx->lcovEnabled();
- }
- 
- bool
--BytecodeCompiler::createParser()
-+BytecodeCompiler::createParser(ParseGoal goal)
- {
-     usedNames.emplace(cx);
-     if (!usedNames->init())
-         return false;
- 
-     if (canLazilyParse()) {
-         syntaxParser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
-                              /* foldConstants = */ false, *usedNames, nullptr, nullptr,
--                             sourceObject);
-+                             sourceObject, goal);
-         if (!syntaxParser->checkOptions())
-             return false;
-     }
- 
-     parser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
-                    /* foldConstants = */ true, *usedNames, syntaxParser.ptrOr(nullptr), nullptr,
--                   sourceObject);
-+                   sourceObject, goal);
-     parser->ss = scriptSource;
-     return parser->checkOptions();
- }
- 
- bool
--BytecodeCompiler::createSourceAndParser(const Maybe<uint32_t>& parameterListEnd /* = Nothing() */)
-+BytecodeCompiler::createSourceAndParser(ParseGoal goal,
-+                                        const Maybe<uint32_t>& parameterListEnd /* = Nothing() */)
- {
-     return createScriptSource(parameterListEnd) &&
--           createParser();
-+           createParser(goal);
- }
- 
- bool
- BytecodeCompiler::createScript()
- {
-     return createScript(0, sourceBuffer.length());
- }
- 
-@@ -309,17 +311,17 @@ BytecodeCompiler::deoptimizeArgumentsInE
-     }
- 
-     return true;
- }
- 
- JSScript*
- BytecodeCompiler::compileScript(HandleObject environment, SharedContext* sc)
- {
--    if (!createSourceAndParser())
-+    if (!createSourceAndParser(ParseGoal::Script))
-         return nullptr;
- 
-     TokenStreamPosition startPosition(keepAtoms, parser->tokenStream);
- 
-     if (!createScript())
-         return nullptr;
- 
-     Maybe<BytecodeEmitter> emitter;
-@@ -385,17 +387,17 @@ BytecodeCompiler::compileEvalScript(Hand
-     EvalSharedContext evalsc(cx, environment, enclosingScope,
-                              directives, options.extraWarningsOption);
-     return compileScript(environment, &evalsc);
- }
- 
- ModuleObject*
- BytecodeCompiler::compileModule()
- {
--    if (!createSourceAndParser())
-+    if (!createSourceAndParser(ParseGoal::Module))
-         return nullptr;
- 
-     Rooted<ModuleObject*> module(cx, ModuleObject::create(cx));
-     if (!module)
-         return nullptr;
- 
-     if (!createScript())
-         return nullptr;
-@@ -444,17 +446,17 @@ bool
- BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
-                                             GeneratorKind generatorKind,
-                                             FunctionAsyncKind asyncKind,
-                                             const Maybe<uint32_t>& parameterListEnd)
- {
-     MOZ_ASSERT(fun);
-     MOZ_ASSERT(fun->isTenured());
- 
--    if (!createSourceAndParser(parameterListEnd))
-+    if (!createSourceAndParser(ParseGoal::Script, parameterListEnd))
-         return false;
- 
-     TokenStreamPosition startPosition(keepAtoms, parser->tokenStream);
- 
-     // Speculatively parse using the default directives implied by the context.
-     // If a directive is encountered (e.g., "use strict") that changes how the
-     // function should have been parsed, we backup and reparse with the new set
-     // of directives.
-@@ -775,17 +777,17 @@ frontend::CompileLazyFunction(JSContext*
- 
-     UsedNameTracker usedNames(cx);
-     if (!usedNames.init())
-         return false;
- 
-     RootedScriptSourceObject sourceObject(cx, &lazy->sourceObject());
-     Parser<FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options, chars, length,
-                                               /* foldConstants = */ true, usedNames, nullptr,
--                                              lazy, sourceObject);
-+                                              lazy, sourceObject, lazy->parseGoal());
-     if (!parser.checkOptions())
-         return false;
- 
-     Rooted<JSFunction*> fun(cx, lazy->functionNonDelazifying());
-     ParseNode* pn = parser.standaloneLazyFunction(fun, lazy->toStringStart(),
-                                                   lazy->strict(), lazy->generatorKind(),
-                                                   lazy->asyncKind());
-     if (!pn)
-diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
---- a/js/src/frontend/BytecodeEmitter.cpp
-+++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -3298,16 +3298,17 @@ BytecodeEmitter::checkSideEffects(ParseN
-       // functions or eval.
-       case ParseNodeKind::This:
-         MOZ_ASSERT(pn->isArity(PN_UNARY));
-         *answer = sc->needsThisTDZChecks();
-         return true;
- 
-       // Trivial binary nodes with more token pos holders.
-       case ParseNodeKind::NewTarget:
-+      case ParseNodeKind::ImportMeta:
-         MOZ_ASSERT(pn->isArity(PN_BINARY));
-         MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PosHolder));
-         MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PosHolder));
-         *answer = false;
-         return true;
- 
-       case ParseNodeKind::Break:
-       case ParseNodeKind::Continue:
-@@ -11141,16 +11142,20 @@ BytecodeEmitter::emitTree(ParseNode* pn,
-             return false;
-         break;
- 
-       case ParseNodeKind::NewTarget:
-         if (!emit1(JSOP_NEWTARGET))
-             return false;
-         break;
- 
-+      case ParseNodeKind::ImportMeta:
-+        MOZ_CRASH("NYI");
-+        break;
-+
-       case ParseNodeKind::SetThis:
-         if (!emitSetThis(pn))
-             return false;
-         break;
- 
-       case ParseNodeKind::PosHolder:
-         MOZ_FALLTHROUGH_ASSERT("Should never try to emit ParseNodeKind::PosHolder");
- 
-diff --git a/js/src/frontend/FoldConstants.cpp b/js/src/frontend/FoldConstants.cpp
---- a/js/src/frontend/FoldConstants.cpp
-+++ b/js/src/frontend/FoldConstants.cpp
-@@ -370,16 +370,17 @@ ContainsHoistedDeclaration(JSContext* cx
-       case ParseNodeKind::Catch:
-       case ParseNodeKind::ForIn:
-       case ParseNodeKind::ForOf:
-       case ParseNodeKind::ForHead:
-       case ParseNodeKind::ClassMethod:
-       case ParseNodeKind::ClassMethodList:
-       case ParseNodeKind::ClassNames:
-       case ParseNodeKind::NewTarget:
-+      case ParseNodeKind::ImportMeta:
-       case ParseNodeKind::PosHolder:
-       case ParseNodeKind::SuperCall:
-       case ParseNodeKind::SuperBase:
-       case ParseNodeKind::SetThis:
-         MOZ_CRASH("ContainsHoistedDeclaration should have indicated false on "
-                   "some parent node without recurring to test this node");
- 
-       case ParseNodeKind::Pipeline:
-@@ -1720,16 +1721,17 @@ Fold(JSContext* cx, ParseNode** pnp, Per
-       case ParseNodeKind::ImportSpec:
-       case ParseNodeKind::ExportSpec:
-       case ParseNodeKind::SetThis:
-         MOZ_ASSERT(pn->isArity(PN_BINARY));
-         return Fold(cx, &pn->pn_left, parser) &&
-                Fold(cx, &pn->pn_right, parser);
- 
-       case ParseNodeKind::NewTarget:
-+      case ParseNodeKind::ImportMeta:
-         MOZ_ASSERT(pn->isArity(PN_BINARY));
-         MOZ_ASSERT(pn->pn_left->isKind(ParseNodeKind::PosHolder));
-         MOZ_ASSERT(pn->pn_right->isKind(ParseNodeKind::PosHolder));
-         return true;
- 
-       case ParseNodeKind::ClassNames:
-         MOZ_ASSERT(pn->isArity(PN_BINARY));
-         if (ParseNode*& outerBinding = pn->pn_left) {
-diff --git a/js/src/frontend/FullParseHandler.h b/js/src/frontend/FullParseHandler.h
---- a/js/src/frontend/FullParseHandler.h
-+++ b/js/src/frontend/FullParseHandler.h
-@@ -555,16 +555,20 @@ class FullParseHandler
-     ParseNode* newExportSpec(ParseNode* bindingName, ParseNode* exportName) {
-         return newBinary(ParseNodeKind::ExportSpec, bindingName, exportName);
-     }
- 
-     ParseNode* newExportBatchSpec(const TokenPos& pos) {
-         return new_<NullaryNode>(ParseNodeKind::ExportBatchSpec, JSOP_NOP, pos);
-     }
- 
-+    ParseNode* newImportMeta(ParseNode* importHolder, ParseNode* metaHolder) {
-+        return new_<BinaryNode>(ParseNodeKind::ImportMeta, JSOP_NOP, importHolder, metaHolder);
-+    }
-+
-     ParseNode* newExprStatement(ParseNode* expr, uint32_t end) {
-         MOZ_ASSERT(expr->pn_pos.end <= end);
-         return new_<UnaryNode>(ParseNodeKind::ExpressionStatement,
-                                TokenPos(expr->pn_pos.begin, end), expr);
-     }
- 
-     ParseNode* newIfStatement(uint32_t begin, ParseNode* cond, ParseNode* thenBranch,
-                               ParseNode* elseBranch)
-diff --git a/js/src/frontend/NameAnalysisTypes.h b/js/src/frontend/NameAnalysisTypes.h
---- a/js/src/frontend/NameAnalysisTypes.h
-+++ b/js/src/frontend/NameAnalysisTypes.h
-@@ -59,16 +59,22 @@ class EnvironmentCoordinate
- 
-     bool operator==(const EnvironmentCoordinate& rhs) const {
-         return hops() == rhs.hops() && slot() == rhs.slot();
-     }
- };
- 
- namespace frontend {
- 
-+enum class ParseGoal : uint8_t
-+{
-+    Script,
-+    Module
-+};
-+
- // A detailed kind used for tracking declarations in the Parser. Used for
- // specific early error semantics and better error messages.
- enum class DeclarationKind : uint8_t
- {
-     PositionalFormalParameter,
-     FormalParameter,
-     CoverArrowParameter,
-     Var,
-diff --git a/js/src/frontend/NameFunctions.cpp b/js/src/frontend/NameFunctions.cpp
---- a/js/src/frontend/NameFunctions.cpp
-+++ b/js/src/frontend/NameFunctions.cpp
-@@ -412,16 +412,17 @@ class NameResolver
-           case ParseNodeKind::TypeOfName:
-           case ParseNodeKind::SuperBase:
-             MOZ_ASSERT(cur->isArity(PN_UNARY));
-             MOZ_ASSERT(cur->pn_kid->isKind(ParseNodeKind::Name));
-             MOZ_ASSERT(!cur->pn_kid->expr());
-             break;
- 
-           case ParseNodeKind::NewTarget:
-+          case ParseNodeKind::ImportMeta:
-             MOZ_ASSERT(cur->isArity(PN_BINARY));
-             MOZ_ASSERT(cur->pn_left->isKind(ParseNodeKind::PosHolder));
-             MOZ_ASSERT(cur->pn_right->isKind(ParseNodeKind::PosHolder));
-             break;
- 
-           // Nodes with a single non-null child requiring name resolution.
-           case ParseNodeKind::ExpressionStatement:
-           case ParseNodeKind::TypeOfExpr:
-diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h
---- a/js/src/frontend/ParseNode.h
-+++ b/js/src/frontend/ParseNode.h
-@@ -127,16 +127,17 @@ class ObjectBox;
-     F(ClassMethod) \
-     F(ClassMethodList) \
-     F(ClassNames) \
-     F(NewTarget) \
-     F(PosHolder) \
-     F(SuperBase) \
-     F(SuperCall) \
-     F(SetThis) \
-+    F(ImportMeta) \
-     \
-     /* Unary operators. */ \
-     F(TypeOfName) \
-     F(TypeOfExpr) \
-     F(Void) \
-     F(Not) \
-     F(BitNot) \
-     F(Await) \
-diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp
---- a/js/src/frontend/Parser.cpp
-+++ b/js/src/frontend/Parser.cpp
-@@ -795,33 +795,35 @@ ParserBase::errorNoOffset(unsigned error
- 
-     va_end(args);
- }
- 
- ParserBase::ParserBase(JSContext* cx, LifoAlloc& alloc,
-                        const ReadOnlyCompileOptions& options,
-                        bool foldConstants,
-                        UsedNameTracker& usedNames,
--                       ScriptSourceObject* sourceObject)
-+                       ScriptSourceObject* sourceObject,
-+                       ParseGoal parseGoal)
-   : AutoGCRooter(cx, AutoGCRooter::Tag::Parser),
-     context(cx),
-     alloc(alloc),
-     anyChars(cx, options, thisForCtor()),
-     traceListHead(nullptr),
-     pc(nullptr),
-     usedNames(usedNames),
-     ss(nullptr),
-     sourceObject(cx, sourceObject),
-     keepAtoms(cx),
-     foldConstants(foldConstants),
- #ifdef DEBUG
-     checkOptionsCalled(false),
- #endif
-     isUnexpectedEOF_(false),
--    awaitHandling_(AwaitIsName)
-+    awaitHandling_(AwaitIsName),
-+    parseGoal_(uint8_t(parseGoal))
- {
-     cx->frontendCollectionPool().addActiveCompilation();
-     tempPoolMark = alloc.mark();
- }
- 
- bool
- ParserBase::checkOptions()
- {
-@@ -848,33 +850,35 @@ ParserBase::~ParserBase()
-     context->frontendCollectionPool().removeActiveCompilation();
- }
- 
- template <class ParseHandler>
- PerHandlerParser<ParseHandler>::PerHandlerParser(JSContext* cx, LifoAlloc& alloc,
-                                                  const ReadOnlyCompileOptions& options,
-                                                  bool foldConstants, UsedNameTracker& usedNames,
-                                                  LazyScript* lazyOuterFunction,
--                                                 ScriptSourceObject* sourceObject)
--  : ParserBase(cx, alloc, options, foldConstants, usedNames, sourceObject),
-+                                                 ScriptSourceObject* sourceObject,
-+                                                 ParseGoal parseGoal)
-+  : ParserBase(cx, alloc, options, foldConstants, usedNames, sourceObject, parseGoal),
-     handler(cx, alloc, lazyOuterFunction)
- {
- 
- }
- 
- template <class ParseHandler, typename CharT>
- GeneralParser<ParseHandler, CharT>::GeneralParser(JSContext* cx, LifoAlloc& alloc,
-                                                   const ReadOnlyCompileOptions& options,
-                                                   const CharT* chars, size_t length,
-                                                   bool foldConstants,
-                                                   UsedNameTracker& usedNames,
-                                                   SyntaxParser* syntaxParser,
-                                                   LazyScript* lazyOuterFunction,
--                                                  ScriptSourceObject* sourceObject)
--  : Base(cx, alloc, options, foldConstants, usedNames, lazyOuterFunction, sourceObject),
-+                                                  ScriptSourceObject* sourceObject,
-+                                                  ParseGoal parseGoal)
-+  : Base(cx, alloc, options, foldConstants, usedNames, lazyOuterFunction, sourceObject, parseGoal),
-     tokenStream(cx, options, chars, length)
- {
-     // The Mozilla specific JSOPTION_EXTRA_WARNINGS option adds extra warnings
-     // which are not generated if functions are parsed lazily. Note that the
-     // standard "use strict" does not inhibit lazy parsing.
-     if (options.extraWarningsOption)
-         disableSyntaxParser();
-     else
-@@ -2546,17 +2550,18 @@ PerHandlerParser<SyntaxParseHandler>::fi
- 
-     FunctionBox* funbox = pc->functionBox();
-     RootedFunction fun(context, funbox->function());
-     LazyScript* lazy = LazyScript::Create(context, fun, sourceObject,
-                                           pc->closedOverBindingsForLazy(),
-                                           pc->innerFunctionsForLazy,
-                                           funbox->bufStart, funbox->bufEnd,
-                                           funbox->toStringStart,
--                                          funbox->startLine, funbox->startColumn);
-+                                          funbox->startLine, funbox->startColumn,
-+                                          parseGoal());
-     if (!lazy)
-         return false;
- 
-     // Flags that need to be copied into the JSScript when we do the full
-     // parse.
-     if (pc->sc()->strict())
-         lazy->setStrict();
-     lazy->setGeneratorKind(funbox->generatorKind());
-@@ -5346,16 +5351,32 @@ Parser<SyntaxParseHandler, CharT>::impor
- 
- template <class ParseHandler, typename CharT>
- inline typename ParseHandler::Node
- GeneralParser<ParseHandler, CharT>::importDeclaration()
- {
-     return asFinalParser()->importDeclaration();
- }
- 
-+template <class ParseHandler, typename CharT>
-+inline typename ParseHandler::Node
-+GeneralParser<ParseHandler, CharT>::importDeclarationOrImportMeta(YieldHandling yieldHandling)
-+{
-+    MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import));
-+
-+    TokenKind tt;
-+    if (!tokenStream.peekToken(&tt))
-+        return null();
-+
-+    if (tt == TokenKind::Dot)
-+        return expressionStatement(yieldHandling);
-+
-+    return importDeclaration();
-+}
-+
- template<typename CharT>
- bool
- Parser<FullParseHandler, CharT>::checkExportedName(JSAtom* exportName)
- {
-     if (!pc->sc()->asModuleContext()->builder.hasExportedName(exportName))
-         return true;
- 
-     JSAutoByteString str;
-@@ -7694,17 +7715,17 @@ GeneralParser<ParseHandler, CharT>::stat
- 
-       // |class| is also forbidden by lookahead restriction.
-       case TokenKind::Class:
-         error(JSMSG_FORBIDDEN_AS_STATEMENT, "classes");
-         return null();
- 
-       // ImportDeclaration (only inside modules)
-       case TokenKind::Import:
--        return importDeclaration();
-+        return importDeclarationOrImportMeta(yieldHandling);
- 
-       // ExportDeclaration (only inside modules)
-       case TokenKind::Export:
-         return exportDeclaration();
- 
-       // Miscellaneous error cases arguably better caught here than elsewhere.
- 
-       case TokenKind::Catch:
-@@ -7887,17 +7908,17 @@ GeneralParser<ParseHandler, CharT>::stat
-       //     LetOrConst BindingList[?In, ?Yield]
-       case TokenKind::Const:
-         // [In] is the default behavior, because for-loops specially parse
-         // their heads to handle |in| in this situation.
-         return lexicalDeclaration(yieldHandling, DeclarationKind::Const);
- 
-       // ImportDeclaration (only inside modules)
-       case TokenKind::Import:
--        return importDeclaration();
-+        return importDeclarationOrImportMeta(yieldHandling);
- 
-       // ExportDeclaration (only inside modules)
-       case TokenKind::Export:
-         return exportDeclaration();
- 
-       // Miscellaneous error cases arguably better caught here than elsewhere.
- 
-       case TokenKind::Catch:
-@@ -8709,16 +8730,20 @@ GeneralParser<ParseHandler, CharT>::memb
-         }
-     } else if (tt == TokenKind::Super) {
-         Node thisName = newThisName();
-         if (!thisName)
-             return null();
-         lhs = handler.newSuperBase(thisName, pos());
-         if (!lhs)
-             return null();
-+    } else if (tt == TokenKind::Import) {
-+        lhs = importMeta();
-+        if (!lhs)
-+            return null();
-     } else {
-         lhs = primaryExpr(yieldHandling, tripledotHandling, tt, possibleError, invoked);
-         if (!lhs)
-             return null();
-     }
- 
-     MOZ_ASSERT_IF(handler.isSuperBase(lhs), anyChars.isCurrentTokenType(TokenKind::Super));
- 
-@@ -9887,16 +9912,55 @@ GeneralParser<ParseHandler, CharT>::tryN
-         return false;
- 
-     newTarget = handler.newNewTarget(newHolder, targetHolder);
-     return !!newTarget;
- }
- 
- template <class ParseHandler, typename CharT>
- typename ParseHandler::Node
-+GeneralParser<ParseHandler, CharT>::importMeta()
-+{
-+    MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Import));
-+
-+    uint32_t begin = pos().begin;
-+
-+    if (parseGoal() != ParseGoal::Module) {
-+        errorAt(begin, JSMSG_IMPORT_OUTSIDE_MODULE);
-+        return null();
-+    }
-+
-+    Node importHolder = handler.newPosHolder(pos());
-+    if (!importHolder)
-+        return null();
-+
-+    TokenKind next;
-+    if (!tokenStream.getToken(&next))
-+        return null();
-+    if (next != TokenKind::Dot) {
-+        error(JSMSG_UNEXPECTED_TOKEN, "dot", TokenKindToDesc(next));
-+        return null();
-+    }
-+
-+    if (!tokenStream.getToken(&next))
-+        return null();
-+    if (next != TokenKind::Meta) {
-+        error(JSMSG_UNEXPECTED_TOKEN, "meta", TokenKindToDesc(next));
-+        return null();
-+    }
-+
-+    Node metaHolder = handler.newPosHolder(pos());
-+    if (!metaHolder)
-+        return null();
-+
-+    return handler.newImportMeta(importHolder, metaHolder);
-+}
-+
-+template <class ParseHandler, typename CharT>
-+typename ParseHandler::Node
- GeneralParser<ParseHandler, CharT>::primaryExpr(YieldHandling yieldHandling,
-                                                 TripledotHandling tripledotHandling,
-                                                 TokenKind tt, PossibleError* possibleError,
-                                                 InvokedPrediction invoked /* = PredictUninvoked */)
- {
-     MOZ_ASSERT(anyChars.isCurrentTokenType(tt));
-     if (!CheckRecursionLimit(context))
-         return null();
-diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h
---- a/js/src/frontend/Parser.h
-+++ b/js/src/frontend/Parser.h
-@@ -290,26 +290,32 @@ class MOZ_STACK_CLASS ParserBase
-     bool checkOptionsCalled:1;
- #endif
- 
-     /* Unexpected end of input, i.e. Eof not at top-level. */
-     bool isUnexpectedEOF_:1;
- 
-     /* AwaitHandling */ uint8_t awaitHandling_:2;
- 
-+    /* ParseGoal */ uint8_t parseGoal_:1;
-+
-   public:
-     bool awaitIsKeyword() const {
-       return awaitHandling_ != AwaitIsName;
-     }
- 
-+    ParseGoal parseGoal() const {
-+        return ParseGoal(parseGoal_);
-+    }
-+
-     template<class, typename> friend class AutoAwaitIsKeyword;
- 
-     ParserBase(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
-                bool foldConstants, UsedNameTracker& usedNames,
--               ScriptSourceObject* sourceObject);
-+               ScriptSourceObject* sourceObject, ParseGoal parseGoal);
-     ~ParserBase();
- 
-     bool checkOptions();
- 
-     void trace(JSTracer* trc);
- 
-     const char* getFilename() const { return anyChars.getFilename(); }
-     TokenPos pos() const { return anyChars.currentToken().pos; }
-@@ -464,17 +470,18 @@ class MOZ_STACK_CLASS PerHandlerParser
-     // |GeneralParser<ParseHandler, CharT>| that impose the real type on this
-     // field.
-     void* internalSyntaxParser_;
- 
-   protected:
-     PerHandlerParser(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
-                      bool foldConstants, UsedNameTracker& usedNames,
-                      LazyScript* lazyOuterFunction,
--                     ScriptSourceObject* sourceObject);
-+                     ScriptSourceObject* sourceObject,
-+                     ParseGoal parseGoal);
- 
-     static Node null() { return ParseHandler::null(); }
- 
-     Node stringLiteral();
- 
-     const char* nameIsArgumentsOrEval(Node node);
- 
-     bool noteDestructuredPositionalFormalParameter(Node fn, Node destruct);
-@@ -657,16 +664,17 @@ class MOZ_STACK_CLASS GeneralParser
-     using Modifier = TokenStreamShared::Modifier;
-     using Position = typename TokenStream::Position;
- 
-     using Base::PredictUninvoked;
-     using Base::PredictInvoked;
- 
-     using Base::alloc;
-     using Base::awaitIsKeyword;
-+    using Base::parseGoal;
- #if DEBUG
-     using Base::checkOptionsCalled;
- #endif
-     using Base::finishFunctionScopes;
-     using Base::finishLexicalScope;
-     using Base::foldConstants;
-     using Base::getFilename;
-     using Base::hasUsedFunctionSpecialName;
-@@ -867,17 +875,18 @@ class MOZ_STACK_CLASS GeneralParser
-   public:
-     TokenStream tokenStream;
- 
-   public:
-     GeneralParser(JSContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
-                   const CharT* chars, size_t length, bool foldConstants,
-                   UsedNameTracker& usedNames, SyntaxParser* syntaxParser,
-                   LazyScript* lazyOuterFunction,
--                  ScriptSourceObject* sourceObject);
-+                  ScriptSourceObject* sourceObject,
-+                  ParseGoal parseGoal);
- 
-     inline void setAwaitHandling(AwaitHandling awaitHandling);
- 
-     /*
-      * Parse a top-level JS script.
-      */
-     Node parse();
- 
-@@ -1008,16 +1017,17 @@ class MOZ_STACK_CLASS GeneralParser
-     Node labeledItem(YieldHandling yieldHandling);
- 
-     Node ifStatement(YieldHandling yieldHandling);
-     Node consequentOrAlternative(YieldHandling yieldHandling);
- 
-     Node lexicalDeclaration(YieldHandling yieldHandling, DeclarationKind kind);
- 
-     inline Node importDeclaration();
-+    Node importDeclarationOrImportMeta(YieldHandling yieldHandling);
- 
-     Node exportFrom(uint32_t begin, Node specList);
-     Node exportBatch(uint32_t begin);
-     inline bool checkLocalExportNames(Node node);
-     Node exportClause(uint32_t begin);
-     Node exportFunctionDeclaration(uint32_t begin, uint32_t toStringStart,
-                                    FunctionAsyncKind asyncKind = FunctionAsyncKind::SyncFunction);
-     Node exportVariableStatement(uint32_t begin);
-@@ -1107,16 +1117,18 @@ class MOZ_STACK_CLASS GeneralParser
-     Node primaryExpr(YieldHandling yieldHandling, TripledotHandling tripledotHandling,
-                      TokenKind tt, PossibleError* possibleError,
-                      InvokedPrediction invoked = PredictUninvoked);
-     Node exprInParens(InHandling inHandling, YieldHandling yieldHandling,
-                       TripledotHandling tripledotHandling, PossibleError* possibleError = nullptr);
- 
-     bool tryNewTarget(Node& newTarget);
- 
-+    Node importMeta();
-+
-     Node methodDefinition(uint32_t toStringStart, PropertyType propType, HandleAtom funName);
- 
-     /*
-      * Additional JS parsers.
-      */
-     bool functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind,
-                            Node funcpn);
- 
-diff --git a/js/src/frontend/ReservedWords.h b/js/src/frontend/ReservedWords.h
---- a/js/src/frontend/ReservedWords.h
-+++ b/js/src/frontend/ReservedWords.h
-@@ -61,16 +61,17 @@
-     \
-     /* Contextual keywords. */ \
-     macro(as, as, TokenKind::As) \
-     macro(async, async, TokenKind::Async) \
-     macro(await, await, TokenKind::Await) \
-     macro(from, from, TokenKind::From) \
-     macro(get, get, TokenKind::Get) \
-     macro(let, let, TokenKind::Let) \
-+    macro(meta, meta, TokenKind::Meta) \
-     macro(of, of, TokenKind::Of) \
-     macro(set, set, TokenKind::Set) \
-     macro(static, static_, TokenKind::Static) \
-     macro(target, target, TokenKind::Target) \
-     /* \
-      * Yield is a token inside function*.  Outside of a function*, it is a \
-      * future reserved word in strict mode, but a keyword in JS1.7 even \
-      * when strict.  Punt logic to parser. \
-diff --git a/js/src/frontend/SyntaxParseHandler.h b/js/src/frontend/SyntaxParseHandler.h
---- a/js/src/frontend/SyntaxParseHandler.h
-+++ b/js/src/frontend/SyntaxParseHandler.h
-@@ -292,16 +292,19 @@ class SyntaxParseHandler
-         return NodeGeneric;
-     }
-     Node newExportSpec(Node bindingName, Node exportName) {
-         return NodeGeneric;
-     }
-     Node newExportBatchSpec(const TokenPos& pos) {
-         return NodeGeneric;
-     }
-+    Node newImportMeta(Node importHolder, Node metaHolder) {
-+        return NodeGeneric;
-+    }
- 
-     Node newSetThis(Node thisName, Node value) { return value; }
- 
-     Node newExprStatement(Node expr, uint32_t end) {
-         return expr == NodeUnparenthesizedString ? NodeStringExprStatement : NodeGeneric;
-     }
- 
-     Node newIfStatement(uint32_t begin, Node cond, Node then, Node else_) { return NodeGeneric; }
-diff --git a/js/src/frontend/TokenKind.h b/js/src/frontend/TokenKind.h
---- a/js/src/frontend/TokenKind.h
-+++ b/js/src/frontend/TokenKind.h
-@@ -122,16 +122,17 @@
-     macro(As,           "'as'") \
-     range(ContextualKeywordFirst, As) \
-     macro(Async,        "'async'") \
-     macro(Await,        "'await'") \
-     macro(Each,         "'each'") \
-     macro(From,         "'from'") \
-     macro(Get,          "'get'") \
-     macro(Let,          "'let'") \
-+    macro(Meta,         "'meta'") \
-     macro(Of,           "'of'") \
-     macro(Set,          "'set'") \
-     macro(Static,       "'static'") \
-     macro(Target,       "'target'") \
-     macro(Yield,        "'yield'") \
-     range(ContextualKeywordLast, Yield) \
-     \
-     /* future reserved words */ \
-diff --git a/js/src/jit-test/tests/modules/import-meta-expression.js b/js/src/jit-test/tests/modules/import-meta-expression.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit-test/tests/modules/import-meta-expression.js
-@@ -0,0 +1,97 @@
-+load(libdir + "match.js");
-+load(libdir + "asserts.js");
-+
-+var { Pattern, MatchError } = Match;
-+
-+program = (elts) => Pattern({
-+    type: "Program",
-+    body: elts
-+});
-+expressionStatement = (expression) => Pattern({
-+    type: "ExpressionStatement",
-+    expression: expression
-+});
-+assignmentExpression = (left, operator, right) => Pattern({
-+    type: "AssignmentExpression",
-+    operator: operator,
-+    left: left,
-+    right: right
-+});
-+ident = (name) => Pattern({
-+    type: "Identifier",
-+    name: name
-+});
-+metaProperty = (meta, property) => Pattern({
-+    type: "MetaProperty",
-+    meta: meta,
-+    property: property
-+});
-+memberExpression = (object, property) => Pattern({
-+    type: "MemberExpression",
-+    object: object,
-+    property: property
-+});
-+
-+function parseAsModule(source)
-+{
-+    return Reflect.parse(source, {target: "module"});
-+}
-+
-+program([
-+    expressionStatement(
-+        metaProperty(
-+            ident("import"),
-+            ident("meta")
-+        )
-+    )
-+]).assert(parseAsModule("import.meta;"));
-+
-+program([
-+    expressionStatement(
-+        assignmentExpression(
-+            ident("x"),
-+            "=",
-+            metaProperty(
-+                ident("import"),
-+                ident("meta")
-+            )
-+        )
-+    )
-+]).assert(parseAsModule("x = import.meta;"));
-+
-+program([
-+    expressionStatement(
-+        assignmentExpression(
-+            memberExpression(
-+                metaProperty(
-+                    ident("import"),
-+                    ident("meta")
-+                ),
-+                ident("foo")
-+            ),
-+            "=",
-+            ident("x"),
-+        )
-+    )
-+]).assert(parseAsModule("import.meta.foo = x;"));
-+
-+function assertModuleParseThrowsSyntaxError(source)
-+{
-+    assertThrowsInstanceOf(() => parseAsModule(source), SyntaxError);
-+}
-+
-+function assertModuleParseThrowsReferenceError(source)
-+{
-+    assertThrowsInstanceOf(() => parseAsModule(source), ReferenceError);
-+}
-+
-+assertModuleParseThrowsSyntaxError("import");
-+assertModuleParseThrowsSyntaxError("import.");
-+assertModuleParseThrowsSyntaxError("import.met");
-+assertModuleParseThrowsSyntaxError("import.metaa");
-+assertModuleParseThrowsSyntaxError("x = import");
-+assertModuleParseThrowsSyntaxError("x = import.");
-+assertModuleParseThrowsSyntaxError("x = import.met");
-+assertModuleParseThrowsSyntaxError("x = import.metaa");
-+
-+assertModuleParseThrowsReferenceError("import.meta = x");
-diff --git a/js/src/js.msg b/js/src/js.msg
---- a/js/src/js.msg
-+++ b/js/src/js.msg
-@@ -256,16 +256,17 @@ MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY,     0
- MSG_DEF(JSMSG_FORBIDDEN_AS_STATEMENT,  1, JSEXN_SYNTAXERR, "{0} can't appear in single-statement context")
- MSG_DEF(JSMSG_FOR_AWAIT_OUTSIDE_ASYNC, 0, JSEXN_SYNTAXERR, "for await (... of ...) is only valid in async functions and async generators")
- MSG_DEF(JSMSG_FROM_AFTER_IMPORT_CLAUSE, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after import clause")
- MSG_DEF(JSMSG_FROM_AFTER_EXPORT_STAR,  0, JSEXN_SYNTAXERR, "missing keyword 'from' after export *")
- MSG_DEF(JSMSG_GARBAGE_AFTER_INPUT,     2, JSEXN_SYNTAXERR, "unexpected garbage after {0}, starting with {1}")
- MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER,    0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal")
- MSG_DEF(JSMSG_BAD_ESCAPE,              0, JSEXN_SYNTAXERR, "invalid escape sequence")
- MSG_DEF(JSMSG_ILLEGAL_CHARACTER,       0, JSEXN_SYNTAXERR, "illegal character")
-+MSG_DEF(JSMSG_IMPORT_OUTSIDE_MODULE,   0, JSEXN_SYNTAXERR, "the import keyword may only appear in a module")
- MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level of a module")
- MSG_DEF(JSMSG_OF_AFTER_FOR_LOOP_DECL,  0, JSEXN_SYNTAXERR, "a declaration in the head of a for-of loop can't have an initializer")
- MSG_DEF(JSMSG_IN_AFTER_LEXICAL_FOR_DECL,0,JSEXN_SYNTAXERR, "a lexical declaration in the head of a for-in loop can't have an initializer")
- MSG_DEF(JSMSG_INVALID_FOR_IN_DECL_WITH_INIT,0,JSEXN_SYNTAXERR,"for-in loop head declarations may not have initializers")
- MSG_DEF(JSMSG_INVALID_ID,              1, JSEXN_SYNTAXERR, "{0} is an invalid identifier")
- MSG_DEF(JSMSG_LABEL_NOT_FOUND,         0, JSEXN_SYNTAXERR, "label not found")
- MSG_DEF(JSMSG_LEXICAL_DECL_NOT_IN_BLOCK,   1, JSEXN_SYNTAXERR, "{0} declaration not directly within block")
- MSG_DEF(JSMSG_LEXICAL_DECL_LABEL,      1, JSEXN_SYNTAXERR, "{0} declarations cannot be labelled")
-diff --git a/js/src/jsapi-tests/testBinASTReader.cpp b/js/src/jsapi-tests/testBinASTReader.cpp
---- a/js/src/jsapi-tests/testBinASTReader.cpp
-+++ b/js/src/jsapi-tests/testBinASTReader.cpp
-@@ -172,17 +172,17 @@ runTestFromPath(JSContext* cx, const cha
-         RootedScriptSourceObject sourceObject(cx, frontend::CreateScriptSourceObject(
-                                                   cx, txtOptions, mozilla::Nothing()));
-         if (!sourceObject)
-             MOZ_CRASH("Couldn't initialize ScriptSourceObject");
- 
-         js::frontend::Parser<js::frontend::FullParseHandler, char16_t> txtParser(
-             cx, allocScope.alloc(), txtOptions, txtSource.begin(), txtSource.length(),
-             /* foldConstants = */ false, txtUsedNames, nullptr,
--            nullptr, sourceObject);
-+            nullptr, sourceObject, frontend::ParseGoal::Script);
-         if (!txtParser.checkOptions())
-             MOZ_CRASH("Bad options");
- 
-         auto txtParsed = txtParser.parse(); // Will be deallocated once `parser` goes out of scope.
-         RootedValue txtExn(cx);
-         if (!txtParsed) {
-             // Save exception for more detailed error message, if necessary.
-             if (!js::GetAndClearException(cx, &txtExn))
-diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
---- a/js/src/jsapi.cpp
-+++ b/js/src/jsapi.cpp
-@@ -4474,17 +4474,18 @@ JS_BufferIsCompilableUnit(JSContext* cx,
-                                                                                  mozilla::Nothing()));
-     if (!sourceObject)
-         return false;
- 
-     frontend::Parser<frontend::FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(),
-                                                                   options, chars, length,
-                                                                   /* foldConstants = */ true,
-                                                                   usedNames, nullptr, nullptr,
--                                                                  sourceObject);
-+                                                                  sourceObject,
-+                                                                  frontend::ParseGoal::Script);
-     JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
-     if (!parser.checkOptions() || !parser.parse()) {
-         // We ran into an error. If it was because we ran out of source, we
-         // return false so our caller knows to try to collect more buffered
-         // source.
-         if (parser.isUnexpectedEOF())
-             result = false;
- 
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -4513,17 +4513,17 @@ Parse(JSContext* cx, unsigned argc, Valu
- 
-     RootedScriptSourceObject sourceObject(cx, frontend::CreateScriptSourceObject(cx, options,
-                                                                                  Nothing()));
-     if (!sourceObject)
-         return false;
- 
-     Parser<FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options, chars, length,
-                                               /* foldConstants = */ false, usedNames, nullptr,
--                                              nullptr, sourceObject);
-+                                              nullptr, sourceObject, ParseGoal::Script);
-     if (!parser.checkOptions())
-         return false;
- 
-     ParseNode* pn = parser.parse(); // Deallocated once `parser` goes out of scope.
-     if (!pn)
-         return false;
- #ifdef DEBUG
-     js::Fprinter out(stderr);
-@@ -4571,17 +4571,18 @@ SyntaxParse(JSContext* cx, unsigned argc
-     RootedScriptSourceObject sourceObject(cx, frontend::CreateScriptSourceObject(cx, options,
-                                                                                  Nothing()));
-     if (!sourceObject)
-         return false;
- 
-     Parser<frontend::SyntaxParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(),
-                                                           options, chars, length, false,
-                                                           usedNames, nullptr, nullptr,
--                                                          sourceObject);
-+                                                          sourceObject,
-+                                                          frontend::ParseGoal::Script);
-     if (!parser.checkOptions())
-         return false;
- 
-     bool succeeded = parser.parse();
-     if (cx->isExceptionPending())
-         return false;
- 
-     if (!succeeded && !parser.hadAbortedSyntaxParse()) {
-diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
---- a/js/src/vm/CommonPropertyNames.h
-+++ b/js/src/vm/CommonPropertyNames.h
-@@ -225,16 +225,17 @@
-     macro(lookupGetter, lookupGetter, "__lookupGetter__") \
-     macro(lookupSetter, lookupSetter, "__lookupSetter__") \
-     macro(ltr, ltr, "ltr") \
-     macro(MapConstructorInit, MapConstructorInit, "MapConstructorInit") \
-     macro(MapIterator, MapIterator, "Map Iterator") \
-     macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \
-     macro(maximumSignificantDigits, maximumSignificantDigits, "maximumSignificantDigits") \
-     macro(message, message, "message") \
-+    macro(meta, meta, "meta") \
-     macro(minDays, minDays, "minDays") \
-     macro(minimumFractionDigits, minimumFractionDigits, "minimumFractionDigits") \
-     macro(minimumIntegerDigits, minimumIntegerDigits, "minimumIntegerDigits") \
-     macro(minimumSignificantDigits, minimumSignificantDigits, "minimumSignificantDigits") \
-     macro(minusSign, minusSign, "minusSign") \
-     macro(minute, minute, "minute") \
-     macro(missingArguments, missingArguments, "missingArguments") \
-     macro(mode, mode, "mode") \
-diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp
---- a/js/src/vm/Debugger.cpp
-+++ b/js/src/vm/Debugger.cpp
-@@ -5056,17 +5056,18 @@ Debugger::isCompilableUnit(JSContext* cx
-     if (!sourceObject)
-         return false;
- 
-     frontend::Parser<frontend::FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(),
-                                                                   options, chars.twoByteChars(),
-                                                                   length,
-                                                                   /* foldConstants = */ true,
-                                                                   usedNames, nullptr, nullptr,
--                                                                  sourceObject);
-+                                                                  sourceObject,
-+                                                                  frontend::ParseGoal::Script);
-     JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
-     if (!parser.checkOptions() || !parser.parse()) {
-         // We ran into an error. If it was because we ran out of memory we report
-         // it in the usual way.
-         if (cx->isThrowingOutOfMemory()) {
-             JS::SetWarningReporter(cx, older);
-             return false;
-         }
-diff --git a/js/src/vm/JSScript.cpp b/js/src/vm/JSScript.cpp
---- a/js/src/vm/JSScript.cpp
-+++ b/js/src/vm/JSScript.cpp
-@@ -4297,17 +4297,18 @@ LazyScript::CreateRaw(JSContext* cx, Han
- }
- 
- /* static */ LazyScript*
- LazyScript::Create(JSContext* cx, HandleFunction fun,
-                    HandleScriptSourceObject sourceObject,
-                    const frontend::AtomVector& closedOverBindings,
-                    Handle<GCVector<JSFunction*, 8>> innerFunctions,
-                    uint32_t sourceStart, uint32_t sourceEnd,
--                   uint32_t toStringStart, uint32_t lineno, uint32_t column)
-+                   uint32_t toStringStart, uint32_t lineno, uint32_t column,
-+                   frontend::ParseGoal parseGoal)
- {
-     union {
-         PackedView p;
-         uint64_t packedFields;
-     };
- 
-     p.shouldDeclareArguments = false;
-     p.hasThisBinding = false;
-@@ -4318,16 +4319,17 @@ LazyScript::Create(JSContext* cx, Handle
-     p.isGenerator = false;
-     p.strict = false;
-     p.bindingsAccessedDynamically = false;
-     p.hasDebuggerStatement = false;
-     p.hasDirectEval = false;
-     p.isLikelyConstructorWrapper = false;
-     p.isDerivedClassConstructor = false;
-     p.needsHomeObject = false;
-+    p.parseGoal = uint32_t(parseGoal);
- 
-     LazyScript* res = LazyScript::CreateRaw(cx, fun, sourceObject, packedFields,
-                                             sourceStart, sourceEnd,
-                                             toStringStart, lineno, column);
-     if (!res)
-         return nullptr;
- 
-     JSAtom** resClosedOverBindings = res->closedOverBindings();
-diff --git a/js/src/vm/JSScript.h b/js/src/vm/JSScript.h
---- a/js/src/vm/JSScript.h
-+++ b/js/src/vm/JSScript.h
-@@ -2182,16 +2182,17 @@ class LazyScript : public gc::TenuredCel
-         uint32_t hasDebuggerStatement : 1;
-         uint32_t hasDirectEval : 1;
-         uint32_t isLikelyConstructorWrapper : 1;
-         uint32_t hasBeenCloned : 1;
-         uint32_t treatAsRunOnce : 1;
-         uint32_t isDerivedClassConstructor : 1;
-         uint32_t needsHomeObject : 1;
-         uint32_t hasRest : 1;
-+        uint32_t parseGoal : 1;
-     };
- 
-     union {
-         PackedView p_;
-         uint64_t packedFields_;
-     };
- 
-     // Source location for the script.
-@@ -2224,17 +2225,18 @@ class LazyScript : public gc::TenuredCel
- 
-     // Create a LazyScript and initialize closedOverBindings and innerFunctions
-     // with the provided vectors.
-     static LazyScript* Create(JSContext* cx, HandleFunction fun,
-                               HandleScriptSourceObject sourceObject,
-                               const frontend::AtomVector& closedOverBindings,
-                               Handle<GCVector<JSFunction*, 8>> innerFunctions,
-                               uint32_t begin, uint32_t end,
--                              uint32_t toStringStart, uint32_t lineno, uint32_t column);
-+                              uint32_t toStringStart, uint32_t lineno, uint32_t column,
-+                              frontend::ParseGoal parseGoal);
- 
-     // Create a LazyScript and initialize the closedOverBindings and the
-     // innerFunctions with dummy values to be replaced in a later initialization
-     // phase.
-     //
-     // The "script" argument to this function can be null.  If it's non-null,
-     // then this LazyScript should be associated with the given JSScript.
-     //
-@@ -2321,16 +2323,20 @@ class LazyScript : public gc::TenuredCel
- 
-     bool hasRest() const {
-         return p_.hasRest;
-     }
-     void setHasRest() {
-         p_.hasRest = true;
-     }
- 
-+    frontend::ParseGoal parseGoal() const {
-+        return frontend::ParseGoal(p_.parseGoal);
-+    }
-+
-     bool strict() const {
-         return p_.strict;
-     }
-     void setStrict() {
-         p_.strict = true;
-     }
- 
-     bool bindingsAccessedDynamically() const {

+ 0 - 673
frg/work-js/mozilla-release/patches/mozilla-central_419571.patch

@@ -1,673 +0,0 @@
-# HG changeset patch
-# User Jon Coppeard <jcoppeard@mozilla.com>
-# Date 1527061648 -3600
-#      Wed May 23 08:47:28 2018 +0100
-# Node ID a506ea1db794c9e8e5ba0b52b8f7fc94285a0234
-# Parent  277bd9cf9edc37653b8931349b1c9a232987fd57
-Bug 1427610 - Implement import.meta in the JS shell r=anba
-
-diff --git a/js/src/builtin/ModuleObject.cpp b/js/src/builtin/ModuleObject.cpp
---- a/js/src/builtin/ModuleObject.cpp
-+++ b/js/src/builtin/ModuleObject.cpp
-@@ -996,16 +996,35 @@ ModuleObject::hadEvaluationError() const
- 
- Value
- ModuleObject::evaluationError() const
- {
-     MOZ_ASSERT(hadEvaluationError());
-     return getReservedSlot(EvaluationErrorSlot);
- }
- 
-+JSObject*
-+ModuleObject::metaObject() const
-+{
-+    Value value = getReservedSlot(MetaObjectSlot);
-+    if (value.isObject())
-+        return &value.toObject();
-+
-+    MOZ_ASSERT(value.isUndefined());
-+    return nullptr;
-+}
-+
-+void
-+ModuleObject::setMetaObject(JSObject* obj)
-+{
-+    MOZ_ASSERT(obj);
-+    MOZ_ASSERT(!metaObject());
-+    setReservedSlot(MetaObjectSlot, ObjectValue(*obj));
-+}
-+
- Value
- ModuleObject::hostDefinedField() const
- {
-     return getReservedSlot(HostDefinedSlot);
- }
- 
- void
- ModuleObject::setHostDefinedField(const JS::Value& value)
-@@ -1618,8 +1637,29 @@ ArrayObject* ModuleBuilder::createArray(
-     array->setDenseInitializedLength(length);
- 
-     uint32_t i = 0;
-     for (auto r = map.all(); !r.empty(); r.popFront())
-         array->initDenseElement(i++, ObjectValue(*r.front().value()));
- 
-     return array;
- }
-+
-+JSObject*
-+js::GetOrCreateModuleMetaObject(JSContext* cx, HandleObject moduleArg)
-+{
-+    HandleModuleObject module = moduleArg.as<ModuleObject>();
-+    if (JSObject* obj = module->metaObject())
-+        return obj;
-+
-+    RootedObject metaObject(cx, NewObjectWithGivenProto<PlainObject>(cx, nullptr));
-+    if (!metaObject)
-+        return nullptr;
-+
-+    JS::ModuleMetadataHook func = cx->runtime()->moduleMetadataHook;
-+    MOZ_ASSERT(func);
-+    if (!func(cx, module, metaObject))
-+        return nullptr;
-+
-+    module->setMetaObject(metaObject);
-+
-+    return metaObject;
-+}
-diff --git a/js/src/builtin/ModuleObject.h b/js/src/builtin/ModuleObject.h
---- a/js/src/builtin/ModuleObject.h
-+++ b/js/src/builtin/ModuleObject.h
-@@ -249,16 +249,17 @@ class ModuleObject : public NativeObject
-   public:
-     enum ModuleSlot
-     {
-         ScriptSlot = 0,
-         EnvironmentSlot,
-         NamespaceSlot,
-         StatusSlot,
-         EvaluationErrorSlot,
-+        MetaObjectSlot,
-         HostDefinedSlot,
-         RequestedModulesSlot,
-         ImportEntriesSlot,
-         LocalExportEntriesSlot,
-         IndirectExportEntriesSlot,
-         StarExportEntriesSlot,
-         ImportBindingsSlot,
-         FunctionDeclarationsSlot,
-@@ -299,27 +300,30 @@ class ModuleObject : public NativeObject
-     JSScript* script() const;
-     Scope* enclosingScope() const;
-     ModuleEnvironmentObject& initialEnvironment() const;
-     ModuleEnvironmentObject* environment() const;
-     ModuleNamespaceObject* namespace_();
-     ModuleStatus status() const;
-     bool hadEvaluationError() const;
-     Value evaluationError() const;
-+    JSObject* metaObject() const;
-     Value hostDefinedField() const;
-     ArrayObject& requestedModules() const;
-     ArrayObject& importEntries() const;
-     ArrayObject& localExportEntries() const;
-     ArrayObject& indirectExportEntries() const;
-     ArrayObject& starExportEntries() const;
-     IndirectBindingMap& importBindings();
- 
-     static bool Instantiate(JSContext* cx, HandleModuleObject self);
-     static bool Evaluate(JSContext* cx, HandleModuleObject self);
- 
-+    void setMetaObject(JSObject* obj);
-+
-     void setHostDefinedField(const JS::Value& value);
- 
-     // For BytecodeEmitter.
-     bool noteFunctionDeclaration(JSContext* cx, HandleAtom name, HandleFunction fun);
- 
-     // For intrinsic_InstantiateModuleFunctionDeclarations.
-     static bool instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self);
- 
-@@ -402,16 +406,19 @@ class MOZ_STACK_CLASS ModuleBuilder
-     bool maybeAppendRequestedModule(HandleAtom specifier, frontend::ParseNode* node);
- 
-     template <typename T>
-     ArrayObject* createArray(const JS::Rooted<GCVector<T>>& vector);
-     template <typename K, typename V>
-     ArrayObject* createArray(const JS::Rooted<GCHashMap<K, V>>& map);
- };
- 
-+JSObject*
-+GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
-+
- } // namespace js
- 
- template<>
- inline bool
- JSObject::is<js::ModuleNamespaceObject>() const
- {
-     return js::IsDerivedProxyObject(this, &js::ModuleNamespaceObject::proxyHandler);
- }
-diff --git a/js/src/builtin/SelfHostingDefines.h b/js/src/builtin/SelfHostingDefines.h
---- a/js/src/builtin/SelfHostingDefines.h
-+++ b/js/src/builtin/SelfHostingDefines.h
-@@ -94,18 +94,18 @@
- #define REGEXP_GLOBAL_FLAG      0x02
- #define REGEXP_MULTILINE_FLAG   0x04
- #define REGEXP_STICKY_FLAG      0x08
- #define REGEXP_UNICODE_FLAG     0x10
- 
- #define MODULE_OBJECT_ENVIRONMENT_SLOT        1
- #define MODULE_OBJECT_STATUS_SLOT             3
- #define MODULE_OBJECT_EVALUATION_ERROR_SLOT   4
--#define MODULE_OBJECT_DFS_INDEX_SLOT          13
--#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 14
-+#define MODULE_OBJECT_DFS_INDEX_SLOT          14
-+#define MODULE_OBJECT_DFS_ANCESTOR_INDEX_SLOT 15
- 
- #define MODULE_STATUS_UNINSTANTIATED  0
- #define MODULE_STATUS_INSTANTIATING   1
- #define MODULE_STATUS_INSTANTIATED    2
- #define MODULE_STATUS_EVALUATING      3
- #define MODULE_STATUS_EVALUATED       4
- #define MODULE_STATUS_EVALUATED_ERROR 5
- 
-diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp
---- a/js/src/frontend/BytecodeEmitter.cpp
-+++ b/js/src/frontend/BytecodeEmitter.cpp
-@@ -11143,17 +11143,18 @@ BytecodeEmitter::emitTree(ParseNode* pn,
-         break;
- 
-       case ParseNodeKind::NewTarget:
-         if (!emit1(JSOP_NEWTARGET))
-             return false;
-         break;
- 
-       case ParseNodeKind::ImportMeta:
--        MOZ_CRASH("NYI");
-+        if (!emit1(JSOP_IMPORTMETA))
-+            return false;
-         break;
- 
-       case ParseNodeKind::SetThis:
-         if (!emitSetThis(pn))
-             return false;
-         break;
- 
-       case ParseNodeKind::PosHolder:
-diff --git a/js/src/jit-test/modules/exportImportMeta.js b/js/src/jit-test/modules/exportImportMeta.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit-test/modules/exportImportMeta.js
-@@ -0,0 +1,3 @@
-+export default function() {
-+    return import.meta;
-+}
-diff --git a/js/src/jit-test/tests/modules/import-meta-oom.js b/js/src/jit-test/tests/modules/import-meta-oom.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit-test/tests/modules/import-meta-oom.js
-@@ -0,0 +1,6 @@
-+// |jit-test| module
-+
-+if (typeof oomTest !== "function")
-+    quit();
-+
-+oomTest(() => import.meta);
-diff --git a/js/src/jit-test/tests/modules/import-meta.js b/js/src/jit-test/tests/modules/import-meta.js
-new file mode 100644
---- /dev/null
-+++ b/js/src/jit-test/tests/modules/import-meta.js
-@@ -0,0 +1,58 @@
-+// |jit-test| module
-+
-+// import.meta is an object.
-+assertEq(typeof import.meta, "object");
-+assertEq(import.meta !== null, true);
-+
-+// import.meta always returns the same object.
-+let obj = import.meta;
-+assertEq(import.meta, obj);
-+
-+// Test calling from lazily compile function.
-+function get() {
-+    return import.meta;
-+}
-+assertEq(get(), import.meta);
-+
-+// import.meta.url: This property will contain the module script's base URL,
-+// serialized.
-+
-+assertEq("url" in import.meta, true);
-+assertEq(import.meta.url.endsWith("import-meta.js"), true);
-+
-+import getOtherMetaObject from "exportImportMeta.js";
-+
-+let otherImportMeta = getOtherMetaObject();
-+assertEq(otherImportMeta.url.endsWith("exportImportMeta.js"), true);
-+
-+// By default the import.meta object will be extensible, and its properties will
-+// be writable, configurable, and enumerable.
-+
-+assertEq(Object.isExtensible(import.meta), true);
-+
-+var desc = Object.getOwnPropertyDescriptor(import.meta, "url");
-+assertEq(desc.writable, true);
-+assertEq(desc.enumerable, true);
-+assertEq(desc.configurable, true);
-+assertEq(desc.value, import.meta.url);
-+
-+// The import.meta object's prototype is null.
-+assertEq(Object.getPrototypeOf(import.meta), null);
-+
-+import.meta.url = 0;
-+assertEq(import.meta.url, 0);
-+
-+import.meta.newProp = 42;
-+assertEq(import.meta.newProp, 42);
-+
-+let found = new Set(Reflect.ownKeys(import.meta));
-+
-+assertEq(found.size, 2);
-+assertEq(found.has("url"), true);
-+assertEq(found.has("newProp"), true);
-+
-+delete import.meta.url;
-+delete import.meta.newProp;
-+
-+found = new Set(Reflect.ownKeys(import.meta));
-+assertEq(found.size, 0);
-diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
---- a/js/src/jit/BaselineCompiler.cpp
-+++ b/js/src/jit/BaselineCompiler.cpp
-@@ -1015,16 +1015,17 @@ BaselineCompiler::emitBody()
-           case JSOP_FORCEINTERPRETER:
-             // Intentionally not implemented.
-           case JSOP_SETINTRINSIC:
-             // Run-once opcode during self-hosting initialization.
-           case JSOP_UNUSED126:
-           case JSOP_UNUSED206:
-           case JSOP_UNUSED223:
-           case JSOP_LIMIT:
-+          case JSOP_IMPORTMETA:
-             // === !! WARNING WARNING WARNING !! ===
-             // Do you really want to sacrifice performance by not implementing
-             // this operation in the BaselineCompiler?
-             JitSpew(JitSpew_BaselineAbort, "Unhandled op: %s", CodeName[op]);
-             return Method_CantCompile;
- 
- #define EMIT_OP(OP)                            \
-           case OP:                             \
-diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
---- a/js/src/jit/IonBuilder.cpp
-+++ b/js/src/jit/IonBuilder.cpp
-@@ -2435,16 +2435,17 @@ IonBuilder::inspectOpcode(JSOp op)
-       // Misc
-       case JSOP_DELNAME:
-       case JSOP_FINALLY:
-       case JSOP_GETRVAL:
-       case JSOP_GOSUB:
-       case JSOP_RETSUB:
-       case JSOP_SETINTRINSIC:
-       case JSOP_THROWMSG:
-+      case JSOP_IMPORTMETA:
-         // === !! WARNING WARNING WARNING !! ===
-         // Do you really want to sacrifice performance by not implementing this
-         // operation in the optimizing compiler?
-         break;
- 
-       case JSOP_FORCEINTERPRETER:
-         // Intentionally not implemented.
-         break;
-diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
---- a/js/src/jsapi.cpp
-+++ b/js/src/jsapi.cpp
-@@ -4956,16 +4956,30 @@ JS::GetModuleResolveHook(JSRuntime* rt)
- 
- JS_PUBLIC_API(void)
- JS::SetModuleResolveHook(JSRuntime* rt, JS::ModuleResolveHook func)
- {
-     AssertHeapIsIdle();
-     rt->moduleResolveHook = func;
- }
- 
-+JS_PUBLIC_API(JS::ModuleMetadataHook)
-+JS::GetModuleMetadataHook(JSRuntime* rt)
-+{
-+    AssertHeapIsIdle();
-+    return rt->moduleMetadataHook;
-+}
-+
-+JS_PUBLIC_API(void)
-+JS::SetModuleMetadataHook(JSRuntime* rt, JS::ModuleMetadataHook func)
-+{
-+    AssertHeapIsIdle();
-+    rt->moduleMetadataHook = func;
-+}
-+
- JS_PUBLIC_API(bool)
- JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-                   SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
- {
-     MOZ_ASSERT(!cx->realm()->isAtomsRealm());
-     AssertHeapIsIdle();
-     CHECK_REQUEST(cx);
- 
-diff --git a/js/src/jsapi.h b/js/src/jsapi.h
---- a/js/src/jsapi.h
-+++ b/js/src/jsapi.h
-@@ -3920,16 +3920,31 @@ extern JS_PUBLIC_API(ModuleResolveHook)
- GetModuleResolveHook(JSRuntime* rt);
- 
- /**
-  * Set the HostResolveImportedModule hook for the runtime to the given function.
-  */
- extern JS_PUBLIC_API(void)
- SetModuleResolveHook(JSRuntime* rt, ModuleResolveHook func);
- 
-+using ModuleMetadataHook = bool (*)(JSContext*, HandleObject, HandleObject);
-+
-+/**
-+ * Get the hook for populating the import.meta metadata object.
-+ */
-+extern JS_PUBLIC_API(ModuleMetadataHook)
-+GetModuleMetadataHook(JSRuntime* rt);
-+
-+/**
-+ * Set the hook for populating the import.meta metadata object to the given
-+ * function.
-+ */
-+extern JS_PUBLIC_API(void)
-+SetModuleMetadataHook(JSRuntime* rt, ModuleMetadataHook func);
-+
- /**
-  * Parse the given source buffer as a module in the scope of the current global
-  * of cx and return a source text module record.
-  */
- extern JS_PUBLIC_API(bool)
- CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
-               SourceBufferHolder& srcBuf, JS::MutableHandleObject moduleRecord);
- 
-diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp
---- a/js/src/shell/js.cpp
-+++ b/js/src/shell/js.cpp
-@@ -4307,16 +4307,34 @@ CallModuleResolveHook(JSContext* cx, Han
-          JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
-          return nullptr;
-     }
- 
-     return &result.toObject();
- }
- 
- static bool
-+ShellModuleMetadataHook(JSContext* cx, HandleObject module, HandleObject metaObject)
-+{
-+    // For the shell, just use the script's filename as the base URL.
-+    RootedScript script(cx, module->as<ModuleObject>().script());
-+    const char* filename = script->scriptSource()->filename();
-+    MOZ_ASSERT(filename);
-+
-+    RootedString url(cx, NewStringCopyZ<CanGC>(cx, filename));
-+    if (!url)
-+        return false;
-+
-+    if (!JS_DefineProperty(cx, metaObject, "url", url, JSPROP_ENUMERATE))
-+        return false;
-+
-+    return true;
-+}
-+
-+static bool
- GetModuleLoadPath(JSContext* cx, unsigned argc, Value* vp)
- {
-     CallArgs args = CallArgsFromVp(argc, vp);
- 
-     ShellContext* sc = GetShellContext(cx);
-     if (sc->moduleLoadPath) {
-         JSString* str = JS_NewStringCopyZ(cx, sc->moduleLoadPath.get());
-         if (!str)
-@@ -9311,16 +9329,17 @@ main(int argc, char** argv, char** envp)
-         JS_SetGCParameter(cx, JSGC_DYNAMIC_MARK_SLICE, 1);
-         JS_SetGCParameter(cx, JSGC_SLICE_TIME_BUDGET, 10);
-     }
- #endif
- 
-     js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
- 
-     JS::SetModuleResolveHook(cx->runtime(), CallModuleResolveHook);
-+    JS::SetModuleMetadataHook(cx->runtime(), ShellModuleMetadataHook);
- 
-     result = Shell(cx, &op, envp);
- 
- #ifdef DEBUG
-     if (OOM_printAllocationCount)
-         printf("OOM max count: %" PRIu64 "\n", js::oom::counter);
- #endif
- 
-diff --git a/js/src/vm/EnvironmentObject.cpp b/js/src/vm/EnvironmentObject.cpp
---- a/js/src/vm/EnvironmentObject.cpp
-+++ b/js/src/vm/EnvironmentObject.cpp
-@@ -3210,19 +3210,29 @@ WithEnvironmentObject::scope() const
- {
-     MOZ_ASSERT(isSyntactic());
-     return *static_cast<WithScope*>(getReservedSlot(SCOPE_SLOT).toGCThing());
- }
- 
- ModuleEnvironmentObject*
- js::GetModuleEnvironmentForScript(JSScript* script)
- {
-+    ModuleObject* module = GetModuleObjectForScript(script);
-+    if (!module)
-+        return nullptr;
-+
-+    return module->environment();
-+}
-+
-+ModuleObject*
-+js::GetModuleObjectForScript(JSScript* script)
-+{
-     for (ScopeIter si(script); si; si++) {
-         if (si.kind() == ScopeKind::Module)
--            return si.scope()->as<ModuleScope>().module()->environment();
-+            return si.scope()->as<ModuleScope>().module();
-     }
-     return nullptr;
- }
- 
- bool
- js::GetThisValueForDebuggerMaybeOptimizedOut(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc,
-                                              MutableHandleValue res)
- {
-diff --git a/js/src/vm/EnvironmentObject.h b/js/src/vm/EnvironmentObject.h
---- a/js/src/vm/EnvironmentObject.h
-+++ b/js/src/vm/EnvironmentObject.h
-@@ -1160,16 +1160,18 @@ IsFrameInitialEnvironment(AbstractFrameP
-     return false;
- }
- 
- extern bool
- CreateObjectsForEnvironmentChain(JSContext* cx, AutoObjectVector& chain,
-                                  HandleObject terminatingEnv,
-                                  MutableHandleObject envObj);
- 
-+ModuleObject* GetModuleObjectForScript(JSScript* script);
-+
- ModuleEnvironmentObject* GetModuleEnvironmentForScript(JSScript* script);
- 
- MOZ_MUST_USE bool
- GetThisValueForDebuggerMaybeOptimizedOut(JSContext* cx, AbstractFramePtr frame,
-                                          jsbytecode* pc, MutableHandleValue res);
- 
- MOZ_MUST_USE bool
- CheckVarNameConflict(JSContext* cx, Handle<LexicalEnvironmentObject*> lexicalEnv,
-diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp
---- a/js/src/vm/Interpreter.cpp
-+++ b/js/src/vm/Interpreter.cpp
-@@ -17,16 +17,17 @@
- 
- #include <string.h>
- 
- #include "jslibmath.h"
- #include "jsnum.h"
- 
- #include "builtin/Array.h"
- #include "builtin/Eval.h"
-+#include "builtin/ModuleObject.h"
- #include "builtin/String.h"
- #include "jit/AtomicOperations.h"
- #include "jit/BaselineJIT.h"
- #include "jit/Ion.h"
- #include "jit/IonAnalysis.h"
- #include "jit/Jit.h"
- #include "util/StringBuffer.h"
- #include "vm/AsyncFunction.h"
-@@ -1626,17 +1627,16 @@ GetSuperEnvFunction(JSContext* cx, Inter
-                 continue;
- 
-             return callee;
-         }
-     }
-     MOZ_CRASH("unexpected env chain for GetSuperEnvFunction");
- }
- 
--
- /*
-  * As an optimization, the interpreter creates a handful of reserved Rooted<T>
-  * variables at the beginning, thus inserting them into the Rooted list once
-  * upon entry. ReservedRooted "borrows" a reserved Rooted variable and uses it
-  * within a local scope, resetting the value to nullptr (or the appropriate
-  * equivalent for T) at scope end. This avoids inserting/removing the Rooted
-  * from the rooter list, while preventing stale values from being kept alive
-  * unnecessarily.
-@@ -4207,16 +4207,29 @@ CASE(JSOP_SUPERBASE)
- }
- END_CASE(JSOP_SUPERBASE)
- 
- CASE(JSOP_NEWTARGET)
-     PUSH_COPY(REGS.fp()->newTarget());
-     MOZ_ASSERT(REGS.sp[-1].isObject() || REGS.sp[-1].isUndefined());
- END_CASE(JSOP_NEWTARGET)
- 
-+CASE(JSOP_IMPORTMETA)
-+{
-+    ReservedRooted<JSObject*> module(&rootObject0, GetModuleObjectForScript(script));
-+    MOZ_ASSERT(module);
-+
-+    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, module);
-+    if (!metaObject)
-+        goto error;
-+
-+    PUSH_OBJECT(*metaObject);
-+}
-+END_CASE(JSOP_NEWTARGET)
-+
- CASE(JSOP_SUPERFUN)
- {
-     ReservedRooted<JSObject*> superEnvFunc(&rootObject0, &GetSuperEnvFunction(cx, REGS));
-     ReservedRooted<JSObject*> superFun(&rootObject1);
-     superFun = SuperFunOperation(cx, superEnvFunc);
-     if (!superFun)
-         goto error;
- 
-diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h
---- a/js/src/vm/Opcodes.h
-+++ b/js/src/vm/Opcodes.h
-@@ -58,16 +58,17 @@ 1234567890123456789012345678901234567890
-  *     Local Variables
-  *     Aliased Variables
-  *     Intrinsics
-  *     Block-local Scope
-  *     This
-  *     Super
-  *     Arguments
-  *     Var Scope
-+ *     Modules
-  *   [Operators]
-  *     Comparison Operators
-  *     Arithmetic Operators
-  *     Bitwise Logical Operators
-  *     Bitwise Shift Operators
-  *     Logical Operators
-  *     Special Operators
-  *     Stack Operations
-@@ -2339,24 +2340,32 @@ 1234567890123456789012345678901234567890
-      * Like JSOP_CALL, but tells the function that the return value is ignored.
-      * stack.
-      *   Category: Statements
-      *   Type: Function
-      *   Operands: uint16_t argc
-      *   Stack: callee, this, args[0], ..., args[argc-1] => rval
-      *   nuses: (argc+2)
-      */ \
--    macro(JSOP_CALL_IGNORES_RV, 231, "call-ignores-rv", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
-+    macro(JSOP_CALL_IGNORES_RV, 231, "call-ignores-rv", NULL, 3, -1, 1, JOF_UINT16|JOF_INVOKE|JOF_TYPESET) \
-+    /*
-+     * Push "import.meta"
-+     *
-+     *   Category: Variables and Scopes
-+     *   Type: Modules
-+     *   Operands:
-+     *   Stack: => import.meta
-+     */ \
-+    macro(JSOP_IMPORTMETA,    232, "importmeta", NULL,      1,  0,  1,  JOF_BYTE)
- 
- /*
-  * In certain circumstances it may be useful to "pad out" the opcode space to
-  * a power of two.  Use this macro to do so.
-  */
- #define FOR_EACH_TRAILING_UNUSED_OPCODE(macro) \
--    macro(232) \
-     macro(233) \
-     macro(234) \
-     macro(235) \
-     macro(236) \
-     macro(237) \
-     macro(238) \
-     macro(239) \
-     macro(240) \
-diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
---- a/js/src/vm/Runtime.cpp
-+++ b/js/src/vm/Runtime.cpp
-@@ -170,17 +170,18 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
-     autoWritableJitCodeActive_(false),
-     oomCallback(nullptr),
-     debuggerMallocSizeOf(ReturnZeroSize),
-     lastAnimationTime(0),
-     performanceMonitoring_(),
-     stackFormat_(parentRuntime ? js::StackFormat::Default
-                                : js::StackFormat::SpiderMonkey),
-     wasmInstances(mutexid::WasmRuntimeInstances),
--    moduleResolveHook()
-+    moduleResolveHook(),
-+    moduleMetadataHook()
- {
-     JS_COUNT_CTOR(JSRuntime);
-     liveRuntimesCount++;
- 
-     lcovOutput().init();
- }
- 
- JSRuntime::~JSRuntime()
-diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h
---- a/js/src/vm/Runtime.h
-+++ b/js/src/vm/Runtime.h
-@@ -938,16 +938,20 @@ struct JSRuntime : public js::MallocProv
-     // List of all the live wasm::Instances in the runtime. Equal to the union
-     // of all instances registered in all JSCompartments. Accessed from watchdog
-     // threads for purposes of wasm::InterruptRunningCode().
-     js::ExclusiveData<js::wasm::InstanceVector> wasmInstances;
- 
-     // The implementation-defined abstract operation HostResolveImportedModule.
-     js::MainThreadData<JS::ModuleResolveHook> moduleResolveHook;
- 
-+    // A hook that implements the abstract operations
-+    // HostGetImportMetaProperties and HostFinalizeImportMeta.
-+    js::MainThreadData<JS::ModuleMetadataHook> moduleMetadataHook;
-+
-   public:
- #if defined(JS_BUILD_BINAST)
-     js::BinaryASTSupport& binast() {
-         return binast_;
-     }
-   private:
-     js::BinaryASTSupport binast_;
- #endif // defined(JS_BUILD_BINAST)

+ 0 - 169
frg/work-js/mozilla-release/patches/mozilla-central_419572.patch

@@ -1,169 +0,0 @@
-# HG changeset patch
-# User Jon Coppeard <jcoppeard@mozilla.com>
-# Date 1527061648 -3600
-#      Wed May 23 08:47:28 2018 +0100
-# Node ID 847453f52aab8c637cb7ee1365375015becbeb20
-# Parent  a506ea1db794c9e8e5ba0b52b8f7fc94285a0234
-Bug 1427610 - Support import.meta in the JITs r=jandem
-
-diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp
---- a/js/src/jit/BaselineCompiler.cpp
-+++ b/js/src/jit/BaselineCompiler.cpp
-@@ -1015,17 +1015,16 @@ BaselineCompiler::emitBody()
-           case JSOP_FORCEINTERPRETER:
-             // Intentionally not implemented.
-           case JSOP_SETINTRINSIC:
-             // Run-once opcode during self-hosting initialization.
-           case JSOP_UNUSED126:
-           case JSOP_UNUSED206:
-           case JSOP_UNUSED223:
-           case JSOP_LIMIT:
--          case JSOP_IMPORTMETA:
-             // === !! WARNING WARNING WARNING !! ===
-             // Do you really want to sacrifice performance by not implementing
-             // this operation in the BaselineCompiler?
-             JitSpew(JitSpew_BaselineAbort, "Unhandled op: %s", CodeName[op]);
-             return Method_CantCompile;
- 
- #define EMIT_OP(OP)                            \
-           case OP:                             \
-@@ -5076,8 +5075,22 @@ BaselineCompiler::emit_JSOP_DERIVEDCONST
-     pushArg(ImmGCPtr(script));
-     if (!callVM(MakeDefaultConstructorInfo))
-         return false;
- 
-     masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
-     frame.push(R0);
-     return true;
- }
-+
-+bool
-+BaselineCompiler::emit_JSOP_IMPORTMETA()
-+{
-+    RootedModuleObject module(cx, GetModuleObjectForScript(script));
-+    MOZ_ASSERT(module);
-+
-+    JSObject* metaObject = GetOrCreateModuleMetaObject(cx, module);
-+    if (!metaObject)
-+        return false;
-+
-+    frame.push(ObjectValue(*metaObject));
-+    return true;
-+}
-diff --git a/js/src/jit/BaselineCompiler.h b/js/src/jit/BaselineCompiler.h
---- a/js/src/jit/BaselineCompiler.h
-+++ b/js/src/jit/BaselineCompiler.h
-@@ -251,17 +251,18 @@ namespace jit {
-     _(JSOP_IS_CONSTRUCTING)    \
-     _(JSOP_TRY_DESTRUCTURING_ITERCLOSE) \
-     _(JSOP_CHECKCLASSHERITAGE) \
-     _(JSOP_INITHOMEOBJECT)     \
-     _(JSOP_BUILTINPROTO)       \
-     _(JSOP_OBJWITHPROTO)       \
-     _(JSOP_FUNWITHPROTO)       \
-     _(JSOP_CLASSCONSTRUCTOR)   \
--    _(JSOP_DERIVEDCONSTRUCTOR)
-+    _(JSOP_DERIVEDCONSTRUCTOR) \
-+    _(JSOP_IMPORTMETA)
- 
- class BaselineCompiler : public BaselineCompilerSpecific
- {
-     FixedList<Label>            labels_;
-     NonAssertingLabel           return_;
-     NonAssertingLabel           postBarrierSlot_;
- 
-     // Native code offset right before the scope chain is initialized.
-diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp
---- a/js/src/jit/IonBuilder.cpp
-+++ b/js/src/jit/IonBuilder.cpp
-@@ -2371,16 +2371,19 @@ IonBuilder::inspectOpcode(JSOp op)
-         // Assuming optimization isn't available doesn't affect correctness.
-         // TODO: Investigate dynamic checks.
-         MDefinition* arr = current->peek(-1);
-         arr->setImplicitlyUsedUnchecked();
-         pushConstant(BooleanValue(false));
-         return Ok();
-       }
- 
-+      case JSOP_IMPORTMETA:
-+          return jsop_importmeta();
-+
-       // ===== NOT Yet Implemented =====
-       // Read below!
- 
-       // With
-       case JSOP_ENTERWITH:
-       case JSOP_LEAVEWITH:
- 
-       // Spread
-@@ -2435,17 +2438,16 @@ IonBuilder::inspectOpcode(JSOp op)
-       // Misc
-       case JSOP_DELNAME:
-       case JSOP_FINALLY:
-       case JSOP_GETRVAL:
-       case JSOP_GOSUB:
-       case JSOP_RETSUB:
-       case JSOP_SETINTRINSIC:
-       case JSOP_THROWMSG:
--      case JSOP_IMPORTMETA:
-         // === !! WARNING WARNING WARNING !! ===
-         // Do you really want to sacrifice performance by not implementing this
-         // operation in the optimizing compiler?
-         break;
- 
-       case JSOP_FORCEINTERPRETER:
-         // Intentionally not implemented.
-         break;
-@@ -13138,16 +13140,31 @@ IonBuilder::jsop_implicitthis(PropertyNa
- 
-     MImplicitThis* implicitThis = MImplicitThis::New(alloc(), current->environmentChain(), name);
-     current->add(implicitThis);
-     current->push(implicitThis);
- 
-     return resumeAfter(implicitThis);
- }
- 
-+AbortReasonOr<Ok>
-+IonBuilder::jsop_importmeta()
-+{
-+    ModuleObject* module = GetModuleObjectForScript(script());
-+    MOZ_ASSERT(module);
-+
-+    // The object must have been created already when we compiled for baseline.
-+    JSObject* metaObject = module->metaObject();
-+    MOZ_ASSERT(metaObject);
-+
-+    pushConstant(ObjectValue(*metaObject));
-+
-+    return Ok();
-+}
-+
- MInstruction*
- IonBuilder::addConvertElementsToDoubles(MDefinition* elements)
- {
-     MInstruction* convert = MConvertElementsToDoubles::New(alloc(), elements);
-     current->add(convert);
-     return convert;
- }
- 
-diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h
---- a/js/src/jit/IonBuilder.h
-+++ b/js/src/jit/IonBuilder.h
-@@ -586,16 +586,17 @@ class IonBuilder
-     AbortReasonOr<Ok> jsop_setaliasedvar(EnvironmentCoordinate ec);
-     AbortReasonOr<Ok> jsop_debugger();
-     AbortReasonOr<Ok> jsop_newtarget();
-     AbortReasonOr<Ok> jsop_checkisobj(uint8_t kind);
-     AbortReasonOr<Ok> jsop_checkiscallable(uint8_t kind);
-     AbortReasonOr<Ok> jsop_checkobjcoercible();
-     AbortReasonOr<Ok> jsop_pushcallobj();
-     AbortReasonOr<Ok> jsop_implicitthis(PropertyName* name);
-+    AbortReasonOr<Ok> jsop_importmeta();
- 
-     /* Inlining. */
- 
-     enum InliningStatus
-     {
-         InliningStatus_NotInlined,
-         InliningStatus_WarmUpCountTooLow,
-         InliningStatus_Inlined

+ 0 - 116
frg/work-js/mozilla-release/patches/mozilla-central_419573.patch

@@ -1,116 +0,0 @@
-# HG changeset patch
-# User Jon Coppeard <jcoppeard@mozilla.com>
-# Date 1527064213 -3600
-#      Wed May 23 09:30:13 2018 +0100
-# Node ID 9a5e8a990f0abb3be62858082bf82b18a9925949
-# Parent  847453f52aab8c637cb7ee1365375015becbeb20
-Bug 1427610 - Implement import.meta in the browser r=bkelly
-
-diff --git a/dom/script/ScriptLoader.cpp b/dom/script/ScriptLoader.cpp
---- a/dom/script/ScriptLoader.cpp
-+++ b/dom/script/ScriptLoader.cpp
-@@ -780,25 +780,54 @@ HostResolveImportedModule(JSContext* aCx
-   MOZ_ASSERT(ms, "Resolved module not found in module map");
- 
-   MOZ_ASSERT(!ms->HasParseError());
-   MOZ_ASSERT(ms->ModuleRecord());
- 
-   return ms->ModuleRecord();
- }
- 
-+bool
-+HostPopulateImportMeta(JSContext* aCx, JS::Handle<JSObject*> aModule,
-+                       JS::Handle<JSObject*> aMetaObject)
-+{
-+  MOZ_DIAGNOSTIC_ASSERT(aModule);
-+
-+  JS::Value value = JS::GetModuleHostDefinedField(aModule);
-+  if (value.isUndefined()) {
-+    JS_ReportErrorASCII(aCx, "Module script not found");
-+    return false;
-+  }
-+
-+  auto script = static_cast<ModuleScript*>(value.toPrivate());
-+  MOZ_DIAGNOSTIC_ASSERT(script->ModuleRecord() == aModule);
-+
-+  nsAutoCString url;
-+  MOZ_DIAGNOSTIC_ASSERT(script->BaseURL());
-+  MOZ_ALWAYS_SUCCEEDS(script->BaseURL()->GetAsciiSpec(url));
-+
-+  JS::Rooted<JSString*> urlString(aCx, JS_NewStringCopyZ(aCx, url.get()));
-+  if (!urlString) {
-+    JS_ReportOutOfMemory(aCx);
-+    return false;
-+  }
-+
-+  return JS_DefineProperty(aCx, aMetaObject, "url", urlString, JSPROP_ENUMERATE);
-+}
-+
- static void
- EnsureModuleResolveHook(JSContext* aCx)
- {
-   JSRuntime* rt = JS_GetRuntime(aCx);
-   if (JS::GetModuleResolveHook(rt)) {
-     return;
-   }
- 
-   JS::SetModuleResolveHook(rt, HostResolveImportedModule);
-+  JS::SetModuleMetadataHook(rt, HostPopulateImportMeta);
- }
- 
- void
- ScriptLoader::CheckModuleDependenciesLoaded(ModuleLoadRequest* aRequest)
- {
-   LOG(("ScriptLoadRequest (%p): Check dependencies loaded", aRequest));
- 
-   RefPtr<ModuleScript> moduleScript = aRequest->mModuleScript;
-diff --git a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html.ini b/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html.ini
-deleted file mode 100644
---- a/testing/web-platform/meta/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html.ini
-+++ /dev/null
-@@ -1,4 +0,0 @@
--[import-meta-url.html]
--  [Untitled]
--    expected: FAIL
--
-diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html
---- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html
-+++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html
-@@ -16,16 +16,37 @@ test(() => {
-                 base + "/import-meta-root.js");
- }, "import.meta.url in a root external script");
- 
- test(() => {
-   assert_equals(importMetaOnDependentModule.url,
-                 base + "/import-meta-dependent.js");
- }, "import.meta.url in a dependent external script");
- 
-+test(() => {
-+  assert_equals(typeof importMetaOnRootModule, "object");
-+  assert_not_equals(importMetaOnRootModule, null);
-+}, "import.meta is an object");
-+
-+test(() => {
-+  importMetaOnRootModule.newProperty = 1;
-+  assert_true(Object.isExtensible(importMetaOnRootModule));
-+}, "import.meta is extensible");
-+
-+test(() => {
-+  let names = new Set(Reflect.ownKeys(importMetaOnRootModule));
-+  for (name of names) {
-+    var desc = Object.getOwnPropertyDescriptor(importMetaOnRootModule, name);
-+    assert_equals(desc.writable, true);
-+    assert_equals(desc.enumerable, true);
-+    assert_equals(desc.configurable, true);
-+  }
-+}, "import.meta's properties are writable, configurable, and enumerable");
-+
-+
- import { importMetaOnRootModule as hashedImportMetaOnRootModule1,
-          importMetaOnDependentModule as hashedImportMetaOnDependentModule1 }
-        from "./import-meta-root.js#1";
- 
- import { importMetaOnRootModule as hashedImportMetaOnRootModule2,
-          importMetaOnDependentModule as hashedImportMetaOnDependentModule2 }
-        from "./import-meta-root.js#2";
- 

+ 0 - 37586
frg/work-js/mozilla-release/patches/mozilla-central_476624.patch

@@ -1,37586 +0,0 @@
-# HG changeset patch
-# User Ryan VanderMeulen <ryanvm@gmail.com>
-# Date 1559574709 0
-#      Mon Jun 03 15:11:49 2019 +0000
-# Node ID 038735236230fe6c9137006418352c852fd4c199
-# Parent  23f5c0544d7bd2e6ceab83657a63e85c9c95ff85
-Bug 1554306 - Update HarfBuzz to version 2.5.1. r=jfkthame
-
-Differential Revision: https://phabricator.services.mozilla.com/D32776
-
-diff --git a/gfx/harfbuzz/AUTHORS b/gfx/harfbuzz/AUTHORS
---- a/gfx/harfbuzz/AUTHORS
-+++ b/gfx/harfbuzz/AUTHORS
-@@ -1,11 +1,14 @@
- Behdad Esfahbod
-+David Corbett
- David Turner
- Ebrahim Byagowi
-+Garret Rieger
- Jonathan Kew
- Khaled Hosny
- Lars Knoll
- Martin Hosken
- Owen Taylor
-+Roderick Sheeter
- Roozbeh Pournader
- Simon Hausmann
- Werner Lemberg
-diff --git a/gfx/harfbuzz/COPYING b/gfx/harfbuzz/COPYING
---- a/gfx/harfbuzz/COPYING
-+++ b/gfx/harfbuzz/COPYING
-@@ -1,13 +1,14 @@
- HarfBuzz is licensed under the so-called "Old MIT" license.  Details follow.
- For parts of HarfBuzz that are licensed under different licenses see individual
- files names COPYING in subdirectories where applicable.
- 
--Copyright © 2010,2011,2012  Google, Inc.
-+Copyright © 2010,2011,2012,2013,2014,2015,2016,2017,2018,2019  Google, Inc.
-+Copyright © 2019  Facebook, Inc.
- Copyright © 2012  Mozilla Foundation
- Copyright © 2011  Codethink Limited
- Copyright © 2008,2010  Nokia Corporation and/or its subsidiary(-ies)
- Copyright © 2009  Keith Stribley
- Copyright © 2009  Martin Hosken and SIL International
- Copyright © 2007  Chris Wilson
- Copyright © 2006  Behdad Esfahbod
- Copyright © 2005  David Turner
-diff --git a/gfx/harfbuzz/Makefile.am b/gfx/harfbuzz/Makefile.am
---- a/gfx/harfbuzz/Makefile.am
-+++ b/gfx/harfbuzz/Makefile.am
-@@ -4,22 +4,28 @@ NULL =
- 
- ACLOCAL_AMFLAGS = -I m4
- 
- SUBDIRS = src util test docs
- 
- EXTRA_DIST = \
- 	autogen.sh \
- 	harfbuzz.doap \
-+	README.md \
-+	README.mingw.md \
- 	README.python.md \
--	README.wine.md \
- 	BUILD.md \
- 	RELEASING.md \
-+	TESTING.md \
- 	CMakeLists.txt \
- 	replace-enum-strings.cmake \
-+	mingw-configure.sh \
-+	mingw-ldd.py \
-+	mingw32.sh \
-+	mingw64.sh \
- 	$(NULL)
- 
- MAINTAINERCLEANFILES = \
- 	$(GITIGNORE_MAINTAINERCLEANFILES_TOPLEVEL) \
- 	$(GITIGNORE_MAINTAINERCLEANFILES_M4_LIBTOOL) \
- 	$(GITIGNORE_MAINTAINERCLEANFILES_MAKEFILE_IN) \
- 	$(srcdir)/INSTALL \
- 	$(srcdir)/ChangeLog \
-@@ -55,32 +61,42 @@ ChangeLog: $(srcdir)/ChangeLog
- 
- DISTCHECK_CONFIGURE_FLAGS = \
- 	--enable-gtk-doc \
- 	--disable-doc-cross-references \
- 	--with-gobject \
- 	--enable-introspection \
- 	$(NULL)
- 
--# TODO: Copy infrastructure from cairo
--
- # TAR_OPTIONS is not set as env var for 'make dist'.  How to fix that?
- TAR_OPTIONS = --owner=0 --group=0
- 
- dist-hook: dist-clear-sticky-bits
- # Clean up any sticky bits we may inherit from parent dir
- dist-clear-sticky-bits:
- 	chmod -R a-s $(distdir)
- 
--
--tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.bz2
-+tar_file = $(PACKAGE_TARNAME)-$(VERSION).tar.xz
- sha256_file = $(tar_file).sha256
- gpg_file = $(sha256_file).asc
- $(sha256_file): $(tar_file)
- 	sha256sum $^ > $@
- $(gpg_file): $(sha256_file)
- 	@echo "Please enter your GPG password to sign the checksum."
- 	gpg --armor --sign $^
- 
- release-files: $(tar_file) $(sha256_file) $(gpg_file)
- 
-+dist-win:
-+	@case $(host_triplet) in *-w64-mingw32) ;; *) echo "Error: Requires mingw build. See README.mingw.md.">&2; exit 1 ;; esac
-+	@DIR=$(PACKAGE_TARNAME)-$(VERSION)-win`case $(host_triplet) in i686-*) echo 32 ;; x86_64-*) echo 64 ;; esac`; \
-+	$(RM) -r $$DIR; $(MKDIR_P) $$DIR || exit 1; \
-+	cp util/.libs/hb-{shape,view,subset}.exe $$DIR && \
-+	$(top_srcdir)/mingw-ldd.py $$DIR/hb-view.exe | grep -v 'not found' | cut -d '>' -f 2 | xargs cp -t $$DIR && \
-+	cp src/.libs/libharfbuzz{,-subset}-0.dll $$DIR && \
-+	chmod a+x $$DIR/*.{exe,dll} && \
-+	$(STRIP) $$DIR/*.{exe,dll} && \
-+	zip -r $$DIR.zip $$DIR && \
-+	$(RM) -r $$DIR && \
-+	echo "$$DIR.zip is ready."
-+
- 
- -include $(top_srcdir)/git.mk
-diff --git a/gfx/harfbuzz/NEWS b/gfx/harfbuzz/NEWS
---- a/gfx/harfbuzz/NEWS
-+++ b/gfx/harfbuzz/NEWS
-@@ -1,8 +1,33 @@
-+Overview of changes leading to 2.5.1
-+Friday, May 31, 2019
-+====================================
-+- Fix build with various versions of Visual Studio.
-+- Improved documentation, thanks to Nathan Willis.
-+- Bugfix in subsetting glyf table.
-+- Improved scripts for cross-compiling for Windows using mingw.
-+- Rename HB_MATH_GLYPH_PART_FLAG_EXTENDER to HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER.
-+  A deprecated macro is added for backwards-compatibility.
-+
-+
-+Overview of changes leading to 2.5.0
-+Friday, May 24, 2019
-+====================================
-+- This release does not include much functional changes, but includes major internal
-+  code-base changes.  We now require C++11.  Support for gcc 4.8 and earlier has been
-+  dropped.
-+- New hb-config.hh facility for compiling smaller library for embedded and web usecases.
-+- New Unicode Character Databse implementation that is half the size of previously-used
-+  UCDN.
-+- Subsetter improvements.
-+- Improved documentation, thanks to Nathan Willis.
-+- Misc shaping fixes.
-+
-+
- Overview of changes leading to 2.4.0
- Monday, March 25, 2019
- ====================================
- - Unicode 12.
- - Misc fixes.
- - Subsetter improvements.
- - New API:
- HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE
-diff --git a/gfx/harfbuzz/README-mozilla b/gfx/harfbuzz/README-mozilla
---- a/gfx/harfbuzz/README-mozilla
-+++ b/gfx/harfbuzz/README-mozilla
-@@ -1,12 +1,12 @@
- This directory contains the HarfBuzz source from the upstream repo:
- https://github.com/harfbuzz/harfbuzz
- 
--Current version: 2.4.0 [commit d6fc1d49aa099104a889c96bc9087c21d8fc0960]
-+Current version: 2.5.1 [commit 93c455567fe3d92a7efe65bf0e9ac2af794e2c4f]
- 
- UPDATING:
- 
- Our in-tree copy of HarfBuzz does not depend on any generated files from the
- upstream build system. Therefore, it should be sufficient to simply overwrite
- the in-tree files one the updated ones from upstream to perform updates.
- 
- To simplify this, the in-tree copy can be updated by running
-diff --git a/gfx/harfbuzz/README.md b/gfx/harfbuzz/README.md
---- a/gfx/harfbuzz/README.md
-+++ b/gfx/harfbuzz/README.md
-@@ -8,11 +8,15 @@
- [ABI Tracker](http://abi-laboratory.pro/tracker/timeline/harfbuzz/)
- 
- This is HarfBuzz, a text shaping library.
- 
- For bug reports, mailing list, and other information please visit:
- 
-   http://harfbuzz.org/
- 
--For license information, see the file COPYING.
-+For license information, see [COPYING](COPYING).
-+
-+For build information, see [BUILD.md](BUILD.md).
-+
-+For test execution, see [TESTING.md](TESTING.md).
- 
- Documentation: https://harfbuzz.github.io
-diff --git a/gfx/harfbuzz/THANKS b/gfx/harfbuzz/THANKS
---- a/gfx/harfbuzz/THANKS
-+++ b/gfx/harfbuzz/THANKS
-@@ -1,7 +1,7 @@
- Bradley Grainger
--Khaled Hosny
- Kenichi Ishibashi
-+Ivan Kuckir <https://photopea.com/>
- Ryan Lortie
- Jeff Muizelaar
- suzuki toshiya
- Philip Withnall
-diff --git a/gfx/harfbuzz/configure.ac b/gfx/harfbuzz/configure.ac
---- a/gfx/harfbuzz/configure.ac
-+++ b/gfx/harfbuzz/configure.ac
-@@ -1,34 +1,34 @@
- AC_PREREQ([2.64])
- AC_INIT([HarfBuzz],
--        [2.4.0],
-+        [2.5.1],
-         [https://github.com/harfbuzz/harfbuzz/issues/new],
-         [harfbuzz],
-         [http://harfbuzz.org/])
- 
- AC_CONFIG_MACRO_DIR([m4])
- AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
- AC_CONFIG_HEADERS([config.h])
- 
--AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-bzip2 no-dist-gzip -Wall no-define color-tests -Wno-portability])
-+AM_INIT_AUTOMAKE([1.13.0 gnits tar-ustar dist-xz no-dist-gzip -Wall no-define color-tests -Wno-portability])
- AM_SILENT_RULES([yes])
- AX_CODE_COVERAGE
- 
- # Initialize libtool
- m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
- LT_PREREQ([2.2])
- LT_INIT([disable-static])
- 
- # Check for programs
- AC_PROG_CC
- AC_PROG_CC_C99
- AM_PROG_CC_C_O
- AC_PROG_CXX
--dnl AX_CXX_COMPILE_STDCXX(11, noext, optional)
-+AX_CXX_COMPILE_STDCXX(11,, optional)
- AC_SYS_LARGEFILE
- PKG_PROG_PKG_CONFIG([0.20])
- AM_MISSING_PROG([RAGEL], [ragel])
- AM_MISSING_PROG([GIT], [git])
- 
- # Version
- m4_define(hb_version_triplet,m4_split(AC_PACKAGE_VERSION,[[.]]))
- m4_define(hb_version_major,m4_argn(1,hb_version_triplet))
-@@ -129,19 +129,17 @@ case "$host" in
-   *-*-mingw*)
-     hb_os_win32=yes
-     ;;
- esac
- AC_MSG_RESULT([$hb_os_win32])
- AM_CONDITIONAL(OS_WIN32, test "$hb_os_win32" = "yes")
- 
- have_pthread=false
--if test "$hb_os_win32" = no; then
--	AX_PTHREAD([have_pthread=true])
--fi
-+AX_PTHREAD([have_pthread=true])
- if $have_pthread; then
- 	AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads])
- fi
- AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
- 
- dnl ==========================================================================
- 
- have_fallback=true
-@@ -295,31 +293,16 @@ if $have_icu; then
- 		AC_DEFINE(HAVE_ICU_BUILTIN, 1, [Use hb-icu Unicode callbacks])
- 	fi
- fi
- AM_CONDITIONAL(HAVE_ICU, $have_icu)
- AM_CONDITIONAL(HAVE_ICU_BUILTIN, $have_icu && test "x$with_icu" = "xbuiltin")
- 
- dnl ===========================================================================
- 
--AC_ARG_WITH(ucdn,
--	[AS_HELP_STRING([--with-ucdn=@<:@yes/no@:>@],
--			[Use builtin UCDN library @<:@default=yes@:>@])],,
--	[with_ucdn=yes])
--have_ucdn=false
--if test "x$with_ucdn" = "xyes"; then
--	have_ucdn=true
--fi
--if $have_ucdn; then
--	AC_DEFINE(HAVE_UCDN, 1, [Have UCDN Unicode functions])
--fi
--AM_CONDITIONAL(HAVE_UCDN, $have_ucdn)
--
--dnl ==========================================================================
--
- AC_ARG_WITH(graphite2,
- 	[AS_HELP_STRING([--with-graphite2=@<:@yes/no/auto@:>@],
- 			[Use the graphite2 library @<:@default=no@:>@])],,
- 	[with_graphite2=no])
- have_graphite2=false
- GRAPHITE2_DEPS="graphite2 >= 1.2.0"
- AC_SUBST(GRAPHITE2_DEPS)
- if test "x$with_graphite2" = "xyes" -o "x$with_graphite2" = "xauto"; then
-@@ -492,17 +475,16 @@ if test "$os_win32" = no && ! $have_pthr
- fi
- 
- dnl ===========================================================================
- 
- AC_CONFIG_FILES([
- Makefile
- src/Makefile
- src/harfbuzz-config.cmake
--src/hb-ucdn/Makefile
- util/Makefile
- test/Makefile
- test/api/Makefile
- test/fuzzing/Makefile
- test/shaping/Makefile
- test/shaping/data/Makefile
- test/shaping/data/aots/Makefile
- test/shaping/data/in-house/Makefile
-@@ -520,17 +502,17 @@ echo "C++ compiler version:"
- $CXX --version
- echo
- 
- AC_MSG_NOTICE([
- 
- Build configuration:
- 
- Unicode callbacks (you want at least one):
--	Builtin (UCDN):		${have_ucdn}
-+	Builtin			true
- 	Glib:			${have_glib}
- 	ICU:			${have_icu}
- 
- Font callbacks (the more the merrier):
- 	FreeType:		${have_freetype}
- 
- Tools used for command-line utilities:
- 	Cairo:			${have_cairo}
-diff --git a/gfx/harfbuzz/src/Makefile.am b/gfx/harfbuzz/src/Makefile.am
---- a/gfx/harfbuzz/src/Makefile.am
-+++ b/gfx/harfbuzz/src/Makefile.am
-@@ -82,27 +82,16 @@ endif
- 
- if HAVE_CORETEXT
- HBCFLAGS += $(CORETEXT_CFLAGS)
- HBNONPCLIBS += $(CORETEXT_LIBS)
- HBSOURCES += $(HB_CORETEXT_sources)
- HBHEADERS += $(HB_CORETEXT_headers)
- endif
- 
--if HAVE_UCDN
--SUBDIRS += hb-ucdn
--HBCFLAGS += -I$(srcdir)/hb-ucdn
--HBLIBS   += hb-ucdn/libhb-ucdn.la
--HBSOURCES += $(HB_UCDN_sources)
--hb-ucdn/libhb-ucdn.la: ucdn
--ucdn:
--	@$(MAKE) $(AM_MAKEFLAGS) -C hb-ucdn
--endif
--DIST_SUBDIRS += hb-ucdn
--
- 
- BUILT_SOURCES += \
- 	hb-version.h
- 
- $(srcdir)/hb-version.h: hb-version.h.in $(top_srcdir)/configure.ac
- 	$(AM_V_GEN) $(SED) \
- 		-e 's/[@]HB_VERSION_MAJOR@/$(HB_VERSION_MAJOR)/' \
- 		-e 's/[@]HB_VERSION_MINOR@/$(HB_VERSION_MINOR)/' \
-@@ -253,16 +242,17 @@ harfbuzz-deprecated-symbols.txt: $(srcdi
- 
- GENERATORS = \
- 	gen-arabic-table.py \
- 	gen-def.py \
- 	gen-emoji-table.py \
- 	gen-indic-table.py \
- 	gen-os2-unicode-ranges.py \
- 	gen-tag-table.py \
-+	gen-ucd-table.py \
- 	gen-use-table.py \
- 	gen-vowel-constraints.py \
- 	$(NULL)
- EXTRA_DIST += $(GENERATORS)
- 
- unicode-tables: arabic-table indic-table tag-table use-table emoji-table
- 
- arabic-table: gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
-@@ -305,45 +295,45 @@ EXTRA_DIST += \
- $(srcdir)/%.hh: $(srcdir)/%.rl
- 	$(AM_V_GEN)(cd $(srcdir) && $(RAGEL) -e -F1 -o "$*.hh" "$*.rl") \
- 	|| ($(RM) "$@"; false)
- 
- noinst_PROGRAMS = \
- 	main \
- 	test \
- 	test-buffer-serialize \
--	test-name-table \
--	test-size-params \
--	test-would-substitute \
-+	test-ot-name \
-+	test-gpos-size-params \
-+	test-gsub-would-substitute \
- 	$(NULL)
- bin_PROGRAMS =
- 
- main_SOURCES = main.cc
- main_CPPFLAGS = $(HBCFLAGS)
- main_LDADD = libharfbuzz.la $(HBLIBS)
- 
- test_SOURCES = test.cc
- test_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
- test_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
- 
- test_buffer_serialize_SOURCES = test-buffer-serialize.cc
- test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
- test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
- 
--test_name_table_SOURCES = test-name-table.cc
--test_name_table_CPPFLAGS = $(HBCFLAGS)
--test_name_table_LDADD = libharfbuzz.la $(HBLIBS)
-+test_ot_name_SOURCES = test-ot-name.cc
-+test_ot_name_CPPFLAGS = $(HBCFLAGS)
-+test_ot_name_LDADD = libharfbuzz.la $(HBLIBS)
- 
--test_size_params_SOURCES = test-size-params.cc
--test_size_params_CPPFLAGS = $(HBCFLAGS)
--test_size_params_LDADD = libharfbuzz.la $(HBLIBS)
-+test_gpos_size_params_SOURCES = test-gpos-size-params.cc
-+test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
-+test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
- 
--test_would_substitute_SOURCES = test-would-substitute.cc
--test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
--test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
-+test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
-+test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
-+test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
- 
- if HAVE_FREETYPE
- if HAVE_CAIRO_FT
- noinst_PROGRAMS += test-ot-color
- test_ot_color_SOURCES = test-ot-color.cc
- test_ot_color_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
- test_ot_color_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
- endif # HAVE_CAIRO_FT
-@@ -379,26 +369,34 @@ dump_khmer_data_CPPFLAGS = $(HBCFLAGS)
- dump_khmer_data_LDADD = libharfbuzz.la $(HBLIBS)
- dump_myanmar_data_SOURCES = dump-myanmar-data.cc hb-ot-shape-complex-indic-table.cc
- dump_myanmar_data_CPPFLAGS = $(HBCFLAGS)
- dump_myanmar_data_LDADD = libharfbuzz.la $(HBLIBS)
- dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
- dump_use_data_CPPFLAGS = $(HBCFLAGS)
- dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
- 
--COMPILED_TESTS = test-iter test-ot-tag test-unicode-ranges
-+COMPILED_TESTS = test-algs test-iter test-meta test-ot-tag test-unicode-ranges
- COMPILED_TESTS_CPPFLAGS = $(HBCFLAGS) -DMAIN -UNDEBUG
- COMPILED_TESTS_LDADD = libharfbuzz.la $(HBLIBS)
- check_PROGRAMS += $(COMPILED_TESTS)
- TESTS += $(COMPILED_TESTS)
- 
-+test_algs_SOURCES = test-algs.cc hb-static.cc
-+test_algs_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
-+test_algs_LDADD = $(COMPILED_TESTS_LDADD)
-+
- test_iter_SOURCES = test-iter.cc hb-static.cc
- test_iter_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
- test_iter_LDADD = $(COMPILED_TESTS_LDADD)
- 
-+test_meta_SOURCES = test-meta.cc hb-static.cc
-+test_meta_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
-+test_meta_LDADD = $(COMPILED_TESTS_LDADD)
-+
- test_ot_tag_SOURCES = hb-ot-tag.cc
- test_ot_tag_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
- test_ot_tag_LDADD = $(COMPILED_TESTS_LDADD)
- 
- test_unicode_ranges_SOURCES = test-unicode-ranges.cc
- test_unicode_ranges_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
- test_unicode_ranges_LDADD = $(COMPILED_TESTS_LDADD)
- 
-diff --git a/gfx/harfbuzz/src/Makefile.sources b/gfx/harfbuzz/src/Makefile.sources
---- a/gfx/harfbuzz/src/Makefile.sources
-+++ b/gfx/harfbuzz/src/Makefile.sources
-@@ -11,41 +11,44 @@ HB_BASE_sources = \
- 	hb-aat-layout-lcar-table.hh \
- 	hb-aat-layout-morx-table.hh \
- 	hb-aat-layout-trak-table.hh \
- 	hb-aat-layout.cc \
- 	hb-aat-layout.hh \
- 	hb-aat-ltag-table.hh \
- 	hb-aat-map.cc \
- 	hb-aat-map.hh \
-+	hb-algs.hh \
- 	hb-array.hh \
- 	hb-atomic.hh \
- 	hb-blob.cc \
- 	hb-blob.hh \
- 	hb-buffer-serialize.cc \
- 	hb-buffer.cc \
- 	hb-buffer.hh \
- 	hb-cache.hh \
- 	hb-cff-interp-common.hh \
- 	hb-cff-interp-cs-common.hh \
- 	hb-cff-interp-dict-common.hh \
- 	hb-cff1-interp-cs.hh \
- 	hb-cff2-interp-cs.hh \
- 	hb-common.cc \
-+	hb-config.hh \
- 	hb-debug.hh \
--	hb-dsalgs.hh \
-+	hb-dispatch.hh \
- 	hb-face.cc \
- 	hb-face.hh \
- 	hb-font.cc \
- 	hb-font.hh \
- 	hb-iter.hh \
- 	hb-kern.hh \
- 	hb-machinery.hh \
- 	hb-map.cc \
- 	hb-map.hh \
-+	hb-meta.hh \
- 	hb-mutex.hh \
- 	hb-null.hh \
- 	hb-object.hh \
- 	hb-open-file.hh \
- 	hb-open-type.hh \
- 	hb-ot-cff-common.hh \
- 	hb-ot-cff1-table.cc \
- 	hb-ot-cff1-table.hh \
-@@ -77,17 +80,17 @@ HB_BASE_sources = \
- 	hb-ot-layout-jstf-table.hh \
- 	hb-ot-layout.cc \
- 	hb-ot-layout.hh \
- 	hb-ot-map.cc \
- 	hb-ot-map.hh \
- 	hb-ot-math-table.hh \
- 	hb-ot-math.cc \
- 	hb-ot-maxp-table.hh \
--	hb-ot-name-language.cc \
-+	hb-ot-name-language-static.hh \
- 	hb-ot-name-language.hh \
- 	hb-ot-name-table.hh \
- 	hb-ot-name.cc \
- 	hb-ot-os2-table.hh \
- 	hb-ot-os2-unicode-ranges.hh \
- 	hb-ot-post-macroman.hh \
- 	hb-ot-post-table.hh \
- 	hb-ot-shape-complex-arabic-fallback.hh \
-@@ -122,28 +125,33 @@ HB_BASE_sources = \
- 	hb-ot-tag-table.hh \
- 	hb-ot-tag.cc \
- 	hb-ot-var-avar-table.hh \
- 	hb-ot-var-fvar-table.hh \
- 	hb-ot-var-hvar-table.hh \
- 	hb-ot-var-mvar-table.hh \
- 	hb-ot-var.cc \
- 	hb-ot-vorg-table.hh \
-+	hb-pool.hh \
-+	hb-sanitize.hh \
-+	hb-serialize.hh \
- 	hb-set-digest.hh \
- 	hb-set.cc \
- 	hb-set.hh \
- 	hb-shape-plan.cc \
- 	hb-shape-plan.hh \
- 	hb-shape.cc \
- 	hb-shaper-impl.hh \
- 	hb-shaper-list.hh \
- 	hb-shaper.cc \
- 	hb-shaper.hh \
- 	hb-static.cc \
- 	hb-string-array.hh \
-+	hb-ucd-table.hh \
-+	hb-ucd.cc \
- 	hb-unicode-emoji-table.hh \
- 	hb-unicode.cc \
- 	hb-unicode.hh \
- 	hb-utf.hh \
- 	hb-vector.hh \
- 	hb-warning.cc \
- 	hb.hh \
- 	$(NULL)
-@@ -213,37 +221,31 @@ HB_CORETEXT_sources = hb-coretext.cc
- HB_CORETEXT_headers = hb-coretext.h
- 
- HB_DIRECTWRITE_sources = hb-directwrite.cc
- HB_DIRECTWRITE_headers = hb-directwrite.h
- 
- HB_UNISCRIBE_sources = hb-uniscribe.cc
- HB_UNISCRIBE_headers = hb-uniscribe.h
- 
--# Additional supplemental sources
--HB_UCDN_sources  = hb-ucdn.cc
--
- # Sources for libharfbuzz-gobject and libharfbuzz-icu
- HB_ICU_sources = hb-icu.cc
- HB_ICU_headers = hb-icu.h
- 
- # Sources for libharfbuzz-subset
- HB_SUBSET_sources = \
- 	hb-ot-cff1-table.cc \
- 	hb-ot-cff2-table.cc \
- 	hb-static.cc \
- 	hb-subset-cff-common.cc \
- 	hb-subset-cff-common.hh \
- 	hb-subset-cff1.cc \
- 	hb-subset-cff1.hh \
- 	hb-subset-cff2.cc \
- 	hb-subset-cff2.hh \
--	hb-subset-glyf.cc \
--	hb-subset-glyf.hh \
--	hb-subset-glyf.hh \
- 	hb-subset-input.cc \
- 	hb-subset-input.hh \
- 	hb-subset-plan.cc \
- 	hb-subset-plan.hh \
- 	hb-subset-plan.hh \
- 	hb-subset.cc \
- 	hb-subset.hh \
- 	hb-subset.hh \
-diff --git a/gfx/harfbuzz/src/check-symbols.sh b/gfx/harfbuzz/src/check-symbols.sh
---- a/gfx/harfbuzz/src/check-symbols.sh
-+++ b/gfx/harfbuzz/src/check-symbols.sh
-@@ -2,17 +2,17 @@
- 
- LC_ALL=C
- export LC_ALL
- 
- test -z "$srcdir" && srcdir=.
- test -z "$libs" && libs=.libs
- stat=0
- 
--IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_flush\|llvm_.*'
-+IGNORED_SYMBOLS='_fini\|_init\|_fdata\|_ftext\|_fbss\|__bss_start\|__bss_start__\|__bss_end__\|_edata\|_end\|_bss_end__\|__end__\|__gcov_.*\|llvm_.*'
- 
- if which nm 2>/dev/null >/dev/null; then
- 	:
- else
- 	echo "check-symbols.sh: 'nm' not found; skipping test"
- 	exit 77
- fi
- 
-diff --git a/gfx/harfbuzz/src/gen-os2-unicode-ranges.py b/gfx/harfbuzz/src/gen-os2-unicode-ranges.py
-old mode 100644
-new mode 100755
---- a/gfx/harfbuzz/src/gen-os2-unicode-ranges.py
-+++ b/gfx/harfbuzz/src/gen-os2-unicode-ranges.py
-@@ -1,13 +1,15 @@
-+#!/usr/bin/python
-+
- # -*- coding: utf-8 -*-
- 
- # Generates the code for a sorted unicode range array as used in hb-ot-os2-unicode-ranges.hh
- # Input is a tab seperated list of unicode ranges from the otspec
--# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ulunicoderange1).
-+# (https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur).
- 
- from __future__ import print_function, division, absolute_import
- 
- import io
- import re
- import sys
- 
- try:
-diff --git a/gfx/harfbuzz/src/gen-tag-table.py b/gfx/harfbuzz/src/gen-tag-table.py
---- a/gfx/harfbuzz/src/gen-tag-table.py
-+++ b/gfx/harfbuzz/src/gen-tag-table.py
-@@ -890,46 +890,42 @@ def language_name_intersection (a, b):
- 	Returns:
- 		The normalized language names shared by ``a`` and ``b``.
- 	"""
- 	return get_variant_set (a).intersection (get_variant_set (b))
- 
- def get_matching_language_name (intersection, candidates):
- 	return next (iter (c for c in candidates if not intersection.isdisjoint (get_variant_set (c))))
- 
--maximum_tags = 0
-+def same_tag (bcp_47_tag, ot_tags):
-+	return len (bcp_47_tag) == 3 and len (ot_tags) == 1 and bcp_47_tag == ot_tags[0].lower ()
-+
- for language, tags in sorted (ot.from_bcp_47.items ()):
- 	if language == '' or '-' in language:
- 		continue
--	print ('  {\"%s\",\t{' % language, end='')
--	maximum_tags = max (maximum_tags, len (tags))
--	tag_count = len (tags)
-+	commented_out = same_tag (language, tags)
- 	for i, tag in enumerate (tags, start=1):
--		if i > 1:
--			print ('\t\t ', end='')
--		print (hb_tag (tag), end='')
--		if i == tag_count:
--			print ('}}', end='')
--		print (',\t/* ', end='')
-+		print ('%s{\"%s\",\t%s},' % ('/*' if commented_out else '  ', language, hb_tag (tag)), end='')
-+		if commented_out:
-+			print ('*/', end='')
-+		print ('\t/* ', end='')
- 		bcp_47_name = bcp_47.names.get (language, '')
- 		bcp_47_name_candidates = bcp_47_name.split ('\n')
- 		intersection = language_name_intersection (bcp_47_name, ot.names[tag])
- 		scope = bcp_47.scopes.get (language, '')
- 		if not intersection:
- 			write ('%s%s -> %s' % (bcp_47_name_candidates[0], scope, ot.names[tag]))
- 		else:
- 			name = get_matching_language_name (intersection, bcp_47_name_candidates)
- 			bcp_47.names[language] = name
- 			write ('%s%s' % (name if len (name) > len (ot.names[tag]) else ot.names[tag], scope))
- 		print (' */')
- 
- print ('};')
- print ()
--print ('static_assert (HB_OT_MAX_TAGS_PER_LANGUAGE == %iu, "");' % maximum_tags)
--print ()
- 
- print ('/**')
- print (' * hb_ot_tags_from_complex_language:')
- print (' * @lang_str: a BCP 47 language tag to convert.')
- print (' * @limit: a pointer to the end of the substring of @lang_str to consider for')
- print (' * conversion.')
- print (' * @count: maximum number of language tags to retrieve (IN) and actual number of')
- print (' * language tags retrieved (OUT). If no tags are retrieved, it is not modified.')
-@@ -1046,17 +1042,18 @@ print ('  return false;')
- print ('}')
- print ()
- print ('/**')
- print (' * hb_ot_ambiguous_tag_to_language')
- print (' * @tag: A language tag.')
- print (' *')
- print (' * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to')
- print (' * many language tags) and the best tag is not the alphabetically first, or if')
--print (' * the best tag consists of multiple subtags.')
-+print (' * the best tag consists of multiple subtags, or if the best tag does not appear')
-+print (' * in #ot_languages.')
- print (' *')
- print (' * Return value: The #hb_language_t corresponding to the BCP 47 language tag,')
- print (' * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.')
- print (' **/')
- print ('static hb_language_t')
- print ('hb_ot_ambiguous_tag_to_language (hb_tag_t tag)')
- print ('{')
- print ('  switch (tag)')
-@@ -1097,17 +1094,18 @@ def verify_disambiguation_dict ():
- 			if len (macrolanguages) != 1:
- 				macrolanguages = list (t for t in primary_tags if 'retired code' not in bcp_47.scopes.get (t, ''))
- 			if len (macrolanguages) != 1:
- 				expect (ot_tag in disambiguation, 'ambiguous OT tag: %s %s' % (ot_tag, str (macrolanguages)))
- 				expect (disambiguation[ot_tag] in bcp_47_tags,
- 						'%s is not a valid disambiguation for %s' % (disambiguation[ot_tag], ot_tag))
- 			elif ot_tag not in disambiguation:
- 				disambiguation[ot_tag] = macrolanguages[0]
--			if disambiguation[ot_tag] == sorted (primary_tags)[0] and '-' not in disambiguation[ot_tag]:
-+			different_primary_tags = sorted (t for t in primary_tags if not same_tag (t, ot.from_bcp_47.get (t)))
-+			if different_primary_tags and disambiguation[ot_tag] == different_primary_tags[0] and '-' not in disambiguation[ot_tag]:
- 				del disambiguation[ot_tag]
- 	for ot_tag in disambiguation.keys ():
- 		expect (ot_tag in ot.to_bcp_47, 'unknown OT tag: %s' % ot_tag)
- 
- verify_disambiguation_dict ()
- for ot_tag, bcp_47_tag in sorted (disambiguation.items ()):
- 	write ('  case %s:  /* %s */' % (hb_tag (ot_tag), ot.names[ot_tag]))
- 	print ()
-diff --git a/gfx/harfbuzz/src/gen-ucd-table.py b/gfx/harfbuzz/src/gen-ucd-table.py
-new file mode 100755
---- /dev/null
-+++ b/gfx/harfbuzz/src/gen-ucd-table.py
-@@ -0,0 +1,123 @@
-+#!/usr/bin/env python
-+
-+from __future__ import print_function, division, absolute_import
-+
-+import io, os.path, sys, re
-+
-+if len (sys.argv) != 2:
-+	print("usage: ./gen-ucd-table ucd.nonunihan.grouped.xml", file=sys.stderr)
-+	sys.exit(1)
-+
-+
-+# https://github.com/harfbuzz/packtab
-+import packTab
-+import packTab.ucdxml
-+
-+ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1])
-+ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml)
-+
-+
-+gc = [u['gc'] for u in ucd]
-+ccc = [int(u['ccc']) for u in ucd]
-+bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
-+#gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass)
-+#gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr)
-+
-+sc = [u['sc'] for u in ucd]
-+
-+dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd)
-+      if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)}
-+ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
-+
-+assert not any(v for v in dm.values() if len(v) not in (1,2))
-+dm1 = sorted(set(v for v in dm.values() if len(v) == 1))
-+dm1_array = ['0x%04Xu' % v for v in dm1]
-+dm1_order = {v:i+1 for i,v in enumerate(dm1)}
-+dm2 = sorted((v, i) for i,v in dm.items() if len(v) == 2)
-+dm2 = [("HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" %
-+        (v+(i if i not in ce and not ccc[i] else 0,)), v)
-+       for v,i in dm2]
-+dm2_array = [s for s,v in dm2]
-+l = 1 + len(dm1_array)
-+dm2_order = {v[1]:i+l for i,v in enumerate(dm2)}
-+dm_order = {None: 0}
-+dm_order.update(dm1_order)
-+dm_order.update(dm2_order)
-+
-+gc_order = packTab.AutoMapping()
-+for _ in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
-+          'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
-+          'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',):
-+    gc_order[_]
-+
-+sc_order = packTab.AutoMapping()
-+sc_array = []
-+sc_re = re.compile(" (HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
-+for line in open('hb-common.h'):
-+    m = sc_re.search (line)
-+    if not m: continue
-+    name = m.group(1)
-+    tag = ''.join(m.group(i) for i in range(2, 6))
-+    i = sc_order[tag]
-+    assert i == len(sc_array)
-+    sc_array.append(name)
-+
-+# TODO Currently if gc_order or sc_order do not capture all values, we get in
-+# trouble because they silently add new values.  We should be able to "freeze"
-+# them, or just do the mapping ourselves.
-+
-+DEFAULT = 1
-+COMPACT = 3
-+
-+
-+print("/* == Start of generated table == */")
-+print("/*")
-+print(" * The following table is generated by running:")
-+print(" *")
-+print(" *   ./gen-ucd-table.py ucd.nonunihan.grouped.xml")
-+print(" *")
-+print(" * on file with this description:", ucdxml.description)
-+print(" */")
-+print()
-+print("#ifndef HB_UCD_TABLE_HH")
-+print("#define HB_UCD_TABLE_HH")
-+print()
-+
-+print()
-+print('#include "hb.hh"')
-+print()
-+
-+code = packTab.Code('_hb_ucd')
-+sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
-+dm1_array, _ = code.addArray('hb_codepoint_t', 'dm1_map', dm1_array)
-+dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array)
-+code.print_c(linkage='static inline')
-+
-+for compression in (DEFAULT, COMPACT):
-+    print()
-+    if compression == DEFAULT:
-+        print('#ifndef HB_OPTIMIZE_SIZE')
-+    else:
-+        print('#else')
-+    print()
-+
-+    code = packTab.Code('_hb_ucd')
-+
-+    packTab.pack_table(gc, 'Cn', mapping=gc_order, compression=compression).genCode(code, 'gc')
-+    packTab.pack_table(ccc, 0, compression=compression).genCode(code, 'ccc')
-+    packTab.pack_table(bmg, 0, compression=compression).genCode(code, 'bmg')
-+    packTab.pack_table(sc, 'Zzzz', mapping=sc_order, compression=compression).genCode(code, 'sc')
-+    packTab.pack_table(dm, None, mapping=dm_order, compression=compression).genCode(code, 'dm')
-+
-+    code.print_c(linkage='static inline')
-+
-+
-+    if compression != DEFAULT:
-+        print()
-+        print('#endif')
-+    print()
-+
-+print()
-+print("#endif /* HB_UCD_TABLE_HH */")
-+print()
-+print("/* == End of generated table == */")
-diff --git a/gfx/harfbuzz/src/gen-use-table.py b/gfx/harfbuzz/src/gen-use-table.py
---- a/gfx/harfbuzz/src/gen-use-table.py
-+++ b/gfx/harfbuzz/src/gen-use-table.py
-@@ -42,18 +42,32 @@ for i, f in enumerate (files):
- 		for u in range (start, end + 1):
- 			data[i][u] = t
- 		values[i][t] = values[i].get (t, 0) + end - start + 1
- 
- defaults = ('Other', 'Not_Applicable', 'Cn', 'No_Block')
- 
- # TODO Characters that are not in Unicode Indic files, but used in USE
- data[0][0x034F] = defaults[0]
-+data[0][0x1B61] = defaults[0]
-+data[0][0x1B63] = defaults[0]
-+data[0][0x1B64] = defaults[0]
-+data[0][0x1B65] = defaults[0]
-+data[0][0x1B66] = defaults[0]
-+data[0][0x1B67] = defaults[0]
-+data[0][0x1B69] = defaults[0]
-+data[0][0x1B6A] = defaults[0]
- data[0][0x2060] = defaults[0]
--# TODO https://github.com/roozbehp/unicode-data/issues/9
-+# TODO https://github.com/harfbuzz/harfbuzz/pull/1685
-+data[0][0x1B5B] = 'Consonant_Placeholder'
-+data[0][0x1B5C] = 'Consonant_Placeholder'
-+data[0][0x1B5F] = 'Consonant_Placeholder'
-+data[0][0x1B62] = 'Consonant_Placeholder'
-+data[0][0x1B68] = 'Consonant_Placeholder'
-+# TODO https://github.com/harfbuzz/harfbuzz/issues/1035
- data[0][0x11C44] = 'Consonant_Placeholder'
- data[0][0x11C45] = 'Consonant_Placeholder'
- # TODO https://github.com/harfbuzz/harfbuzz/pull/1399
- data[0][0x111C8] = 'Consonant_Placeholder'
- for u in range (0xFE00, 0xFE0F + 1):
- 	data[0][u] = defaults[0]
- 
- # Merge data into one dict:
-@@ -166,84 +180,89 @@ def is_BASE(U, UISC, UGC):
- 			Tone_Letter,
- 			Vowel_Independent #SPEC-DRAFT
- 			] or
- 		(UGC == Lo and UISC in [Avagraha, Bindu, Consonant_Final, Consonant_Medial,
- 					Consonant_Subjoined, Vowel, Vowel_Dependent]))
- def is_BASE_IND(U, UISC, UGC):
- 	#SPEC-DRAFT return (UISC in [Consonant_Dead, Modifying_Letter] or UGC == Po)
- 	return (UISC in [Consonant_Dead, Modifying_Letter] or
--		(UGC == Po and not U in [0x104B, 0x104E, 0x2022, 0x111C8, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
-+		(UGC == Po and not U in [0x104B, 0x104E, 0x1B5B, 0x1B5C, 0x1B5F, 0x2022, 0x111C8, 0x11A3F, 0x11A45, 0x11C44, 0x11C45]) or
- 		False # SPEC-DRAFT-OUTDATED! U == 0x002D
- 		)
- def is_BASE_NUM(U, UISC, UGC):
- 	return UISC == Brahmi_Joining_Number
- def is_BASE_OTHER(U, UISC, UGC):
- 	if UISC == Consonant_Placeholder: return True #SPEC-DRAFT
- 	#SPEC-DRAFT return U in [0x00A0, 0x00D7, 0x2015, 0x2022, 0x25CC, 0x25FB, 0x25FC, 0x25FD, 0x25FE]
- 	return U in [0x2015, 0x2022, 0x25FB, 0x25FC, 0x25FD, 0x25FE]
- def is_CGJ(U, UISC, UGC):
- 	return U == 0x034F
- def is_CONS_FINAL(U, UISC, UGC):
--	# Consonant_Initial_Postfixed is new in Unicode 11; not in the spec.
- 	return ((UISC == Consonant_Final and UGC != Lo) or
--		UISC == Consonant_Initial_Postfixed or
- 		UISC == Consonant_Succeeding_Repha)
- def is_CONS_FINAL_MOD(U, UISC, UGC):
- 	#SPEC-DRAFT return  UISC in [Consonant_Final_Modifier, Syllable_Modifier]
- 	return  UISC == Syllable_Modifier
- def is_CONS_MED(U, UISC, UGC):
--	return UISC == Consonant_Medial and UGC != Lo
-+	# Consonant_Initial_Postfixed is new in Unicode 11; not in the spec.
-+	return (UISC == Consonant_Medial and UGC != Lo or
-+		UISC == Consonant_Initial_Postfixed)
- def is_CONS_MOD(U, UISC, UGC):
- 	return UISC in [Nukta, Gemination_Mark, Consonant_Killer]
- def is_CONS_SUB(U, UISC, UGC):
- 	#SPEC-DRAFT return UISC == Consonant_Subjoined
- 	return UISC == Consonant_Subjoined and UGC != Lo
- def is_CONS_WITH_STACKER(U, UISC, UGC):
- 	return UISC == Consonant_With_Stacker
- def is_HALANT(U, UISC, UGC):
--	return UISC in [Virama, Invisible_Stacker] and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC)
-+	return (UISC in [Virama, Invisible_Stacker]
-+		and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC)
-+		and not is_SAKOT(U, UISC, UGC))
- def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC):
- 	# https://github.com/harfbuzz/harfbuzz/issues/1102
- 	# https://github.com/harfbuzz/harfbuzz/issues/1379
- 	return U in [0x11046, 0x1134D]
- def is_HALANT_NUM(U, UISC, UGC):
- 	return UISC == Number_Joiner
- def is_ZWNJ(U, UISC, UGC):
- 	return UISC == Non_Joiner
- def is_ZWJ(U, UISC, UGC):
- 	return UISC == Joiner
- def is_Word_Joiner(U, UISC, UGC):
- 	return U == 0x2060
- def is_OTHER(U, UISC, UGC):
- 	#SPEC-OUTDATED return UGC == Zs # or any other SCRIPT_COMMON characters
- 	return (UISC == Other
-+		and not is_SYM(U, UISC, UGC)
- 		and not is_SYM_MOD(U, UISC, UGC)
- 		and not is_CGJ(U, UISC, UGC)
- 		and not is_Word_Joiner(U, UISC, UGC)
- 		and not is_VARIATION_SELECTOR(U, UISC, UGC)
- 	)
- def is_Reserved(U, UISC, UGC):
- 	return UGC == 'Cn'
- def is_REPHA(U, UISC, UGC):
- 	return UISC in [Consonant_Preceding_Repha, Consonant_Prefixed]
-+def is_SAKOT(U, UISC, UGC):
-+	return U == 0x1A60
- def is_SYM(U, UISC, UGC):
- 	if U == 0x25CC: return False #SPEC-DRAFT
- 	#SPEC-DRAFT return UGC in [So, Sc] or UISC == Symbol_Letter
--	return UGC in [So, Sc]
-+	return UGC in [So, Sc] and U not in [0x1B62, 0x1B68]
- def is_SYM_MOD(U, UISC, UGC):
- 	return U in [0x1B6B, 0x1B6C, 0x1B6D, 0x1B6E, 0x1B6F, 0x1B70, 0x1B71, 0x1B72, 0x1B73]
- def is_VARIATION_SELECTOR(U, UISC, UGC):
- 	return 0xFE00 <= U <= 0xFE0F
- def is_VOWEL(U, UISC, UGC):
--	# https://github.com/roozbehp/unicode-data/issues/6
-+	# https://github.com/harfbuzz/harfbuzz/issues/376
- 	return (UISC == Pure_Killer or
- 		(UGC != Lo and UISC in [Vowel, Vowel_Dependent] and U not in [0xAA29]))
- def is_VOWEL_MOD(U, UISC, UGC):
--	# https://github.com/roozbehp/unicode-data/issues/6
-+	# https://github.com/harfbuzz/harfbuzz/issues/376
- 	return (UISC in [Tone_Mark, Cantillation_Mark, Register_Shifter, Visarga] or
- 		(UGC != Lo and (UISC == Bindu or U in [0xAA29])))
- 
- use_mapping = {
- 	'B':	is_BASE,
- 	'IND':	is_BASE_IND,
- 	'N':	is_BASE_NUM,
- 	'GB':	is_BASE_OTHER,
-@@ -259,16 +278,17 @@ use_mapping = {
- 	'HN':	is_HALANT_NUM,
- 	'ZWNJ':	is_ZWNJ,
- 	'ZWJ':	is_ZWJ,
- 	'WJ':	is_Word_Joiner,
- 	'O':	is_OTHER,
- 	'Rsv':	is_Reserved,
- 	'R':	is_REPHA,
- 	'S':	is_SYM,
-+	'Sk':	is_SAKOT,
- 	'SM':	is_SYM_MOD,
- 	'VS':	is_VARIATION_SELECTOR,
- 	'V':	is_VOWEL,
- 	'VM':	is_VOWEL_MOD,
- }
- 
- use_positions = {
- 	'F': {
-@@ -300,17 +320,21 @@ use_positions = {
- 	},
- 	'SM': {
- 		'Abv': [Top],
- 		'Blw': [Bottom],
- 	},
- 	'H': None,
- 	'HVM': None,
- 	'B': None,
--	'FM': None,
-+	'FM': {
-+		'Abv': [Top],
-+		'Blw': [Bottom],
-+		'Pst': [Not_Applicable],
-+	},
- 	'SUB': None,
- }
- 
- def map_to_use(data):
- 	out = {}
- 	items = use_mapping.items()
- 	for U,(UISC,UIPC,UGC,UBlock) in data.items():
- 
-@@ -339,25 +363,19 @@ def map_to_use(data):
- 
- 		# TODO: https://github.com/harfbuzz/harfbuzz/pull/627
- 		if 0x1BF2 <= U <= 0x1BF3: UISC = Nukta; UIPC = Bottom
- 
- 		# TODO: U+1CED should only be allowed after some of
- 		# the nasalization marks, maybe only for U+1CE9..U+1CF1.
- 		if U == 0x1CED: UISC = Tone_Mark
- 
--		# TODO: https://github.com/harfbuzz/harfbuzz/issues/525
--		if U == 0x1A7F: UISC = Consonant_Final
--
- 		# TODO: https://github.com/harfbuzz/harfbuzz/issues/1105
- 		if U == 0x11134: UISC = Gemination_Mark
- 
--		# TODO: https://github.com/harfbuzz/harfbuzz/pull/1399
--		if U == 0x111C9: UISC = Consonant_Final
--
- 		values = [k for k,v in items if v(U,UISC,UGC)]
- 		assert len(values) == 1, "%s %s %s %s" % (hex(U), UISC, UGC, values)
- 		USE = values[0]
- 
- 		# Resolve Indic_Positional_Category
- 
- 		# TODO: These should die, but have UIPC in Unicode 12.0
- 		if U in [0x953, 0x954]: UIPC = Not_Applicable
-diff --git a/gfx/harfbuzz/src/gen-vowel-constraints.py b/gfx/harfbuzz/src/gen-vowel-constraints.py
---- a/gfx/harfbuzz/src/gen-vowel-constraints.py
-+++ b/gfx/harfbuzz/src/gen-vowel-constraints.py
-@@ -175,16 +175,19 @@ print ('  buffer->next_glyph ();')
- print ('}')
- print ()
- 
- print ('void')
- print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,')
- print ('\t\t\t\t       hb_buffer_t              *buffer,')
- print ('\t\t\t\t       hb_font_t                *font HB_UNUSED)')
- print ('{')
-+print ('#if defined(HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS)')
-+print ('  return;')
-+print ('#endif')
- print ('  if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)')
- print ('    return;')
- print ()
- print ('  /* UGLY UGLY UGLY business of adding dotted-circle in the middle of')
- print ('   * vowel-sequences that look like another vowel.  Data for each script')
- print ('   * collected from the USE script development spec.')
- print ('   *')
- print ('   * https://github.com/harfbuzz/harfbuzz/issues/1019')
-diff --git a/gfx/harfbuzz/src/hb-aat-layout-ankr-table.hh b/gfx/harfbuzz/src/hb-aat-layout-ankr-table.hh
---- a/gfx/harfbuzz/src/hb-aat-layout-ankr-table.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout-ankr-table.hh
-@@ -78,17 +78,17 @@ struct ankr
- 			  version == 0 &&
- 			  c->check_range (this, anchorData) &&
- 			  lookupTable.sanitize (c, this, &(this+anchorData))));
-   }
- 
-   protected:
-   HBUINT16	version; 	/* Version number (set to zero) */
-   HBUINT16	flags;		/* Flags (currently unused; set to zero) */
--  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors> > >
-+  LOffsetTo<Lookup<NNOffsetTo<GlyphAnchors>>>
- 		lookupTable;	/* Offset to the table's lookup table */
-   LNNOffsetTo<HBUINT8>
- 		anchorData;	/* Offset to the glyph data table */
- 
-   public:
-   DEFINE_SIZE_STATIC (12);
- };
- 
-diff --git a/gfx/harfbuzz/src/hb-aat-layout-common.hh b/gfx/harfbuzz/src/hb-aat-layout-common.hh
---- a/gfx/harfbuzz/src/hb-aat-layout-common.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout-common.hh
-@@ -120,17 +120,17 @@ struct LookupFormat2
-   bool sanitize (hb_sanitize_context_t *c, const void *base) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (segments.sanitize (c, base));
-   }
- 
-   protected:
-   HBUINT16	format;		/* Format identifier--format = 2 */
--  VarSizedBinSearchArrayOf<LookupSegmentSingle<T> >
-+  VarSizedBinSearchArrayOf<LookupSegmentSingle<T>>
- 		segments;	/* The actual segments. These must already be sorted,
- 				 * according to the first word in each one (the last
- 				 * glyph in each segment). */
-   public:
-   DEFINE_SIZE_ARRAY (8, segments);
- };
- 
- template <typename T>
-@@ -148,28 +148,28 @@ struct LookupSegmentArray
- 
-   bool sanitize (hb_sanitize_context_t *c, const void *base) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  first <= last &&
- 		  valuesZ.sanitize (c, base, last - first + 1));
-   }
--  template <typename T2>
--  bool sanitize (hb_sanitize_context_t *c, const void *base, T2 user_data) const
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  first <= last &&
--		  valuesZ.sanitize (c, base, last - first + 1, user_data));
-+		  valuesZ.sanitize (c, base, last - first + 1, hb_forward<Ts> (ds)...));
-   }
- 
-   GlyphID	last;		/* Last GlyphID in this segment */
-   GlyphID	first;		/* First GlyphID in this segment */
--  NNOffsetTo<UnsizedArrayOf<T> >
-+  NNOffsetTo<UnsizedArrayOf<T>>
- 		valuesZ;	/* A 16-bit offset from the start of
- 				 * the table to the data. */
-   public:
-   DEFINE_SIZE_STATIC (6);
- };
- 
- template <typename T>
- struct LookupFormat4
-@@ -191,17 +191,17 @@ struct LookupFormat4
-   bool sanitize (hb_sanitize_context_t *c, const void *base) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (segments.sanitize (c, this, base));
-   }
- 
-   protected:
-   HBUINT16	format;		/* Format identifier--format = 4 */
--  VarSizedBinSearchArrayOf<LookupSegmentArray<T> >
-+  VarSizedBinSearchArrayOf<LookupSegmentArray<T>>
- 		segments;	/* The actual segments. These must already be sorted,
- 				 * according to the first word in each one (the last
- 				 * glyph in each segment). */
-   public:
-   DEFINE_SIZE_ARRAY (8, segments);
- };
- 
- template <typename T>
-@@ -248,17 +248,17 @@ struct LookupFormat6
-   bool sanitize (hb_sanitize_context_t *c, const void *base) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (entries.sanitize (c, base));
-   }
- 
-   protected:
-   HBUINT16	format;		/* Format identifier--format = 6 */
--  VarSizedBinSearchArrayOf<LookupSingle<T> >
-+  VarSizedBinSearchArrayOf<LookupSingle<T>>
- 		entries;	/* The actual entries, sorted by glyph index. */
-   public:
-   DEFINE_SIZE_ARRAY (8, entries);
- };
- 
- template <typename T>
- struct LookupFormat8
- {
-@@ -414,17 +414,17 @@ struct Lookup
- };
- /* Lookup 0 has unbounded size (dependant on num_glyphs).  So we need to defined
-  * special NULL objects for Lookup<> objects, but since it's template our macros
-  * don't work.  So we have to hand-code them here.  UGLY. */
- } /* Close namespace. */
- /* Ugly hand-coded null objects for template Lookup<> :(. */
- extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
- template <typename T>
--struct Null<AAT::Lookup<T> > {
-+struct Null<AAT::Lookup<T>> {
-   static AAT::Lookup<T> const & get_null ()
-   { return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); }
- };
- namespace AAT {
- 
- enum { DELETED_GLYPH = 0xFFFF };
- 
- /*
-@@ -505,17 +505,17 @@ struct StateTable
-   }
- 
-   const Entry<Extra> *get_entries () const
-   { return (this+entryTable).arrayZ; }
- 
-   const Entry<Extra> &get_entry (int state, unsigned int klass) const
-   {
-     if (unlikely (klass >= nClasses))
--      klass = StateTable<Types, Entry<Extra> >::CLASS_OUT_OF_BOUNDS;
-+      klass = StateTable<Types, Entry<Extra>>::CLASS_OUT_OF_BOUNDS;
- 
-     const HBUSHORT *states = (this+stateArrayTable).arrayZ;
-     const Entry<Extra> *entries = (this+entryTable).arrayZ;
- 
-     unsigned int entry = states[state * nClasses + klass];
-     DEBUG_MSG (APPLY, nullptr, "e%u", entry);
- 
-     return entries[entry];
-@@ -571,17 +571,17 @@ struct StateTable
- 	  return_trace (false);
- 	if ((c->max_ops -= state_neg - min_state) <= 0)
- 	  return_trace (false);
- 	{ /* Sweep new states. */
- 	  const HBUSHORT *stop = &states[min_state * num_classes];
- 	  if (unlikely (stop > states))
- 	    return_trace (false);
- 	  for (const HBUSHORT *p = states; stop < p; p--)
--	    num_entries = MAX<unsigned int> (num_entries, *(p - 1) + 1);
-+	    num_entries = hb_max (num_entries, *(p - 1) + 1);
- 	  state_neg = min_state;
- 	}
-       }
- 
-       if (state_pos <= max_state)
-       {
- 	/* Positive states. */
- 	if (unlikely (!c->check_range (states,
-@@ -592,32 +592,32 @@ struct StateTable
- 	  return_trace (false);
- 	{ /* Sweep new states. */
- 	  if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
- 	    return_trace (false);
- 	  const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
- 	  if (unlikely (stop < states))
- 	    return_trace (false);
- 	  for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
--	    num_entries = MAX<unsigned int> (num_entries, *p + 1);
-+	    num_entries = hb_max (num_entries, *p + 1);
- 	  state_pos = max_state + 1;
- 	}
-       }
- 
-       if (unlikely (!c->check_array (entries, num_entries)))
- 	return_trace (false);
-       if ((c->max_ops -= num_entries - entry) <= 0)
- 	return_trace (false);
-       { /* Sweep new entries. */
- 	const Entry<Extra> *stop = &entries[num_entries];
- 	for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
- 	{
- 	  int newState = new_state (p->newState);
--	  min_state = MIN (min_state, newState);
--	  max_state = MAX (max_state, newState);
-+	  min_state = hb_min (min_state, newState);
-+	  max_state = hb_max (max_state, newState);
- 	}
- 	entry = num_entries;
-       }
-     }
- 
-     if (num_entries_out)
-       *num_entries_out = num_entries;
- 
-@@ -626,17 +626,17 @@ struct StateTable
- 
-   protected:
-   HBUINT	nClasses;	/* Number of classes, which is the number of indices
- 				 * in a single line in the state array. */
-   NNOffsetTo<ClassType, HBUINT>
- 		classTable;	/* Offset to the class table. */
-   NNOffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
- 		stateArrayTable;/* Offset to the state array. */
--  NNOffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT>
-+  NNOffsetTo<UnsizedArrayOf<Entry<Extra>>, HBUINT>
- 		entryTable;	/* Offset to the entry array. */
- 
-   public:
-   DEFINE_SIZE_STATIC (4 * sizeof (HBUINT));
- };
- 
- template <typename HBUCHAR>
- struct ClassTable
-diff --git a/gfx/harfbuzz/src/hb-aat-layout-feat-table.hh b/gfx/harfbuzz/src/hb-aat-layout-feat-table.hh
---- a/gfx/harfbuzz/src/hb-aat-layout-feat-table.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout-feat-table.hh
-@@ -160,17 +160,17 @@ struct feat
- 
-   unsigned int get_feature_types (unsigned int                  start_offset,
- 				  unsigned int                 *count,
- 				  hb_aat_layout_feature_type_t *features) const
-   {
-     unsigned int feature_count = featureNameCount;
-     if (count && *count)
-     {
--      unsigned int len = MIN (feature_count - start_offset, *count);
-+      unsigned int len = hb_min (feature_count - start_offset, *count);
-       for (unsigned int i = 0; i < len; i++)
- 	features[i] = namesZ[i + start_offset].get_feature_type ();
-       *count = len;
-     }
-     return featureNameCount;
-   }
- 
-   const FeatureName& get_feature (hb_aat_layout_feature_type_t feature_type) const
-diff --git a/gfx/harfbuzz/src/hb-aat-layout-just-table.hh b/gfx/harfbuzz/src/hb-aat-layout-just-table.hh
---- a/gfx/harfbuzz/src/hb-aat-layout-just-table.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout-just-table.hh
-@@ -304,17 +304,17 @@ struct WidthDeltaPair
- 				 * used as padding to guarantee longword
- 				 * alignment of the following record). */
-   JustWidthDeltaEntry
- 		wdRecord;	/* The actual width delta record. */
- 
-   public:
-   DEFINE_SIZE_STATIC (24);
- };
--  
-+
- typedef OT::LArrayOf<WidthDeltaPair> WidthDeltaCluster;
- 
- struct JustificationCategory
- {
-   typedef void EntryData;
- 
-   enum Flags
-   {
-@@ -366,17 +366,17 @@ struct JustificationHeader
- 				 * for the glyphs in your font.
- 				 *
- 				 * The width delta clusters table. */
-   OffsetTo<PostcompensationActionChain>
- 		pcTable;	/* Offset from start of justification table to start
- 				 * of postcompensation subtable (set to zero if none).
- 				 *
- 				 * The postcompensation subtable, if present in the font. */
--  Lookup<OffsetTo<WidthDeltaCluster> >
-+  Lookup<OffsetTo<WidthDeltaCluster>>
-   		lookupTable;	/* Lookup table associating glyphs with width delta
- 				 * clusters. See the description of Width Delta Clusters
- 				 * table for details on how to interpret the lookup values. */
- 
-   public:
-   DEFINE_SIZE_MIN (8);
- };
- 
-diff --git a/gfx/harfbuzz/src/hb-aat-layout-kerx-table.hh b/gfx/harfbuzz/src/hb-aat-layout-kerx-table.hh
---- a/gfx/harfbuzz/src/hb-aat-layout-kerx-table.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout-kerx-table.hh
-@@ -246,17 +246,17 @@ struct KerxSubTableFormat1
- 	if (likely (depth < ARRAY_LENGTH (stack)))
- 	  stack[depth++] = buffer->idx;
- 	else
- 	  depth = 0; /* Probably not what CoreText does, but better? */
-       }
- 
-       if (Format1EntryT::performAction (entry) && depth)
-       {
--	unsigned int tuple_count = MAX (1u, table->header.tuple_count ());
-+	unsigned int tuple_count = hb_max (1u, table->header.tuple_count ());
- 
- 	unsigned int kern_idx = Format1EntryT::kernActionIndex (entry);
- 	kern_idx = Types::byteOffsetToIndex (kern_idx, &table->machine, kernAction.arrayZ);
- 	const FWORD *actions = &kernAction[kern_idx];
- 	if (!c->sanitizer.check_array (actions, depth, tuple_count))
- 	{
- 	  depth = 0;
- 	  return;
-@@ -707,28 +707,28 @@ struct KerxSubTableFormat6
-   KernSubTableHeader		header;
-   HBUINT32			flags;
-   HBUINT16			rowCount;
-   HBUINT16			columnCount;
-   union U
-   {
-     struct Long
-     {
--      LNNOffsetTo<Lookup<HBUINT32> >		rowIndexTable;
--      LNNOffsetTo<Lookup<HBUINT32> >		columnIndexTable;
--      LNNOffsetTo<UnsizedArrayOf<FWORD32> >	array;
-+      LNNOffsetTo<Lookup<HBUINT32>>		rowIndexTable;
-+      LNNOffsetTo<Lookup<HBUINT32>>		columnIndexTable;
-+      LNNOffsetTo<UnsizedArrayOf<FWORD32>>	array;
-     } l;
-     struct Short
-     {
--      LNNOffsetTo<Lookup<HBUINT16> >		rowIndexTable;
--      LNNOffsetTo<Lookup<HBUINT16> >		columnIndexTable;
--      LNNOffsetTo<UnsizedArrayOf<FWORD> >	array;
-+      LNNOffsetTo<Lookup<HBUINT16>>		rowIndexTable;
-+      LNNOffsetTo<Lookup<HBUINT16>>		columnIndexTable;
-+      LNNOffsetTo<UnsizedArrayOf<FWORD>>	array;
-     } s;
-   } u;
--  LNNOffsetTo<UnsizedArrayOf<FWORD> >	vector;
-+  LNNOffsetTo<UnsizedArrayOf<FWORD>>	vector;
-   public:
-   DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 24);
- };
- 
- 
- struct KerxSubTableHeader
- {
-   typedef ExtendedTypes Types;
-@@ -766,27 +766,27 @@ struct KerxSubTableHeader
- 
- struct KerxSubTable
- {
-   friend struct kerx;
- 
-   unsigned int get_size () const { return u.header.length; }
-   unsigned int get_type () const { return u.header.coverage & u.header.SubtableType; }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     unsigned int subtable_type = get_type ();
-     TRACE_DISPATCH (this, subtable_type);
-     switch (subtable_type) {
--    case 0:	return_trace (c->dispatch (u.format0));
--    case 1:	return_trace (c->dispatch (u.format1));
--    case 2:	return_trace (c->dispatch (u.format2));
--    case 4:	return_trace (c->dispatch (u.format4));
--    case 6:	return_trace (c->dispatch (u.format6));
-+    case 0:	return_trace (c->dispatch (u.format0, hb_forward<Ts> (ds)...));
-+    case 1:	return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-+    case 2:	return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
-+    case 4:	return_trace (c->dispatch (u.format4, hb_forward<Ts> (ds)...));
-+    case 6:	return_trace (c->dispatch (u.format6, hb_forward<Ts> (ds)...));
-     default:	return_trace (c->default_return_value ());
-     }
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!u.header.sanitize (c) ||
-diff --git a/gfx/harfbuzz/src/hb-aat-layout-lcar-table.hh b/gfx/harfbuzz/src/hb-aat-layout-lcar-table.hh
---- a/gfx/harfbuzz/src/hb-aat-layout-lcar-table.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout-lcar-table.hh
-@@ -76,17 +76,17 @@ struct lcar
-     return_trace (likely (c->check_struct (this) &&
- 			  version.major == 1 &&
- 			  lookup.sanitize (c, this)));
-   }
- 
-   protected:
-   FixedVersion<>version;	/* Version number of the ligature caret table */
-   HBUINT16	format;		/* Format of the ligature caret table. */
--  Lookup<OffsetTo<LigCaretClassEntry> >
-+  Lookup<OffsetTo<LigCaretClassEntry>>
- 		lookup;		/* data Lookup table associating glyphs */
- 
-   public:
-   DEFINE_SIZE_MIN (8);
- };
- 
- } /* namespace AAT */
- 
-diff --git a/gfx/harfbuzz/src/hb-aat-layout-morx-table.hh b/gfx/harfbuzz/src/hb-aat-layout-morx-table.hh
---- a/gfx/harfbuzz/src/hb-aat-layout-morx-table.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout-morx-table.hh
-@@ -83,17 +83,17 @@ struct RearrangementSubtable
-     {
-       hb_buffer_t *buffer = driver->buffer;
-       unsigned int flags = entry.flags;
- 
-       if (flags & MarkFirst)
- 	start = buffer->idx;
- 
-       if (flags & MarkLast)
--	end = MIN (buffer->idx + 1, buffer->len);
-+	end = hb_min (buffer->idx + 1, buffer->len);
- 
-       if ((flags & Verb) && start < end)
-       {
- 	/* The following map has two nibbles, for start-side
- 	 * and end-side. Values of 0,1,2 mean move that many
- 	 * to the other side. Value of 3 means move 2 and
- 	 * flip them. */
- 	const unsigned char map[16] =
-@@ -112,24 +112,24 @@ struct RearrangementSubtable
- 	  0x31,	/* 11	ABxD => DxBA */
- 	  0x22,	/* 12	ABxCD => CDxAB */
- 	  0x32,	/* 13	ABxCD => CDxBA */
- 	  0x23,	/* 14	ABxCD => DCxAB */
- 	  0x33,	/* 15	ABxCD => DCxBA */
- 	};
- 
- 	unsigned int m = map[flags & Verb];
--	unsigned int l = MIN<unsigned int> (2, m >> 4);
--	unsigned int r = MIN<unsigned int> (2, m & 0x0F);
-+	unsigned int l = hb_min (2u, m >> 4);
-+	unsigned int r = hb_min (2u, m & 0x0F);
- 	bool reverse_l = 3 == (m >> 4);
- 	bool reverse_r = 3 == (m & 0x0F);
- 
- 	if (end - start >= l + r)
- 	{
--	  buffer->merge_clusters (start, MIN (buffer->idx + 1, buffer->len));
-+	  buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len));
- 	  buffer->merge_clusters (start, end);
- 
- 	  hb_glyph_info_t *info = buffer->info;
- 	  hb_glyph_info_t buf[4];
- 
- 	  memcpy (buf, info + start, l * sizeof (buf[0]));
- 	  memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
- 
-@@ -256,23 +256,23 @@ struct ContextualSubtable
- 	unsigned int offset = entry.data.markIndex + buffer->info[mark].codepoint;
- 	const UnsizedArrayOf<GlyphID> &subs_old = (const UnsizedArrayOf<GlyphID> &) subs;
- 	replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
- 	if (!replacement->sanitize (&c->sanitizer) || !*replacement)
- 	  replacement = nullptr;
-       }
-       if (replacement)
-       {
--	buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
-+	buffer->unsafe_to_break (mark, hb_min (buffer->idx + 1, buffer->len));
- 	buffer->info[mark].codepoint = *replacement;
- 	ret = true;
-       }
- 
-       replacement = nullptr;
--      unsigned int idx = MIN (buffer->idx, buffer->len - 1);
-+      unsigned int idx = hb_min (buffer->idx, buffer->len - 1);
-       if (Types::extended)
-       {
- 	if (entry.data.currentIndex != 0xFFFF)
- 	{
- 	  const Lookup<GlyphID> &lookup = subs[entry.data.currentIndex];
- 	  replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
- 	}
-       }
-@@ -332,19 +332,19 @@ struct ContextualSubtable
-     unsigned int num_lookups = 0;
- 
-     const Entry<EntryData> *entries = machine.get_entries ();
-     for (unsigned int i = 0; i < num_entries; i++)
-     {
-       const EntryData &data = entries[i].data;
- 
-       if (data.markIndex != 0xFFFF)
--	num_lookups = MAX<unsigned int> (num_lookups, 1 + data.markIndex);
-+	num_lookups = hb_max (num_lookups, 1 + data.markIndex);
-       if (data.currentIndex != 0xFFFF)
--	num_lookups = MAX<unsigned int> (num_lookups, 1 + data.currentIndex);
-+	num_lookups = hb_max (num_lookups, 1 + data.currentIndex);
-     }
- 
-     return_trace (substitutionTables.sanitize (c, this, num_lookups));
-   }
- 
-   protected:
-   StateTable<Types, EntryData>
- 		machine;
-@@ -739,17 +739,17 @@ struct InsertionSubtable
- 	/* TODO We ignore KashidaLike setting. */
- 	for (unsigned int i = 0; i < count; i++)
- 	  buffer->output_glyph (glyphs[i]);
- 	if (buffer->idx < buffer->len && !before)
- 	  buffer->skip_glyph ();
- 
- 	buffer->move_to (end + count);
- 
--	buffer->unsafe_to_break_from_outbuffer (mark, MIN (buffer->idx + 1, buffer->len));
-+	buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len));
-       }
- 
-       if (flags & SetMark)
- 	mark = mark_loc;
- 
-       if (entry.data.currentInsertIndex != 0xFFFF)
-       {
- 	unsigned int count = (flags & CurrentInsertCount) >> 5;
-@@ -878,27 +878,27 @@ struct ChainSubtable
-   {
-     Rearrangement	= 0,
-     Contextual		= 1,
-     Ligature		= 2,
-     Noncontextual	= 4,
-     Insertion		= 5
-   };
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     unsigned int subtable_type = get_type ();
-     TRACE_DISPATCH (this, subtable_type);
-     switch (subtable_type) {
--    case Rearrangement:		return_trace (c->dispatch (u.rearrangement));
--    case Contextual:		return_trace (c->dispatch (u.contextual));
--    case Ligature:		return_trace (c->dispatch (u.ligature));
--    case Noncontextual:		return_trace (c->dispatch (u.noncontextual));
--    case Insertion:		return_trace (c->dispatch (u.insertion));
-+    case Rearrangement:		return_trace (c->dispatch (u.rearrangement, hb_forward<Ts> (ds)...));
-+    case Contextual:		return_trace (c->dispatch (u.contextual, hb_forward<Ts> (ds)...));
-+    case Ligature:		return_trace (c->dispatch (u.ligature, hb_forward<Ts> (ds)...));
-+    case Noncontextual:		return_trace (c->dispatch (u.noncontextual, hb_forward<Ts> (ds)...));
-+    case Insertion:		return_trace (c->dispatch (u.insertion, hb_forward<Ts> (ds)...));
-     default:			return_trace (c->default_return_value ());
-     }
-   }
- 
-   bool apply (hb_aat_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     hb_sanitize_with_object_t with (&c->sanitizer, this);
-@@ -964,17 +964,17 @@ struct Chain
-       }
-     }
-     return flags;
-   }
- 
-   void apply (hb_aat_apply_context_t *c,
- 		     hb_mask_t flags) const
-   {
--    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
-+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
-     unsigned int count = subtableCount;
-     for (unsigned int i = 0; i < count; i++)
-     {
-       bool reverse;
- 
-       if (!(subtable->subFeatureFlags & flags))
-         goto skip;
- 
-@@ -1026,17 +1026,17 @@ struct Chain
-       if (reverse)
-         c->buffer->reverse ();
- 
-       (void) c->buffer->message (c->font, "end chain subtable %d", c->lookup_index);
- 
-       if (unlikely (!c->buffer->successful)) return;
- 
-     skip:
--      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
-+      subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
-       c->set_lookup_index (c->lookup_index + 1);
-     }
-   }
- 
-   unsigned int get_size () const { return length; }
- 
-   bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
-   {
-@@ -1044,23 +1044,23 @@ struct Chain
-     if (!length.sanitize (c) ||
- 	length < min_size ||
- 	!c->check_range (this, length))
-       return_trace (false);
- 
-     if (!c->check_array (featureZ.arrayZ, featureCount))
-       return_trace (false);
- 
--    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types> > (featureZ.as_array (featureCount));
-+    const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
-     unsigned int count = subtableCount;
-     for (unsigned int i = 0; i < count; i++)
-     {
-       if (!subtable->sanitize (c))
- 	return_trace (false);
--      subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
-+      subtable = &StructAfter<ChainSubtable<Types>> (*subtable);
-     }
- 
-     return_trace (true);
-   }
- 
-   protected:
-   HBUINT32	defaultFlags;	/* The default specification for subtables. */
-   HBUINT32	length;		/* Total byte count, including this header. */
-@@ -1090,47 +1090,47 @@ struct mortmorx
-   void compile_flags (const hb_aat_map_builder_t *mapper,
- 		      hb_aat_map_t *map) const
-   {
-     const Chain<Types> *chain = &firstChain;
-     unsigned int count = chainCount;
-     for (unsigned int i = 0; i < count; i++)
-     {
-       map->chain_flags.push (chain->compile_flags (mapper));
--      chain = &StructAfter<Chain<Types> > (*chain);
-+      chain = &StructAfter<Chain<Types>> (*chain);
-     }
-   }
- 
-   void apply (hb_aat_apply_context_t *c) const
-   {
-     if (unlikely (!c->buffer->successful)) return;
-     c->set_lookup_index (0);
-     const Chain<Types> *chain = &firstChain;
-     unsigned int count = chainCount;
-     for (unsigned int i = 0; i < count; i++)
-     {
-       chain->apply (c, c->plan->aat_map.chain_flags[i]);
-       if (unlikely (!c->buffer->successful)) return;
--      chain = &StructAfter<Chain<Types> > (*chain);
-+      chain = &StructAfter<Chain<Types>> (*chain);
-     }
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!version.sanitize (c) || !version || !chainCount.sanitize (c))
-       return_trace (false);
- 
-     const Chain<Types> *chain = &firstChain;
-     unsigned int count = chainCount;
-     for (unsigned int i = 0; i < count; i++)
-     {
-       if (!chain->sanitize (c, version))
- 	return_trace (false);
--      chain = &StructAfter<Chain<Types> > (*chain);
-+      chain = &StructAfter<Chain<Types>> (*chain);
-     }
- 
-     return_trace (true);
-   }
- 
-   protected:
-   HBUINT16	version;	/* Version number of the glyph metamorphosis table.
- 				 * 1, 2, or 3. */
-diff --git a/gfx/harfbuzz/src/hb-aat-layout-trak-table.hh b/gfx/harfbuzz/src/hb-aat-layout-trak-table.hh
---- a/gfx/harfbuzz/src/hb-aat-layout-trak-table.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout-trak-table.hh
-@@ -61,17 +61,17 @@ struct TrackTableEntry
- 			  (valuesZ.sanitize (c, base, table_size))));
-   }
- 
-   protected:
-   Fixed		track;		/* Track value for this record. */
-   NameID	trackNameID;	/* The 'name' table index for this track.
- 				 * (a short word or phrase like "loose"
- 				 * or "very tight") */
--  NNOffsetTo<UnsizedArrayOf<FWORD> >
-+  NNOffsetTo<UnsizedArrayOf<FWORD>>
- 		valuesZ;	/* Offset from start of tracking table to
- 				 * per-size tracking values for this track. */
- 
-   public:
-   DEFINE_SIZE_STATIC (8);
- };
- 
- struct TrackData
-@@ -128,18 +128,18 @@ struct TrackData
-     if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
- 
-     hb_array_t<const Fixed> size_table ((base+sizeTable).arrayZ, sizes);
-     unsigned int size_index;
-     for (size_index = 0; size_index < sizes - 1; size_index++)
-       if (size_table[size_index].to_float () >= csspx)
-         break;
- 
--    return round (interpolate_at (size_index ? size_index - 1 : 0, csspx,
--				  *trackTableEntry, base));
-+    return roundf (interpolate_at (size_index ? size_index - 1 : 0, csspx,
-+				   *trackTableEntry, base));
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c, const void *base) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this) &&
- 			  sizeTable.sanitize (c, base, nSizes) &&
- 			  trackTable.sanitize (c, nTracks, base, nSizes)));
-diff --git a/gfx/harfbuzz/src/hb-aat-layout.cc b/gfx/harfbuzz/src/hb-aat-layout.cc
---- a/gfx/harfbuzz/src/hb-aat-layout.cc
-+++ b/gfx/harfbuzz/src/hb-aat-layout.cc
-@@ -130,28 +130,34 @@ static const hb_aat_feature_mapping_t fe
-   {HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
-   {HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
-   {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS,      HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON,                HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
- };
- 
- const hb_aat_feature_mapping_t *
- hb_aat_layout_find_feature_mapping (hb_tag_t tag)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return nullptr;
-+#endif
-+
-   return (const hb_aat_feature_mapping_t *) bsearch (&tag,
- 						     feature_mappings,
- 						     ARRAY_LENGTH (feature_mappings),
- 						     sizeof (feature_mappings[0]),
- 						     hb_aat_feature_mapping_t::cmp);
- }
- 
- 
- /*
-  * hb_aat_apply_context_t
-  */
- 
-+/* Note: This context is used for kerning, even without AAT. */
-+
- AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
- 						     hb_font_t *font_,
- 						     hb_buffer_t *buffer_,
- 						     hb_blob_t *blob) :
- 						       plan (plan_),
- 						       font (font_),
- 						       face (font->face),
- 						       buffer (buffer_),
-@@ -178,16 +184,20 @@ AAT::hb_aat_apply_context_t::set_ankr_ta
-  * mort/morx/kerx/trak
-  */
- 
- 
- void
- hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
- 			   hb_aat_map_t *map)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return;
-+#endif
-+
-   const AAT::morx& morx = *mapper->face->table.morx;
-   if (morx.has_data ())
-   {
-     morx.compile_flags (mapper, map);
-     return;
-   }
- 
-   const AAT::mort& mort = *mapper->face->table.mort;
-@@ -204,25 +214,33 @@ hb_aat_layout_compile_map (const hb_aat_
-  * @face:
-  *
-  * Returns:
-  * Since: 2.3.0
-  */
- hb_bool_t
- hb_aat_layout_has_substitution (hb_face_t *face)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return false;
-+#endif
-+
-   return face->table.morx->has_data () ||
- 	 face->table.mort->has_data ();
- }
- 
- void
- hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
- 			  hb_font_t *font,
- 			  hb_buffer_t *buffer)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return;
-+#endif
-+
-   hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
-   const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
-   if (morx.has_data ())
-   {
-     AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
-     morx.apply (&c);
-     return;
-   }
-@@ -235,16 +253,20 @@ hb_aat_layout_substitute (const hb_ot_sh
-     mort.apply (&c);
-     return;
-   }
- }
- 
- void
- hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return;
-+#endif
-+
-   unsigned int count = buffer->len;
-   hb_glyph_info_t *info = buffer->info;
-   hb_glyph_position_t *pos = buffer->pos;
-   for (unsigned int i = 0; i < count; i++)
-     if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
-       pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
- }
- 
-@@ -252,37 +274,49 @@ static bool
- is_deleted_glyph (const hb_glyph_info_t *info)
- {
-   return info->codepoint == AAT::DELETED_GLYPH;
- }
- 
- void
- hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return;
-+#endif
-+
-   hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
- }
- 
- /*
-  * hb_aat_layout_has_positioning:
-  * @face:
-  *
-  * Returns:
-  * Since: 2.3.0
-  */
- hb_bool_t
- hb_aat_layout_has_positioning (hb_face_t *face)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return false;
-+#endif
-+
-   return face->table.kerx->has_data ();
- }
- 
- void
- hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
- 			hb_font_t *font,
- 			hb_buffer_t *buffer)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return;
-+#endif
-+
-   hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
-   const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
- 
-   AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
-   c.set_ankr_table (font->face->table.ankr.get ());
-   kerx.apply (&c);
- }
- 
-@@ -292,38 +326,38 @@ hb_aat_layout_position (const hb_ot_shap
-  * @face:
-  *
-  * Returns:
-  * Since: 2.3.0
-  */
- hb_bool_t
- hb_aat_layout_has_tracking (hb_face_t *face)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return false;
-+#endif
-+
-   return face->table.trak->has_data ();
- }
- 
- void
- hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
- 		     hb_font_t *font,
- 		     hb_buffer_t *buffer)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return;
-+#endif
-+
-   const AAT::trak& trak = *font->face->table.trak;
- 
-   AAT::hb_aat_apply_context_t c (plan, font, buffer);
-   trak.apply (&c);
- }
- 
--
--hb_language_t
--_hb_aat_language_get (hb_face_t *face,
--		      unsigned int i)
--{
--  return face->table.ltag->get_language (i);
--}
--
- /**
-  * hb_aat_layout_get_feature_types:
-  * @face: a face object
-  * @start_offset: iteration's start offset
-  * @feature_count:(inout) (allow-none): buffer size as input, filled size as output
-  * @features: (out caller-allocates) (array length=feature_count): features buffer
-  *
-  * Return value: Number of all available feature types.
-@@ -331,32 +365,42 @@ hb_language_t
-  * Since: 2.2.0
-  */
- unsigned int
- hb_aat_layout_get_feature_types (hb_face_t                    *face,
- 				 unsigned int                  start_offset,
- 				 unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
- 				 hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  if (feature_count)
-+    *feature_count = 0;
-+  return 0;
-+#endif
-+
-   return face->table.feat->get_feature_types (start_offset, feature_count, features);
- }
- 
- /**
-  * hb_aat_layout_feature_type_get_name_id:
-  * @face: a face object
-  * @feature_type: feature id
-  *
-  * Return value: Name ID index
-  *
-  * Since: 2.2.0
-  */
- hb_ot_name_id_t
- hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
- 					hb_aat_layout_feature_type_t  feature_type)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return HB_OT_NAME_ID_INVALID;
-+#endif
-+
-   return face->table.feat->get_feature_name_id (feature_type);
- }
- 
- /**
-  * hb_aat_layout_feature_type_get_selectors:
-  * @face:    a face object
-  * @feature_type: feature id
-  * @start_offset:    iteration's start offset
-@@ -375,10 +419,16 @@ hb_aat_layout_feature_type_get_name_id (
- unsigned int
- hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
- 					       hb_aat_layout_feature_type_t           feature_type,
- 					       unsigned int                           start_offset,
- 					       unsigned int                          *selector_count, /* IN/OUT.  May be NULL. */
- 					       hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
- 					       unsigned int                          *default_index   /* OUT.     May be NULL. */)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  if (selector_count)
-+    *selector_count = 0;
-+  return 0;
-+#endif
-+
-   return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
- }
-diff --git a/gfx/harfbuzz/src/hb-aat-layout.hh b/gfx/harfbuzz/src/hb-aat-layout.hh
---- a/gfx/harfbuzz/src/hb-aat-layout.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout.hh
-@@ -25,26 +25,26 @@
-  */
- 
- #ifndef HB_AAT_LAYOUT_HH
- #define HB_AAT_LAYOUT_HH
- 
- #include "hb.hh"
- 
- #include "hb-ot-shape.hh"
--
-+#include "hb-aat-ltag-table.hh"
- 
- struct hb_aat_feature_mapping_t
- {
-   hb_tag_t otFeatureTag;
-   hb_aat_layout_feature_type_t aatFeatureType;
-   hb_aat_layout_feature_selector_t selectorToEnable;
-   hb_aat_layout_feature_selector_t selectorToDisable;
- 
--  static int cmp (const void *key_, const void *entry_)
-+  HB_INTERNAL static int cmp (const void *key_, const void *entry_)
-   {
-     hb_tag_t key = * (unsigned int *) key_;
-     const hb_aat_feature_mapping_t * entry = (const hb_aat_feature_mapping_t *) entry_;
-     return key < entry->otFeatureTag ? -1 :
- 	   key > entry->otFeatureTag ? 1 :
- 	   0;
-   }
- };
-@@ -72,14 +72,18 @@ hb_aat_layout_position (const hb_ot_shap
- 			hb_font_t *font,
- 			hb_buffer_t *buffer);
- 
- HB_INTERNAL void
- hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
- 		     hb_font_t *font,
- 		     hb_buffer_t *buffer);
- 
--HB_INTERNAL hb_language_t
-+
-+inline hb_language_t
- _hb_aat_language_get (hb_face_t *face,
--		      unsigned int i);
-+                      unsigned int i)
-+{
-+  return face->table.ltag->get_language (i);
-+}
- 
- 
- #endif /* HB_AAT_LAYOUT_HH */
-diff --git a/gfx/harfbuzz/src/hb-aat-ltag-table.hh b/gfx/harfbuzz/src/hb-aat-ltag-table.hh
---- a/gfx/harfbuzz/src/hb-aat-ltag-table.hh
-+++ b/gfx/harfbuzz/src/hb-aat-ltag-table.hh
-@@ -45,17 +45,17 @@ struct FTStringRange
- 
-   bool sanitize (hb_sanitize_context_t *c, const void *base) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) && (base+tag).sanitize (c, length));
-   }
- 
-   protected:
--  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
-+  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
- 		tag;		/* Offset from the start of the table to
- 				 * the beginning of the string */
-   HBUINT16	length;		/* String length (in bytes) */
-   public:
-   DEFINE_SIZE_STATIC (4);
- };
- 
- struct ltag
-diff --git a/gfx/harfbuzz/src/hb-aat-map.cc b/gfx/harfbuzz/src/hb-aat-map.cc
---- a/gfx/harfbuzz/src/hb-aat-map.cc
-+++ b/gfx/harfbuzz/src/hb-aat-map.cc
-@@ -29,16 +29,20 @@
- #include "hb-aat-map.hh"
- 
- #include "hb-aat-layout.hh"
- 
- 
- void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
- 					unsigned int value)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return;
-+#endif
-+
-   if (tag == HB_TAG ('a','a','l','t'))
-   {
-     feature_info_t *info = features.push();
-     info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
-     info->setting = (hb_aat_layout_feature_selector_t) value;
-     return;
-   }
- 
-@@ -48,16 +52,20 @@ void hb_aat_map_builder_t::add_feature (
-   feature_info_t *info = features.push();
-   info->type = mapping->aatFeatureType;
-   info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
- }
- 
- void
- hb_aat_map_builder_t::compile (hb_aat_map_t  &m)
- {
-+#ifdef HB_NO_SHAPE_AAT
-+  return;
-+#endif
-+
-   /* Sort features and merge duplicates */
-   if (features.length)
-   {
-     features.qsort ();
-     unsigned int j = 0;
-     for (unsigned int i = 1; i < features.length; i++)
-       if (features[i].type != features[j].type)
- 	features[++j] = features[i];
-diff --git a/gfx/harfbuzz/src/hb-aat-map.hh b/gfx/harfbuzz/src/hb-aat-map.hh
---- a/gfx/harfbuzz/src/hb-aat-map.hh
-+++ b/gfx/harfbuzz/src/hb-aat-map.hh
-@@ -61,17 +61,17 @@ struct hb_aat_map_builder_t
- 
-   public:
-   struct feature_info_t
-   {
-     hb_aat_layout_feature_type_t  type;
-     hb_aat_layout_feature_selector_t  setting;
-     unsigned  seq; /* For stable sorting only. */
- 
--    static int cmp (const void *pa, const void *pb)
-+    HB_INTERNAL static int cmp (const void *pa, const void *pb)
-     {
-       const feature_info_t *a = (const feature_info_t *) pa;
-       const feature_info_t *b = (const feature_info_t *) pb;
-       return (a->type != b->type) ? (a->type < b->type ? -1 : 1) :
- 	     (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
-     }
- 
-     int cmp (hb_aat_layout_feature_type_t ty) const
-@@ -79,13 +79,13 @@ struct hb_aat_map_builder_t
-       return (type != ty) ? (type < ty ? -1 : 1) : 0;
-     }
-   };
- 
-   public:
-   hb_face_t *face;
- 
-   public:
--  hb_vector_t<feature_info_t> features;
-+  hb_sorted_vector_t<feature_info_t> features;
- };
- 
- 
- #endif /* HB_AAT_MAP_HH */
-diff --git a/gfx/harfbuzz/src/hb-algs.hh b/gfx/harfbuzz/src/hb-algs.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-algs.hh
-@@ -0,0 +1,951 @@
-+/*
-+ * Copyright © 2017  Google, Inc.
-+ * Copyright © 2019  Google, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Google Author(s): Behdad Esfahbod
-+ * Facebook Author(s): Behdad Esfahbod
-+ */
-+
-+#ifndef HB_ALGS_HH
-+#define HB_ALGS_HH
-+
-+#include "hb.hh"
-+#include "hb-meta.hh"
-+#include "hb-null.hh"
-+
-+
-+/* Encodes three unsigned integers in one 64-bit number.  If the inputs have more than 21 bits,
-+ * values will be truncated / overlap, and might not decode exactly. */
-+#define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
-+#define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
-+#define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
-+#define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
-+
-+
-+struct
-+{
-+  /* Note.  This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
-+  template <typename T> auto
-+  operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
-+}
-+HB_FUNCOBJ (hb_identity);
-+struct
-+{
-+  /* Like identity(), but only retains lvalue-references.  Rvalues are returned as rvalues. */
-+  template <typename T> T&
-+  operator () (T& v) const { return v; }
-+
-+  template <typename T> hb_remove_reference<T>
-+  operator () (T&& v) const { return v; }
-+}
-+HB_FUNCOBJ (hb_lidentity);
-+struct
-+{
-+  /* Like identity(), but always returns rvalue. */
-+  template <typename T> hb_remove_reference<T>
-+  operator () (T&& v) const { return v; }
-+}
-+HB_FUNCOBJ (hb_ridentity);
-+
-+struct
-+{
-+  template <typename T> bool
-+  operator () (T&& v) const { return bool (hb_forward<T> (v)); }
-+}
-+HB_FUNCOBJ (hb_bool);
-+
-+struct
-+{
-+  private:
-+  template <typename T> auto
-+  impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
-+
-+  template <typename T,
-+	    hb_enable_if (hb_is_integral (T))> auto
-+  impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
-+  (
-+    /* Knuth's multiplicative method: */
-+    (uint32_t) v * 2654435761u
-+  )
-+
-+  public:
-+
-+  template <typename T> auto
-+  operator () (const T& v) const HB_RETURN (uint32_t, impl (v, hb_prioritize))
-+}
-+HB_FUNCOBJ (hb_hash);
-+
-+
-+struct
-+{
-+  private:
-+
-+  /* Pointer-to-member-function. */
-+  template <typename Appl, typename T, typename ...Ts> auto
-+  impl (Appl&& a, hb_priority<2>, T &&v, Ts&&... ds) const HB_AUTO_RETURN
-+  ((hb_deref (hb_forward<T> (v)).*hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
-+
-+  /* Pointer-to-member. */
-+  template <typename Appl, typename T> auto
-+  impl (Appl&& a, hb_priority<1>, T &&v) const HB_AUTO_RETURN
-+  ((hb_deref (hb_forward<T> (v))).*hb_forward<Appl> (a))
-+
-+  /* Operator(). */
-+  template <typename Appl, typename ...Ts> auto
-+  impl (Appl&& a, hb_priority<0>, Ts&&... ds) const HB_AUTO_RETURN
-+  (hb_deref (hb_forward<Appl> (a)) (hb_forward<Ts> (ds)...))
-+
-+  public:
-+
-+  template <typename Appl, typename ...Ts> auto
-+  operator () (Appl&& a, Ts&&... ds) const HB_AUTO_RETURN
-+  (
-+    impl (hb_forward<Appl> (a),
-+	  hb_prioritize,
-+	  hb_forward<Ts> (ds)...)
-+  )
-+}
-+HB_FUNCOBJ (hb_invoke);
-+
-+template <unsigned Pos, typename Appl, typename V>
-+struct hb_partial_t
-+{
-+  hb_partial_t (Appl a, V v) : a (a), v (v) {}
-+
-+  static_assert (Pos > 0, "");
-+
-+  template <typename ...Ts,
-+	    unsigned P = Pos,
-+	    hb_enable_if (P == 1)> auto
-+  operator () (Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
-+						   hb_declval (V),
-+						   hb_declval (Ts)...))
-+  {
-+    return hb_invoke (hb_forward<Appl> (a),
-+		      hb_forward<V> (v),
-+		      hb_forward<Ts> (ds)...);
-+  }
-+  template <typename T0, typename ...Ts,
-+	    unsigned P = Pos,
-+	    hb_enable_if (P == 2)> auto
-+  operator () (T0&& d0, Ts&& ...ds) -> decltype (hb_invoke (hb_declval (Appl),
-+							    hb_declval (T0),
-+							    hb_declval (V),
-+							    hb_declval (Ts)...))
-+  {
-+    return hb_invoke (hb_forward<Appl> (a),
-+		      hb_forward<T0> (d0),
-+		      hb_forward<V> (v),
-+		      hb_forward<Ts> (ds)...);
-+  }
-+
-+  private:
-+  hb_reference_wrapper<Appl> a;
-+  V v;
-+};
-+template <unsigned Pos=1, typename Appl, typename V>
-+auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
-+(( hb_partial_t<Pos, Appl, V> (a, v) ))
-+
-+/* The following hacky replacement version is to make Visual Stuiod build:. */ \
-+/* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
-+#ifdef _MSC_VER
-+#define HB_PARTIALIZE(Pos) \
-+  template <typename _T> \
-+  decltype(auto) operator () (_T&& _v) const \
-+  { return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
-+  static_assert (true, "")
-+#else
-+#define HB_PARTIALIZE(Pos) \
-+  template <typename _T> \
-+  auto operator () (_T&& _v) const HB_AUTO_RETURN \
-+  (hb_partial<Pos> (this, hb_forward<_T> (_v))) \
-+  static_assert (true, "")
-+#endif
-+
-+
-+struct
-+{
-+  private:
-+
-+  template <typename Pred, typename Val> auto
-+  impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
-+  (hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v)))
-+
-+  template <typename Pred, typename Val> auto
-+  impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
-+  (
-+    hb_invoke (hb_forward<Pred> (p),
-+	       hb_forward<Val> (v))
-+  )
-+
-+  public:
-+
-+  template <typename Pred, typename Val> auto
-+  operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
-+    impl (hb_forward<Pred> (p),
-+	  hb_forward<Val> (v),
-+	  hb_prioritize)
-+  )
-+}
-+HB_FUNCOBJ (hb_has);
-+
-+struct
-+{
-+  private:
-+
-+  template <typename Pred, typename Val> auto
-+  impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
-+  (
-+    hb_has (hb_forward<Pred> (p),
-+	    hb_forward<Val> (v))
-+  )
-+
-+  template <typename Pred, typename Val> auto
-+  impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
-+  (
-+    hb_forward<Pred> (p) == hb_forward<Val> (v)
-+  )
-+
-+  public:
-+
-+  template <typename Pred, typename Val> auto
-+  operator () (Pred&& p, Val &&v) const HB_RETURN (bool,
-+    impl (hb_forward<Pred> (p),
-+	  hb_forward<Val> (v),
-+	  hb_prioritize)
-+  )
-+}
-+HB_FUNCOBJ (hb_match);
-+
-+struct
-+{
-+  private:
-+
-+  template <typename Proj, typename Val> auto
-+  impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN
-+  (hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v)))
-+
-+  template <typename Proj, typename Val> auto
-+  impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN
-+  (
-+    hb_invoke (hb_forward<Proj> (f),
-+	       hb_forward<Val> (v))
-+  )
-+
-+  template <typename Proj, typename Val> auto
-+  impl (Proj&& f, Val &&v, hb_priority<0>) const HB_AUTO_RETURN
-+  (
-+    hb_forward<Proj> (f)[hb_forward<Val> (v)]
-+  )
-+
-+  public:
-+
-+  template <typename Proj, typename Val> auto
-+  operator () (Proj&& f, Val &&v) const HB_AUTO_RETURN
-+  (
-+    impl (hb_forward<Proj> (f),
-+	  hb_forward<Val> (v),
-+	  hb_prioritize)
-+  )
-+}
-+HB_FUNCOBJ (hb_get);
-+
-+
-+template <typename T1, typename T2>
-+struct hb_pair_t
-+{
-+  typedef T1 first_t;
-+  typedef T2 second_t;
-+  typedef hb_pair_t<T1, T2> pair_t;
-+
-+  hb_pair_t (T1 a, T2 b) : first (a), second (b) {}
-+
-+  template <typename Q1, typename Q2,
-+	    hb_enable_if (hb_is_convertible (T1, Q1) &&
-+			  hb_is_convertible (T2, T2))>
-+  operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
-+
-+  hb_pair_t<T1, T2> reverse () const
-+  { return hb_pair_t<T1, T2> (second, first); }
-+
-+  bool operator == (const pair_t& o) const { return first == o.first && second == o.second; }
-+  bool operator != (const pair_t& o) const { return !(*this == o); }
-+  bool operator < (const pair_t& o) const { return first < o.first || (first == o.first && second < o.second); }
-+  bool operator >= (const pair_t& o) const { return !(*this < o); }
-+  bool operator > (const pair_t& o) const { return first > o.first || (first == o.first && second > o.second); }
-+  bool operator <= (const pair_t& o) const { return !(*this > o); }
-+
-+  T1 first;
-+  T2 second;
-+};
-+#define hb_pair_t(T1,T2) hb_pair_t<T1, T2>
-+template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
-+hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
-+
-+struct
-+{
-+  template <typename Pair> typename Pair::first_t
-+  operator () (const Pair& pair) const { return pair.first; }
-+}
-+HB_FUNCOBJ (hb_first);
-+
-+struct
-+{
-+  template <typename Pair> typename Pair::second_t
-+  operator () (const Pair& pair) const { return pair.second; }
-+}
-+HB_FUNCOBJ (hb_second);
-+
-+/* Note.  In min/max impl, we can use hb_type_identity<T> for second argument.
-+ * However, that would silently convert between different-signedness integers.
-+ * Instead we accept two different types, such that compiler can err if
-+ * comparing integers of different signedness. */
-+struct
-+{
-+  template <typename T, typename T2> auto
-+  operator () (T&& a, T2&& b) const HB_AUTO_RETURN
-+  (hb_forward<T> (a) <= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
-+}
-+HB_FUNCOBJ (hb_min);
-+struct
-+{
-+  template <typename T, typename T2> auto
-+  operator () (T&& a, T2&& b) const HB_AUTO_RETURN
-+  (hb_forward<T> (a) >= hb_forward<T2> (b) ? hb_forward<T> (a) : hb_forward<T2> (b))
-+}
-+HB_FUNCOBJ (hb_max);
-+
-+
-+/*
-+ * Bithacks.
-+ */
-+
-+/* Return the number of 1 bits in v. */
-+template <typename T>
-+static inline HB_CONST_FUNC unsigned int
-+hb_popcount (T v)
-+{
-+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
-+  if (sizeof (T) <= sizeof (unsigned int))
-+    return __builtin_popcount (v);
-+
-+  if (sizeof (T) <= sizeof (unsigned long))
-+    return __builtin_popcountl (v);
-+
-+  if (sizeof (T) <= sizeof (unsigned long long))
-+    return __builtin_popcountll (v);
-+#endif
-+
-+  if (sizeof (T) <= 4)
-+  {
-+    /* "HACKMEM 169" */
-+    uint32_t y;
-+    y = (v >> 1) &033333333333;
-+    y = v - y - ((y >>1) & 033333333333);
-+    return (((y + (y >> 3)) & 030707070707) % 077);
-+  }
-+
-+  if (sizeof (T) == 8)
-+  {
-+    unsigned int shift = 32;
-+    return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
-+  }
-+
-+  if (sizeof (T) == 16)
-+  {
-+    unsigned int shift = 64;
-+    return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
-+  }
-+
-+  assert (0);
-+  return 0; /* Shut up stupid compiler. */
-+}
-+
-+/* Returns the number of bits needed to store number */
-+template <typename T>
-+static inline HB_CONST_FUNC unsigned int
-+hb_bit_storage (T v)
-+{
-+  if (unlikely (!v)) return 0;
-+
-+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
-+  if (sizeof (T) <= sizeof (unsigned int))
-+    return sizeof (unsigned int) * 8 - __builtin_clz (v);
-+
-+  if (sizeof (T) <= sizeof (unsigned long))
-+    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
-+
-+  if (sizeof (T) <= sizeof (unsigned long long))
-+    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
-+#endif
-+
-+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-+  if (sizeof (T) <= sizeof (unsigned int))
-+  {
-+    unsigned long where;
-+    _BitScanReverse (&where, v);
-+    return 1 + where;
-+  }
-+# if defined(_WIN64)
-+  if (sizeof (T) <= 8)
-+  {
-+    unsigned long where;
-+    _BitScanReverse64 (&where, v);
-+    return 1 + where;
-+  }
-+# endif
-+#endif
-+
-+  if (sizeof (T) <= 4)
-+  {
-+    /* "bithacks" */
-+    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
-+    const unsigned int S[] = {1, 2, 4, 8, 16};
-+    unsigned int r = 0;
-+    for (int i = 4; i >= 0; i--)
-+      if (v & b[i])
-+      {
-+	v >>= S[i];
-+	r |= S[i];
-+      }
-+    return r + 1;
-+  }
-+  if (sizeof (T) <= 8)
-+  {
-+    /* "bithacks" */
-+    const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
-+    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
-+    unsigned int r = 0;
-+    for (int i = 5; i >= 0; i--)
-+      if (v & b[i])
-+      {
-+	v >>= S[i];
-+	r |= S[i];
-+      }
-+    return r + 1;
-+  }
-+  if (sizeof (T) == 16)
-+  {
-+    unsigned int shift = 64;
-+    return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
-+			  hb_bit_storage<uint64_t> ((uint64_t) v);
-+  }
-+
-+  assert (0);
-+  return 0; /* Shut up stupid compiler. */
-+}
-+
-+/* Returns the number of zero bits in the least significant side of v */
-+template <typename T>
-+static inline HB_CONST_FUNC unsigned int
-+hb_ctz (T v)
-+{
-+  if (unlikely (!v)) return 0;
-+
-+#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
-+  if (sizeof (T) <= sizeof (unsigned int))
-+    return __builtin_ctz (v);
-+
-+  if (sizeof (T) <= sizeof (unsigned long))
-+    return __builtin_ctzl (v);
-+
-+  if (sizeof (T) <= sizeof (unsigned long long))
-+    return __builtin_ctzll (v);
-+#endif
-+
-+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-+  if (sizeof (T) <= sizeof (unsigned int))
-+  {
-+    unsigned long where;
-+    _BitScanForward (&where, v);
-+    return where;
-+  }
-+# if defined(_WIN64)
-+  if (sizeof (T) <= 8)
-+  {
-+    unsigned long where;
-+    _BitScanForward64 (&where, v);
-+    return where;
-+  }
-+# endif
-+#endif
-+
-+  if (sizeof (T) <= 4)
-+  {
-+    /* "bithacks" */
-+    unsigned int c = 32;
-+    v &= - (int32_t) v;
-+    if (v) c--;
-+    if (v & 0x0000FFFF) c -= 16;
-+    if (v & 0x00FF00FF) c -= 8;
-+    if (v & 0x0F0F0F0F) c -= 4;
-+    if (v & 0x33333333) c -= 2;
-+    if (v & 0x55555555) c -= 1;
-+    return c;
-+  }
-+  if (sizeof (T) <= 8)
-+  {
-+    /* "bithacks" */
-+    unsigned int c = 64;
-+    v &= - (int64_t) (v);
-+    if (v) c--;
-+    if (v & 0x00000000FFFFFFFFULL) c -= 32;
-+    if (v & 0x0000FFFF0000FFFFULL) c -= 16;
-+    if (v & 0x00FF00FF00FF00FFULL) c -= 8;
-+    if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
-+    if (v & 0x3333333333333333ULL) c -= 2;
-+    if (v & 0x5555555555555555ULL) c -= 1;
-+    return c;
-+  }
-+  if (sizeof (T) == 16)
-+  {
-+    unsigned int shift = 64;
-+    return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
-+			  hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
-+  }
-+
-+  assert (0);
-+  return 0; /* Shut up stupid compiler. */
-+}
-+
-+
-+/*
-+ * Tiny stuff.
-+ */
-+
-+/* ASCII tag/character handling */
-+static inline bool ISALPHA (unsigned char c)
-+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
-+static inline bool ISALNUM (unsigned char c)
-+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
-+static inline bool ISSPACE (unsigned char c)
-+{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
-+static inline unsigned char TOUPPER (unsigned char c)
-+{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
-+static inline unsigned char TOLOWER (unsigned char c)
-+{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
-+
-+static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
-+{ return (a + (b - 1)) / b; }
-+
-+
-+#undef  ARRAY_LENGTH
-+template <typename Type, unsigned int n>
-+static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
-+/* A const version, but does not detect erratically being called on pointers. */
-+#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
-+
-+
-+static inline int
-+hb_memcmp (const void *a, const void *b, unsigned int len)
-+{
-+  /* It's illegal to pass NULL to memcmp(), even if len is zero.
-+   * So, wrap it.
-+   * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
-+  if (!len) return 0;
-+  return memcmp (a, b, len);
-+}
-+
-+static inline bool
-+hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
-+{
-+  return (size > 0) && (count >= ((unsigned int) -1) / size);
-+}
-+
-+static inline unsigned int
-+hb_ceil_to_4 (unsigned int v)
-+{
-+  return ((v - 1) | 3) + 1;
-+}
-+
-+template <typename T> static inline bool
-+hb_in_range (T u, T lo, T hi)
-+{
-+  static_assert (!hb_is_signed<T>::value, "");
-+
-+  /* The casts below are important as if T is smaller than int,
-+   * the subtract results will become a signed int! */
-+  return (T)(u - lo) <= (T)(hi - lo);
-+}
-+template <typename T> static inline bool
-+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
-+{
-+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
-+}
-+template <typename T> static inline bool
-+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
-+{
-+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
-+}
-+
-+
-+/*
-+ * Sort and search.
-+ */
-+
-+static inline void *
-+hb_bsearch (const void *key, const void *base,
-+	    size_t nmemb, size_t size,
-+	    int (*compar)(const void *_key, const void *_item))
-+{
-+  int min = 0, max = (int) nmemb - 1;
-+  while (min <= max)
-+  {
-+    int mid = (min + max) / 2;
-+    const void *p = (const void *) (((const char *) base) + (mid * size));
-+    int c = compar (key, p);
-+    if (c < 0)
-+      max = mid - 1;
-+    else if (c > 0)
-+      min = mid + 1;
-+    else
-+      return (void *) p;
-+  }
-+  return nullptr;
-+}
-+
-+static inline void *
-+hb_bsearch_r (const void *key, const void *base,
-+	      size_t nmemb, size_t size,
-+	      int (*compar)(const void *_key, const void *_item, void *_arg),
-+	      void *arg)
-+{
-+  int min = 0, max = (int) nmemb - 1;
-+  while (min <= max)
-+  {
-+    int mid = ((unsigned int) min + (unsigned int) max) / 2;
-+    const void *p = (const void *) (((const char *) base) + (mid * size));
-+    int c = compar (key, p, arg);
-+    if (c < 0)
-+      max = mid - 1;
-+    else if (c > 0)
-+      min = mid + 1;
-+    else
-+      return (void *) p;
-+  }
-+  return nullptr;
-+}
-+
-+
-+/* From https://github.com/noporpoise/sort_r
-+ * With following modifications:
-+ *
-+ * 10 November 2018:
-+ * https://github.com/noporpoise/sort_r/issues/7
-+ */
-+
-+/* Isaac Turner 29 April 2014 Public Domain */
-+
-+/*
-+
-+hb_sort_r function to be exported.
-+
-+Parameters:
-+  base is the array to be sorted
-+  nel is the number of elements in the array
-+  width is the size in bytes of each element of the array
-+  compar is the comparison function
-+  arg is a pointer to be passed to the comparison function
-+
-+void hb_sort_r(void *base, size_t nel, size_t width,
-+               int (*compar)(const void *_a, const void *_b, void *_arg),
-+               void *arg);
-+*/
-+
-+
-+/* swap a, b iff a>b */
-+/* __restrict is same as restrict but better support on old machines */
-+static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
-+			  int (*compar)(const void *_a, const void *_b,
-+					void *_arg),
-+			  void *arg)
-+{
-+  char tmp, *end = a+w;
-+  if(compar(a, b, arg) > 0) {
-+    for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
-+    return 1;
-+  }
-+  return 0;
-+}
-+
-+/* Note: quicksort is not stable, equivalent values may be swapped */
-+static inline void sort_r_simple(void *base, size_t nel, size_t w,
-+				 int (*compar)(const void *_a, const void *_b,
-+					       void *_arg),
-+				 void *arg)
-+{
-+  char *b = (char *)base, *end = b + nel*w;
-+  if(nel < 7) {
-+    /* Insertion sort for arbitrarily small inputs */
-+    char *pi, *pj;
-+    for(pi = b+w; pi < end; pi += w) {
-+      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
-+    }
-+  }
-+  else
-+  {
-+    /* nel > 6; Quicksort */
-+
-+    /* Use median of first, middle and last items as pivot */
-+    char *x, *y, *xend, ch;
-+    char *pl, *pm, *pr;
-+    char *last = b+w*(nel-1), *tmp;
-+    char *l[3];
-+    l[0] = b;
-+    l[1] = b+w*(nel/2);
-+    l[2] = last;
-+
-+    if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
-+    if(compar(l[1],l[2],arg) > 0) {
-+      tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
-+      if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
-+    }
-+
-+    /* swap l[id], l[2] to put pivot as last element */
-+    for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
-+      ch = *x; *x = *y; *y = ch;
-+    }
-+
-+    pl = b;
-+    pr = last;
-+
-+    while(pl < pr) {
-+      pm = pl+((pr-pl+1)>>1);
-+      for(; pl < pm; pl += w) {
-+        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
-+          pr -= w; /* pivot now at pl */
-+          break;
-+        }
-+      }
-+      pm = pl+((pr-pl)>>1);
-+      for(; pm < pr; pr -= w) {
-+        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
-+          pl += w; /* pivot now at pr */
-+          break;
-+        }
-+      }
-+    }
-+
-+    sort_r_simple(b, (pl-b)/w, w, compar, arg);
-+    sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
-+  }
-+}
-+
-+static inline void
-+hb_sort_r (void *base, size_t nel, size_t width,
-+	   int (*compar)(const void *_a, const void *_b, void *_arg),
-+	   void *arg)
-+{
-+    sort_r_simple(base, nel, width, compar, arg);
-+}
-+
-+
-+template <typename T, typename T2, typename T3> static inline void
-+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
-+{
-+  for (unsigned int i = 1; i < len; i++)
-+  {
-+    unsigned int j = i;
-+    while (j && compar (&array[j - 1], &array[i]) > 0)
-+      j--;
-+    if (i == j)
-+      continue;
-+    /* Move item i to occupy place for item j, shift what's in between. */
-+    {
-+      T t = array[i];
-+      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
-+      array[j] = t;
-+    }
-+    if (array2)
-+    {
-+      T3 t = array2[i];
-+      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T3));
-+      array2[j] = t;
-+    }
-+  }
-+}
-+
-+template <typename T> static inline void
-+hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
-+{
-+  hb_stable_sort (array, len, compar, (int *) nullptr);
-+}
-+
-+static inline hb_bool_t
-+hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
-+{
-+  /* Pain because we don't know whether s is nul-terminated. */
-+  char buf[64];
-+  len = hb_min (ARRAY_LENGTH (buf) - 1, len);
-+  strncpy (buf, s, len);
-+  buf[len] = '\0';
-+
-+  char *end;
-+  errno = 0;
-+  unsigned long v = strtoul (buf, &end, base);
-+  if (errno) return false;
-+  if (*end) return false;
-+  *out = v;
-+  return true;
-+}
-+
-+
-+/* Operators. */
-+
-+struct hb_bitwise_and
-+{ HB_PARTIALIZE(2);
-+  static constexpr bool passthru_left = false;
-+  static constexpr bool passthru_right = false;
-+  template <typename T> auto
-+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b)
-+}
-+HB_FUNCOBJ (hb_bitwise_and);
-+struct hb_bitwise_or
-+{ HB_PARTIALIZE(2);
-+  static constexpr bool passthru_left = true;
-+  static constexpr bool passthru_right = true;
-+  template <typename T> auto
-+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b)
-+}
-+HB_FUNCOBJ (hb_bitwise_or);
-+struct hb_bitwise_xor
-+{ HB_PARTIALIZE(2);
-+  static constexpr bool passthru_left = true;
-+  static constexpr bool passthru_right = true;
-+  template <typename T> auto
-+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b)
-+}
-+HB_FUNCOBJ (hb_bitwise_xor);
-+struct hb_bitwise_sub
-+{ HB_PARTIALIZE(2);
-+  static constexpr bool passthru_left = true;
-+  static constexpr bool passthru_right = false;
-+  template <typename T> auto
-+  operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
-+}
-+HB_FUNCOBJ (hb_bitwise_sub);
-+
-+struct
-+{ HB_PARTIALIZE(2);
-+  template <typename T, typename T2> auto
-+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
-+}
-+HB_FUNCOBJ (hb_add);
-+struct
-+{ HB_PARTIALIZE(2);
-+  template <typename T, typename T2> auto
-+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a - b)
-+}
-+HB_FUNCOBJ (hb_sub);
-+struct
-+{ HB_PARTIALIZE(2);
-+  template <typename T, typename T2> auto
-+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a * b)
-+}
-+HB_FUNCOBJ (hb_mul);
-+struct
-+{ HB_PARTIALIZE(2);
-+  template <typename T, typename T2> auto
-+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a / b)
-+}
-+HB_FUNCOBJ (hb_div);
-+struct
-+{ HB_PARTIALIZE(2);
-+  template <typename T, typename T2> auto
-+  operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a % b)
-+}
-+HB_FUNCOBJ (hb_mod);
-+struct
-+{
-+  template <typename T> auto
-+  operator () (const T &a) const HB_AUTO_RETURN (+a)
-+}
-+HB_FUNCOBJ (hb_pos);
-+struct
-+{
-+  template <typename T> auto
-+  operator () (const T &a) const HB_AUTO_RETURN (-a)
-+}
-+HB_FUNCOBJ (hb_neg);
-+
-+
-+/* Compiler-assisted vectorization. */
-+
-+/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
-+ * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
-+ * Define that to 0 to disable. */
-+template <typename elt_t, unsigned int byte_size>
-+struct hb_vector_size_t
-+{
-+  elt_t& operator [] (unsigned int i) { return u.v[i]; }
-+  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
-+
-+  void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
-+
-+  template <typename Op>
-+  hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
-+  {
-+    hb_vector_size_t r;
-+#if HB_VECTOR_SIZE
-+    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-+	r.u.vec[i] = op (u.vec[i], o.u.vec[i]);
-+    else
-+#endif
-+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-+	r.u.v[i] = op (u.v[i], o.u.v[i]);
-+    return r;
-+  }
-+  hb_vector_size_t operator | (const hb_vector_size_t &o) const
-+  { return process (hb_bitwise_or, o); }
-+  hb_vector_size_t operator & (const hb_vector_size_t &o) const
-+  { return process (hb_bitwise_and, o); }
-+  hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
-+  { return process (hb_bitwise_xor, o); }
-+  hb_vector_size_t operator ~ () const
-+  {
-+    hb_vector_size_t r;
-+#if HB_VECTOR_SIZE && 0
-+    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
-+      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
-+	r.u.vec[i] = ~u.vec[i];
-+    else
-+#endif
-+    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
-+      r.u.v[i] = ~u.v[i];
-+    return r;
-+  }
-+
-+  private:
-+  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
-+  union {
-+    elt_t v[byte_size / sizeof (elt_t)];
-+#if HB_VECTOR_SIZE
-+    hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
-+#endif
-+  } u;
-+};
-+
-+
-+#endif /* HB_ALGS_HH */
-diff --git a/gfx/harfbuzz/src/hb-array.hh b/gfx/harfbuzz/src/hb-array.hh
---- a/gfx/harfbuzz/src/hb-array.hh
-+++ b/gfx/harfbuzz/src/hb-array.hh
-@@ -23,80 +23,101 @@
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #ifndef HB_ARRAY_HH
- #define HB_ARRAY_HH
- 
- #include "hb.hh"
--#include "hb-dsalgs.hh"
-+#include "hb-algs.hh"
- #include "hb-iter.hh"
- #include "hb-null.hh"
- 
- 
- template <typename Type>
- struct hb_sorted_array_t;
- 
- template <typename Type>
--struct hb_array_t :
--	hb_iter_t<hb_array_t<Type>, Type>,
--	hb_iter_mixin_t<hb_array_t<Type>, Type>
-+struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
- {
-   /*
-    * Constructors.
-    */
--  hb_array_t () : arrayZ (nullptr), length (0) {}
--  hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
--  template <unsigned int length_> hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_) {}
-+  hb_array_t () : arrayZ (nullptr), length (0), backwards_length (0) {}
-+  hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_), backwards_length (0) {}
-+  template <unsigned int length_>
-+  hb_array_t (Type (&array_)[length_]) : arrayZ (array_), length (length_), backwards_length (0) {}
- 
-+  template <typename U,
-+	    hb_enable_if (hb_is_cr_convertible(U, Type))>
-+  hb_array_t (const hb_array_t<U> &o) :
-+    hb_iter_with_fallback_t<hb_array_t<Type>, Type&> (),
-+    arrayZ (o.arrayZ), length (o.length), backwards_length (o.backwards_length) {}
-+  template <typename U,
-+	    hb_enable_if (hb_is_cr_convertible(U, Type))>
-+  hb_array_t& operator = (const hb_array_t<U> &o)
-+  { arrayZ = o.arrayZ; length = o.length; backwards_length = o.backwards_length; return *this; }
- 
-   /*
-    * Iterator implementation.
-    */
--  typedef Type __item_type__;
-+  typedef Type& __item_t__;
-+  static constexpr bool is_random_access_iterator = true;
-   Type& __item_at__ (unsigned i) const
-   {
-     if (unlikely (i >= length)) return CrapOrNull (Type);
-     return arrayZ[i];
-   }
-   void __forward__ (unsigned n)
-   {
-     if (unlikely (n > length))
-       n = length;
-     length -= n;
-+    backwards_length += n;
-     arrayZ += n;
-   }
-   void __rewind__ (unsigned n)
-   {
--    if (unlikely (n > length))
--      n = length;
--    length -= n;
-+    if (unlikely (n > backwards_length))
-+      n = backwards_length;
-+    length += n;
-+    backwards_length -= n;
-+    arrayZ -= n;
-   }
-   unsigned __len__ () const { return length; }
--  bool __random_access__ () const { return true; }
-+  /* Ouch. The operator== compares the contents of the array.  For range-based for loops,
-+   * it's best if we can just compare arrayZ, though comparing contents is still fast,
-+   * but also would require that Type has operator==.  As such, we optimize this operator
-+   * for range-based for loop and just compare arrayZ.  No need to compare length, as we
-+   * assume we're only compared to .end(). */
-+  bool operator != (const hb_array_t& o) const
-+  { return arrayZ != o.arrayZ; }
- 
-   /* Extra operators.
-    */
-   Type * operator & () const { return arrayZ; }
-   operator hb_array_t<const Type> () { return hb_array_t<const Type> (arrayZ, length); }
-   template <typename T> operator T * () const { return arrayZ; }
- 
-+  HB_INTERNAL bool operator == (const hb_array_t &o) const;
-+  HB_INTERNAL uint32_t hash () const;
-+
-   /*
-    * Compare, Sort, and Search.
-    */
- 
-   /* Note: our compare is NOT lexicographic; it also does NOT call Type::cmp. */
-   int cmp (const hb_array_t<Type> &a) const
-   {
-     if (length != a.length)
-       return (int) a.length - (int) length;
-     return hb_memcmp (a.arrayZ, arrayZ, get_size ());
-   }
--  static int cmp (const void *pa, const void *pb)
-+  HB_INTERNAL static int cmp (const void *pa, const void *pb)
-   {
-     hb_array_t<Type> *a = (hb_array_t<Type> *) pa;
-     hb_array_t<Type> *b = (hb_array_t<Type> *) pb;
-     return b->cmp (*a);
-   }
- 
-   template <typename T>
-   Type *lsearch (const T &x, Type *not_found = nullptr)
-@@ -126,17 +147,17 @@ struct hb_array_t :
-   hb_sorted_array_t<Type> qsort ()
-   {
-     if (likely (length))
-       ::qsort (arrayZ, length, this->item_size, Type::cmp);
-     return hb_sorted_array_t<Type> (*this);
-   }
-   void qsort (unsigned int start, unsigned int end)
-   {
--    end = MIN (end, length);
-+    end = hb_min (end, length);
-     assert (start <= end);
-     if (likely (start < end))
-       ::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
-   }
- 
-   /*
-    * Other methods.
-    */
-@@ -149,63 +170,92 @@ struct hb_array_t :
-       return *this;
- 
-     unsigned int count = length;
-     if (unlikely (start_offset > count))
-       count = 0;
-     else
-       count -= start_offset;
-     if (seg_count)
--      count = *seg_count = MIN (count, *seg_count);
-+      count = *seg_count = hb_min (count, *seg_count);
-     return hb_array_t<Type> (arrayZ + start_offset, count);
-   }
-   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
-   { return sub_array (start_offset, &seg_count); }
- 
-   /* Only call if you allocated the underlying array using malloc() or similar. */
-   void free ()
-   { ::free ((void *) arrayZ); arrayZ = nullptr; length = 0; }
- 
-+  template <typename hb_serialize_context_t>
-+  hb_array_t copy (hb_serialize_context_t *c) const
-+  {
-+    TRACE_SERIALIZE (this);
-+    auto* out = c->start_embed (arrayZ);
-+    if (unlikely (!c->extend_size (out, get_size ()))) return_trace (hb_array_t ());
-+    for (unsigned i = 0; i < length; i++)
-+      out[i] = arrayZ[i]; /* TODO: add version that calls c->copy() */
-+    return_trace (hb_array_t (out, length));
-+  }
-+
-   template <typename hb_sanitize_context_t>
-   bool sanitize (hb_sanitize_context_t *c) const
-   { return c->check_array (arrayZ, length); }
- 
-   /*
-    * Members
-    */
- 
-   public:
-   Type *arrayZ;
-   unsigned int length;
-+  unsigned int backwards_length;
- };
- template <typename T> inline hb_array_t<T>
- hb_array (T *array, unsigned int length)
- { return hb_array_t<T> (array, length); }
- template <typename T, unsigned int length_> inline hb_array_t<T>
- hb_array (T (&array_)[length_])
- { return hb_array_t<T> (array_); }
- 
--
- enum hb_bfind_not_found_t
- {
-   HB_BFIND_NOT_FOUND_DONT_STORE,
-   HB_BFIND_NOT_FOUND_STORE,
-   HB_BFIND_NOT_FOUND_STORE_CLOSEST,
- };
- 
- template <typename Type>
- struct hb_sorted_array_t :
--	hb_sorted_iter_t<hb_sorted_array_t<Type>, Type>,
--	hb_array_t<Type>,
--	hb_iter_mixin_t<hb_sorted_array_t<Type>, Type>
-+	hb_iter_t<hb_sorted_array_t<Type>, Type&>,
-+	hb_array_t<Type>
- {
-+  typedef hb_iter_t<hb_sorted_array_t<Type>, Type&> iter_base_t;
-+  HB_ITER_USING (iter_base_t);
-+  static constexpr bool is_random_access_iterator = true;
-+  static constexpr bool is_sorted_iterator = true;
-+
-   hb_sorted_array_t () : hb_array_t<Type> () {}
--  hb_sorted_array_t (const hb_array_t<Type> &o) : hb_array_t<Type> (o) {}
-   hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
--  template <unsigned int length_> hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
-+  template <unsigned int length_>
-+  hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
-+
-+  template <typename U,
-+	    hb_enable_if (hb_is_cr_convertible(U, Type))>
-+  hb_sorted_array_t (const hb_array_t<U> &o) :
-+    hb_iter_t<hb_sorted_array_t<Type>, Type&> (),
-+    hb_array_t<Type> (o) {}
-+  template <typename U,
-+	    hb_enable_if (hb_is_cr_convertible(U, Type))>
-+  hb_sorted_array_t& operator = (const hb_array_t<U> &o)
-+  { hb_array_t<Type> (*this) = o; return *this; }
-+
-+  /* Iterator implementation. */
-+  bool operator != (const hb_sorted_array_t& o) const
-+  { return this->arrayZ != o.arrayZ || this->length != o.length; }
- 
-   hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *seg_count /* IN/OUT */) const
-   { return hb_sorted_array_t<Type> (((const hb_array_t<Type> *) (this))->sub_array (start_offset, seg_count)); }
-   hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int seg_count) const
-   { return sub_array (start_offset, &seg_count); }
- 
-   template <typename T>
-   Type *bsearch (const T &x, Type *not_found = nullptr)
-@@ -264,14 +314,35 @@ struct hb_sorted_array_t :
- };
- template <typename T> inline hb_sorted_array_t<T>
- hb_sorted_array (T *array, unsigned int length)
- { return hb_sorted_array_t<T> (array, length); }
- template <typename T, unsigned int length_> inline hb_sorted_array_t<T>
- hb_sorted_array (T (&array_)[length_])
- { return hb_sorted_array_t<T> (array_); }
- 
-+template <typename T>
-+bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
-+{
-+  return length == o.length &&
-+  + hb_zip (*this, o)
-+  | hb_map ([] (hb_pair_t<T&, T&> &&_) { return _.first == _.second; })
-+  | hb_all
-+  ;
-+}
-+template <typename T>
-+uint32_t hb_array_t<T>::hash () const
-+{
-+  return
-+  + hb_iter (*this)
-+  | hb_map (hb_hash)
-+  | hb_reduce ([] (uint32_t a, uint32_t b) { return a * 31 + b; }, 0)
-+  ;
-+}
- 
- typedef hb_array_t<const char> hb_bytes_t;
- typedef hb_array_t<const unsigned char> hb_ubytes_t;
- 
-+/* TODO Specialize opeator==/hash() for hb_bytes_t and hb_ubytes_t. */
-+//template <>
-+//uint32_t hb_array_t<const char>::hash () const { return 0; }
- 
- #endif /* HB_ARRAY_HH */
-diff --git a/gfx/harfbuzz/src/hb-atomic.hh b/gfx/harfbuzz/src/hb-atomic.hh
---- a/gfx/harfbuzz/src/hb-atomic.hh
-+++ b/gfx/harfbuzz/src/hb-atomic.hh
-@@ -28,16 +28,17 @@
-  * Red Hat Author(s): Behdad Esfahbod
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #ifndef HB_ATOMIC_HH
- #define HB_ATOMIC_HH
- 
- #include "hb.hh"
-+#include "hb-meta.hh"
- 
- 
- /*
-  * Atomic integers and pointers.
-  */
- 
- 
- /* We need external help for these */
-@@ -101,17 +102,17 @@ static inline bool
- 
- 
- #elif !defined(HB_NO_MT) && defined(_WIN32)
- 
- #include <windows.h>
- 
- static inline void _hb_memory_barrier ()
- {
--#if !defined(MemoryBarrier)
-+#ifndef MemoryBarrier
-   /* MinGW has a convoluted history of supporting MemoryBarrier. */
-   LONG dummy = 0;
-   InterlockedExchange (&dummy, 1);
- #else
-   MemoryBarrier ();
- #endif
- }
- #define _hb_memory_barrier()			_hb_memory_barrier ()
-@@ -210,28 +211,28 @@ static inline bool _hb_compare_and_swapl
- #define hb_atomic_ptr_impl_cmpexch(P,O,N)       _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N))
- static_assert ((sizeof (long) == sizeof (void *)), "");
- 
- 
- #elif !defined(HB_NO_MT)
- 
- #define HB_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
- 
--#define _hb_memory_barrier()
-+#define _hb_memory_barrier()			do {} while (0)
- 
- #define hb_atomic_int_impl_add(AI, V)		((*(AI) += (V)) - (V))
- 
- #define hb_atomic_ptr_impl_cmpexch(P,O,N)	(* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
- 
- 
- #else /* HB_NO_MT */
- 
- #define hb_atomic_int_impl_add(AI, V)		((*(AI) += (V)) - (V))
- 
--#define _hb_memory_barrier()
-+#define _hb_memory_barrier()			do {} while (0)
- 
- #define hb_atomic_ptr_impl_cmpexch(P,O,N)	(* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
- 
- 
- #endif
- 
- 
- #ifndef _hb_memory_r_barrier
-@@ -277,17 +278,17 @@ struct hb_atomic_int_t
-   int v;
- };
- 
- 
- #define HB_ATOMIC_PTR_INIT(V)          {V}
- template <typename P>
- struct hb_atomic_ptr_t
- {
--  typedef typename hb_remove_pointer (P) T;
-+  typedef hb_remove_pointer<P> T;
- 
-   void init (T* v_ = nullptr) { set_relaxed (v_); }
-   void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); }
-   T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); }
-   T *get () const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); }
-   bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); }
- 
-   T * operator -> () const                    { return get (); }
-diff --git a/gfx/harfbuzz/src/hb-blob.cc b/gfx/harfbuzz/src/hb-blob.cc
---- a/gfx/harfbuzz/src/hb-blob.cc
-+++ b/gfx/harfbuzz/src/hb-blob.cc
-@@ -25,17 +25,17 @@
-  * Red Hat Author(s): Behdad Esfahbod
-  */
- 
- 
- /* https://github.com/harfbuzz/harfbuzz/issues/1308
-  * http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
-  * https://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html
-  */
--#ifndef _POSIX_C_SOURCE
-+#if !defined(_POSIX_C_SOURCE) && !defined(_MSC_VER) && !defined(__NetBSD__)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-macros"
- #define _POSIX_C_SOURCE 200809L
- #pragma GCC diagnostic pop
- #endif
- 
- #include "hb.hh"
- #include "hb-blob.hh"
-@@ -150,17 +150,17 @@ hb_blob_create_sub_blob (hb_blob_t    *p
-   hb_blob_t *blob;
- 
-   if (!length || !parent || offset >= parent->length)
-     return hb_blob_get_empty ();
- 
-   hb_blob_make_immutable (parent);
- 
-   blob = hb_blob_create (parent->data + offset,
--			 MIN (length, parent->length - offset),
-+			 hb_min (length, parent->length - offset),
- 			 HB_MEMORY_MODE_READONLY,
- 			 hb_blob_reference (parent),
- 			 _hb_blob_destroy);
- 
-   return blob;
- }
- 
- /**
-diff --git a/gfx/harfbuzz/src/hb-blob.h b/gfx/harfbuzz/src/hb-blob.h
---- a/gfx/harfbuzz/src/hb-blob.h
-+++ b/gfx/harfbuzz/src/hb-blob.h
-@@ -66,16 +66,19 @@ typedef struct hb_blob_t hb_blob_t;
- 
- HB_EXTERN hb_blob_t *
- hb_blob_create (const char        *data,
- 		unsigned int       length,
- 		hb_memory_mode_t   mode,
- 		void              *user_data,
- 		hb_destroy_func_t  destroy);
- 
-+HB_EXTERN hb_blob_t *
-+hb_blob_create_from_file (const char *file_name);
-+
- /* Always creates with MEMORY_MODE_READONLY.
-  * Even if the parent blob is writable, we don't
-  * want the user of the sub-blob to be able to
-  * modify the parent data as that data may be
-  * shared among multiple sub-blobs.
-  */
- HB_EXTERN hb_blob_t *
- hb_blob_create_sub_blob (hb_blob_t    *parent,
-@@ -118,14 +121,11 @@ HB_EXTERN unsigned int
- hb_blob_get_length (hb_blob_t *blob);
- 
- HB_EXTERN const char *
- hb_blob_get_data (hb_blob_t *blob, unsigned int *length);
- 
- HB_EXTERN char *
- hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length);
- 
--HB_EXTERN hb_blob_t *
--hb_blob_create_from_file (const char *file_name);
--
- HB_END_DECLS
- 
- #endif /* HB_BLOB_H */
-diff --git a/gfx/harfbuzz/src/hb-blob.hh b/gfx/harfbuzz/src/hb-blob.hh
---- a/gfx/harfbuzz/src/hb-blob.hh
-+++ b/gfx/harfbuzz/src/hb-blob.hh
-@@ -76,17 +76,17 @@ struct hb_blob_t
- 
- /*
-  * hb_blob_ptr_t
-  */
- 
- template <typename P>
- struct hb_blob_ptr_t
- {
--  typedef typename hb_remove_pointer (P) T;
-+  typedef hb_remove_pointer<P> T;
- 
-   hb_blob_ptr_t (hb_blob_t *b_ = nullptr) : b (b_) {}
-   hb_blob_t * operator = (hb_blob_t *b_) { return b = b_; }
-   const T * operator -> () const { return get (); }
-   const T & operator * () const  { return *get (); }
-   template <typename C> operator const C * () const { return get (); }
-   operator const char * () const { return (const char *) get (); }
-   const T * get () const { return b->as<T> (); }
-diff --git a/gfx/harfbuzz/src/hb-buffer-serialize.cc b/gfx/harfbuzz/src/hb-buffer-serialize.cc
---- a/gfx/harfbuzz/src/hb-buffer-serialize.cc
-+++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc
-@@ -23,18 +23,20 @@
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb-buffer.hh"
- 
- 
- static const char *serialize_formats[] = {
-+#ifndef HB_NO_BUFFER_SERIALIZE
-   "text",
-   "json",
-+#endif
-   nullptr
- };
- 
- /**
-  * hb_buffer_serialize_list_formats:
-  *
-  * Returns a list of supported buffer serialization formats.
-  *
-@@ -80,20 +82,22 @@ hb_buffer_serialize_format_from_string (
-  * Return value: (transfer none):
-  * A %NULL terminated string corresponding to @format. Should not be freed.
-  *
-  * Since: 0.9.7
-  **/
- const char *
- hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
- {
--  switch (format)
-+  switch ((unsigned) format)
-   {
-+#ifndef HB_NO_BUFFER_SERIALIZE
-     case HB_BUFFER_SERIALIZE_FORMAT_TEXT:	return serialize_formats[0];
-     case HB_BUFFER_SERIALIZE_FORMAT_JSON:	return serialize_formats[1];
-+#endif
-     default:
-     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:	return nullptr;
-   }
- }
- 
- static unsigned int
- _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
- 				  unsigned int start,
-@@ -133,44 +137,44 @@ static unsigned int
-       for (char *q = g; *q; q++) {
-         if (*q == '"')
- 	  *p++ = '\\';
- 	*p++ = *q;
-       }
-       *p++ = '"';
-     }
-     else
--      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
-+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
- 
-     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
--      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
-+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster));
-     }
- 
-     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
-     {
--      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
-+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
- 			     x+pos[i].x_offset, y+pos[i].y_offset));
-       if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
--	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
-+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
- 			       pos[i].x_advance, pos[i].y_advance));
-     }
- 
-     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
-     {
-       if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
--	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
-+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"fl\":%u", info[i].mask & HB_GLYPH_FLAG_DEFINED));
-     }
- 
-     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
-     {
-       hb_glyph_extents_t extents;
-       hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
--      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
-+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"xb\":%d,\"yb\":%d",
- 		extents.x_bearing, extents.y_bearing));
--      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
-+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"w\":%d,\"h\":%d",
- 		extents.width, extents.height));
-     }
- 
-     *p++ = '}';
- 
-     unsigned int l = p - b;
-     if (buf_size > l)
-     {
-@@ -219,47 +223,47 @@ static unsigned int
-       *p++ = '|';
- 
-     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
-     {
-       hb_font_glyph_to_string (font, info[i].codepoint, p, 128);
-       p += strlen (p);
-     }
-     else
--      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
-+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint));
- 
-     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
--      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
-+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster));
-     }
- 
-     if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
-     {
-       if (x+pos[i].x_offset || y+pos[i].y_offset)
--	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
-+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", x+pos[i].x_offset, y+pos[i].y_offset));
- 
-       if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES))
-       {
- 	*p++ = '+';
--	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
-+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance));
- 	if (pos[i].y_advance)
--	  p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
-+	  p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance));
-       }
-     }
- 
-     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS)
-     {
-       if (info[i].mask & HB_GLYPH_FLAG_DEFINED)
--	p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
-+	p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "#%X", info[i].mask &HB_GLYPH_FLAG_DEFINED));
-     }
- 
-     if (flags & HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS)
-     {
-       hb_glyph_extents_t extents;
-       hb_font_get_glyph_extents(font, info[i].codepoint, &extents);
--      p += MAX (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
-+      p += hb_max (0, snprintf (p, ARRAY_LENGTH (b) - (p - b), "<%d,%d,%d,%d>", extents.x_bearing, extents.y_bearing, extents.width, extents.height));
-     }
- 
-     unsigned int l = p - b;
-     if (buf_size > l)
-     {
-       memcpy (buf, b, l);
-       buf += l;
-       buf_size -= l;
-@@ -339,16 +343,20 @@ hb_buffer_serialize_glyphs (hb_buffer_t 
- 
-   unsigned int sconsumed;
-   if (!buf_consumed)
-     buf_consumed = &sconsumed;
-   *buf_consumed = 0;
-   if (buf_size)
-     *buf = '\0';
- 
-+#ifdef HB_NO_BUFFER_SERIALIZE
-+  return 0;
-+#endif
-+
-   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
- 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
- 
-   if (!buffer->have_positions)
-     flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
- 
-   if (unlikely (start == end))
-     return 0;
-@@ -375,17 +383,17 @@ hb_buffer_serialize_glyphs (hb_buffer_t 
-   }
- }
- 
- 
- static hb_bool_t
- parse_uint (const char *pp, const char *end, uint32_t *pv)
- {
-   char buf[32];
--  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
-+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
-   strncpy (buf, pp, len);
-   buf[len] = '\0';
- 
-   char *p = buf;
-   char *pend = p;
-   uint32_t v;
- 
-   errno = 0;
-@@ -396,17 +404,17 @@ parse_uint (const char *pp, const char *
-   *pv = v;
-   return true;
- }
- 
- static hb_bool_t
- parse_int (const char *pp, const char *end, int32_t *pv)
- {
-   char buf[32];
--  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
-+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - pp));
-   strncpy (buf, pp, len);
-   buf[len] = '\0';
- 
-   char *p = buf;
-   char *pend = p;
-   int32_t v;
- 
-   errno = 0;
-@@ -444,16 +452,20 @@ hb_buffer_deserialize_glyphs (hb_buffer_
- 			      hb_font_t *font, /* May be NULL */
- 			      hb_buffer_serialize_format_t format)
- {
-   const char *end;
-   if (!end_ptr)
-     end_ptr = &end;
-   *end_ptr = buf;
- 
-+#ifdef HB_NO_BUFFER_SERIALIZE
-+  return false;
-+#endif
-+
-   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
- 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
- 
-   if (buf_len == -1)
-     buf_len = strlen (buf);
- 
-   if (!buf_len)
-   {
-diff --git a/gfx/harfbuzz/src/hb-buffer.cc b/gfx/harfbuzz/src/hb-buffer.cc
---- a/gfx/harfbuzz/src/hb-buffer.cc
-+++ b/gfx/harfbuzz/src/hb-buffer.cc
-@@ -519,17 +519,17 @@ hb_buffer_t::merge_clusters_impl (unsign
-   {
-     unsafe_to_break (start, end);
-     return;
-   }
- 
-   unsigned int cluster = info[start].cluster;
- 
-   for (unsigned int i = start + 1; i < end; i++)
--    cluster = MIN<unsigned int> (cluster, info[i].cluster);
-+    cluster = hb_min (cluster, info[i].cluster);
- 
-   /* Extend end */
-   while (end < len && info[end - 1].cluster == info[end].cluster)
-     end++;
- 
-   /* Extend start */
-   while (idx < start && info[start - 1].cluster == info[start].cluster)
-     start--;
-@@ -550,17 +550,17 @@ hb_buffer_t::merge_out_clusters (unsigne
-     return;
- 
-   if (unlikely (end - start < 2))
-     return;
- 
-   unsigned int cluster = out_info[start].cluster;
- 
-   for (unsigned int i = start + 1; i < end; i++)
--    cluster = MIN<unsigned int> (cluster, out_info[i].cluster);
-+    cluster = hb_min (cluster, out_info[i].cluster);
- 
-   /* Extend start */
-   while (start && out_info[start - 1].cluster == out_info[start].cluster)
-     start--;
- 
-   /* Extend end */
-   while (end < out_len && out_info[end - 1].cluster == out_info[end].cluster)
-     end++;
-diff --git a/gfx/harfbuzz/src/hb-buffer.hh b/gfx/harfbuzz/src/hb-buffer.hh
---- a/gfx/harfbuzz/src/hb-buffer.hh
-+++ b/gfx/harfbuzz/src/hb-buffer.hh
-@@ -374,17 +374,17 @@ struct hb_buffer_t
-   }
- 
-   int
-   _unsafe_to_break_find_min_cluster (const hb_glyph_info_t *infos,
- 				     unsigned int start, unsigned int end,
- 				     unsigned int cluster) const
-   {
-     for (unsigned int i = start; i < end; i++)
--      cluster = MIN<unsigned int> (cluster, infos[i].cluster);
-+      cluster = hb_min (cluster, infos[i].cluster);
-     return cluster;
-   }
-   void
-   _unsafe_to_break_set_mask (hb_glyph_info_t *infos,
- 			     unsigned int start, unsigned int end,
- 			     unsigned int cluster)
-   {
-     for (unsigned int i = start; i < end; i++)
-diff --git a/gfx/harfbuzz/src/hb-cff-interp-common.hh b/gfx/harfbuzz/src/hb-cff-interp-common.hh
---- a/gfx/harfbuzz/src/hb-cff-interp-common.hh
-+++ b/gfx/harfbuzz/src/hb-cff-interp-common.hh
-@@ -267,21 +267,21 @@ struct UnsizedByteStr : UnsizedArrayOf <
-   {
-     TRACE_SERIALIZE (this);
- 
-     if (unlikely ((value < minVal || value > maxVal)))
-       return_trace (false);
- 
-     HBUINT8 *p = c->allocate_size<HBUINT8> (1);
-     if (unlikely (p == nullptr)) return_trace (false);
--    p->set (intOp);
-+    *p = intOp;
- 
-     INTTYPE *ip = c->allocate_size<INTTYPE> (INTTYPE::static_size);
-     if (unlikely (ip == nullptr)) return_trace (false);
--    ip->set ((unsigned int)value);
-+    *ip = (unsigned int) value;
- 
-     return_trace (true);
-   }
- 
-   static bool serialize_int4 (hb_serialize_context_t *c, int value)
-   { return serialize_int<HBUINT32, 0, 0x7FFFFFFF> (c, OpCode_longintdict, value); }
- 
-   static bool serialize_int2 (hb_serialize_context_t *c, int value)
-@@ -686,17 +686,17 @@ struct opset_t
-       case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
-       case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
- 	env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.str_ref[0] + 108));
- 	env.str_ref.inc ();
- 	break;
- 
-       case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
-       case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
--	env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
-+	env.argStack.push_int ((-(int16_t)(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
- 	env.str_ref.inc ();
- 	break;
- 
-       default:
- 	/* 1-byte integer */
- 	if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)))
- 	{
- 	  env.argStack.push_int ((int)op - 139);
-diff --git a/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh b/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
---- a/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
-+++ b/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
-@@ -142,45 +142,46 @@ struct cs_interp_env_t : interp_env_t<AR
-     localSubrs.fini ();
-   }
- 
-   bool in_error () const
-   {
-     return callStack.in_error () || SUPER::in_error ();
-   }
- 
--  bool popSubrNum (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
-+  bool pop_subr_num (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num)
-   {
-+    subr_num = 0;
-     int n = SUPER::argStack.pop_int ();
-     n += biasedSubrs.get_bias ();
-     if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ())))
-       return false;
- 
-     subr_num = (unsigned int)n;
-     return true;
-   }
- 
--  void callSubr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
-+  void call_subr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type)
-   {
--    unsigned int subr_num;
-+    unsigned int subr_num = 0;
- 
--    if (unlikely (!popSubrNum (biasedSubrs, subr_num)
-+    if (unlikely (!pop_subr_num (biasedSubrs, subr_num)
- 		 || callStack.get_count () >= kMaxCallLimit))
-     {
-       SUPER::set_error ();
-       return;
-     }
-     context.str_ref = SUPER::str_ref;
-     callStack.push (context);
- 
-     context.init ( biasedSubrs[subr_num], type, subr_num);
-     SUPER::str_ref = context.str_ref;
-   }
- 
--  void returnFromSubr ()
-+  void return_from_subr ()
-   {
-     if (unlikely (SUPER::str_ref.in_error ()))
-       SUPER::set_error ();
-     context = callStack.pop ();
-     SUPER::str_ref = context.str_ref;
-   }
- 
-   void determine_hintmask_size ()
-@@ -241,42 +242,42 @@ struct path_procs_null_t
-   static void line (ENV &env, PARAM& param, const point_t &pt1) {}
-   static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) {}
-   static void hflex (ENV &env, PARAM& param) {}
-   static void flex (ENV &env, PARAM& param) {}
-   static void hflex1 (ENV &env, PARAM& param) {}
-   static void flex1 (ENV &env, PARAM& param) {}
- };
- 
--template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM> >
-+template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM>>
- struct cs_opset_t : opset_t<ARG>
- {
-   static void process_op (op_code_t op, ENV &env, PARAM& param)
-   {
-     switch (op) {
- 
-       case OpCode_return:
--	env.returnFromSubr ();
-+	env.return_from_subr ();
- 	break;
-       case OpCode_endchar:
- 	OPSET::check_width (op, env, param);
- 	env.set_endchar (true);
- 	OPSET::flush_args_and_op (op, env, param);
- 	break;
- 
-       case OpCode_fixedcs:
- 	env.argStack.push_fixed_from_substr (env.str_ref);
- 	break;
- 
-       case OpCode_callsubr:
--	env.callSubr (env.localSubrs, CSType_LocalSubr);
-+	env.call_subr (env.localSubrs, CSType_LocalSubr);
- 	break;
- 
-       case OpCode_callgsubr:
--	env.callSubr (env.globalSubrs, CSType_GlobalSubr);
-+	env.call_subr (env.globalSubrs, CSType_GlobalSubr);
- 	break;
- 
-       case OpCode_hstem:
-       case OpCode_hstemhm:
- 	OPSET::check_width (op, env, param);
- 	OPSET::process_hstem (op, env, param);
- 	break;
-       case OpCode_vstem:
-diff --git a/gfx/harfbuzz/src/hb-cff1-interp-cs.hh b/gfx/harfbuzz/src/hb-cff1-interp-cs.hh
---- a/gfx/harfbuzz/src/hb-cff1-interp-cs.hh
-+++ b/gfx/harfbuzz/src/hb-cff1-interp-cs.hh
-@@ -76,17 +76,17 @@ struct cff1_cs_interp_env_t : cs_interp_
-   unsigned int  arg_start;
-   number_t	width;
-   bool	  in_seac;
- 
-   private:
-   typedef cs_interp_env_t<number_t, CFF1Subrs> SUPER;
- };
- 
--template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM> >
-+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff1_cs_interp_env_t, PARAM>>
- struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM, PATH>
- {
-   /* PostScript-originated legacy opcodes (OpCode_add etc) are unsupported */
-   /* Type 1-originated deprecated opcodes, seac behavior of endchar and dotsection are supported */
- 
-   static void process_op (op_code_t op, cff1_cs_interp_env_t &env, PARAM& param)
-   {
-     switch (op) {
-diff --git a/gfx/harfbuzz/src/hb-cff2-interp-cs.hh b/gfx/harfbuzz/src/hb-cff2-interp-cs.hh
---- a/gfx/harfbuzz/src/hb-cff2-interp-cs.hh
-+++ b/gfx/harfbuzz/src/hb-cff2-interp-cs.hh
-@@ -188,17 +188,17 @@ struct cff2_cs_interp_env_t : cs_interp_
-   unsigned int  ivs;
-   hb_vector_t<float>  scalars;
-   bool	  do_blend;
-   bool	  seen_vsindex_;
-   bool	  seen_blend;
- 
-   typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
- };
--template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM> >
-+template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM>>
- struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
- {
-   static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
-   {
-     switch (op) {
-       case OpCode_callsubr:
-       case OpCode_callgsubr:
- 	/* a subroutine number shoudln't be a blended value */
-diff --git a/gfx/harfbuzz/src/hb-common.cc b/gfx/harfbuzz/src/hb-common.cc
---- a/gfx/harfbuzz/src/hb-common.cc
-+++ b/gfx/harfbuzz/src/hb-common.cc
-@@ -62,17 +62,17 @@ void
-   {
-     while (*c)
-     {
-       const char *p = strchr (c, ':');
-       if (!p)
-         p = c + strlen (c);
- 
- #define OPTION(name, symbol) \
--	if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) u.opts.symbol = true;
-+	if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) do { u.opts.symbol = true; } while (0)
- 
-       OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
-       OPTION ("aat", aat);
- 
- #undef OPTION
- 
-       c = *p ? p + 1 : p;
-     }
-@@ -351,17 +351,17 @@ hb_language_from_string (const char *str
-   if (!str || !len || !*str)
-     return HB_LANGUAGE_INVALID;
- 
-   hb_language_item_t *item = nullptr;
-   if (len >= 0)
-   {
-     /* NUL-terminate it. */
-     char strbuf[64];
--    len = MIN (len, (int) sizeof (strbuf) - 1);
-+    len = hb_min (len, (int) sizeof (strbuf) - 1);
-     memcpy (strbuf, str, len);
-     strbuf[len] = '\0';
-     item = lang_find_or_insert (strbuf);
-   }
-   else
-     item = lang_find_or_insert (str);
- 
-   return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
-@@ -483,17 +483,17 @@ hb_script_from_iso15924_tag (hb_tag_t ta
- hb_script_t
- hb_script_from_string (const char *str, int len)
- {
-   return hb_script_from_iso15924_tag (hb_tag_from_string (str, len));
- }
- 
- /**
-  * hb_script_to_iso15924_tag:
-- * @script: an #hb_script_ to convert.
-+ * @script: an #hb_script_t to convert.
-  *
-  * See hb_script_from_iso15924_tag().
-  *
-  * Return value:
-  * An #hb_tag_t representing an ISO 15924 script tag.
-  *
-  * Since: 0.9.2
-  **/
-@@ -715,17 +715,17 @@ parse_char (const char **pp, const char 
-   (*pp)++;
-   return true;
- }
- 
- static bool
- parse_uint (const char **pp, const char *end, unsigned int *pv)
- {
-   char buf[32];
--  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-   strncpy (buf, *pp, len);
-   buf[len] = '\0';
- 
-   char *p = buf;
-   char *pend = p;
-   unsigned int v;
- 
-   /* Intentionally use strtol instead of strtoul, such that
-@@ -739,17 +739,17 @@ parse_uint (const char **pp, const char 
-   *pp += pend - p;
-   return true;
- }
- 
- static bool
- parse_uint32 (const char **pp, const char *end, uint32_t *pv)
- {
-   char buf[32];
--  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-   strncpy (buf, *pp, len);
-   buf[len] = '\0';
- 
-   char *p = buf;
-   char *pend = p;
-   unsigned int v;
- 
-   /* Intentionally use strtol instead of strtoul, such that
-@@ -778,17 +778,17 @@ parse_uint32 (const char **pp, const cha
- #endif
- 
- #ifdef USE_XLOCALE
- 
- #if HB_USE_ATEXIT
- static void free_static_C_locale ();
- #endif
- 
--static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (HB_LOCALE_T),
-+static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<HB_LOCALE_T>,
- 							  hb_C_locale_lazy_loader_t>
- {
-   static HB_LOCALE_T create ()
-   {
-     HB_LOCALE_T C_locale = HB_CREATE_LOCALE ("C");
- 
- #if HB_USE_ATEXIT
-     atexit (free_static_C_locale);
-@@ -820,17 +820,17 @@ get_C_locale ()
-   return static_C_locale.get_unconst ();
- }
- #endif /* USE_XLOCALE */
- 
- static bool
- parse_float (const char **pp, const char *end, float *pv)
- {
-   char buf[32];
--  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-+  unsigned int len = hb_min (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
-   strncpy (buf, *pp, len);
-   buf[len] = '\0';
- 
-   char *p = buf;
-   char *pend = p;
-   float v;
- 
-   errno = 0;
-@@ -1066,31 +1066,31 @@ hb_feature_to_string (hb_feature_t *feat
-   hb_tag_to_string (feature->tag, s + len);
-   len += 4;
-   while (len && s[len - 1] == ' ')
-     len--;
-   if (feature->start != 0 || feature->end != (unsigned int) -1)
-   {
-     s[len++] = '[';
-     if (feature->start)
--      len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
-+      len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->start));
-     if (feature->end != feature->start + 1) {
-       s[len++] = ':';
-       if (feature->end != (unsigned int) -1)
--	len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
-+	len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->end));
-     }
-     s[len++] = ']';
-   }
-   if (feature->value > 1)
-   {
-     s[len++] = '=';
--    len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
-+    len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%u", feature->value));
-   }
-   assert (len < ARRAY_LENGTH (s));
--  len = MIN (len, size - 1);
-+  len = hb_min (len, size - 1);
-   memcpy (buf, s, len);
-   buf[len] = '\0';
- }
- 
- /* hb_variation_t */
- 
- static bool
- parse_variation_value (const char **pp, const char *end, hb_variation_t *variation)
-@@ -1147,24 +1147,81 @@ hb_variation_to_string (hb_variation_t *
- 
-   char s[128];
-   unsigned int len = 0;
-   hb_tag_to_string (variation->tag, s + len);
-   len += 4;
-   while (len && s[len - 1] == ' ')
-     len--;
-   s[len++] = '=';
--  len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
-+  len += hb_max (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%g", (double) variation->value));
- 
-   assert (len < ARRAY_LENGTH (s));
--  len = MIN (len, size - 1);
-+  len = hb_min (len, size - 1);
-   memcpy (buf, s, len);
-   buf[len] = '\0';
- }
- 
-+/**
-+ * hb_color_get_alpha:
-+ * color: a #hb_color_t we are interested in its channels.
-+ *
-+ * Return value: Alpha channel value of the given color
-+ *
-+ * Since: 2.1.0
-+ */
-+uint8_t
-+(hb_color_get_alpha) (hb_color_t color)
-+{
-+  return hb_color_get_alpha (color);
-+}
-+
-+/**
-+ * hb_color_get_red:
-+ * color: a #hb_color_t we are interested in its channels.
-+ *
-+ * Return value: Red channel value of the given color
-+ *
-+ * Since: 2.1.0
-+ */
-+uint8_t
-+(hb_color_get_red) (hb_color_t color)
-+{
-+  return hb_color_get_red (color);
-+}
-+
-+/**
-+ * hb_color_get_green:
-+ * color: a #hb_color_t we are interested in its channels.
-+ *
-+ * Return value: Green channel value of the given color
-+ *
-+ * Since: 2.1.0
-+ */
-+uint8_t
-+(hb_color_get_green) (hb_color_t color)
-+{
-+  return hb_color_get_green (color);
-+}
-+
-+/**
-+ * hb_color_get_blue:
-+ * color: a #hb_color_t we are interested in its channels.
-+ *
-+ * Return value: Blue channel value of the given color
-+ *
-+ * Since: 2.1.0
-+ */
-+uint8_t
-+(hb_color_get_blue) (hb_color_t color)
-+{
-+  return hb_color_get_blue (color);
-+}
-+
-+
- /* If there is no visibility control, then hb-static.cc will NOT
-  * define anything.  Instead, we get it to define one set in here
-  * only, so only libharfbuzz.so defines them, not other libs. */
- #ifdef HB_NO_VISIBILITY
- #undef HB_NO_VISIBILITY
- #include "hb-static.cc"
- #define HB_NO_VISIBILITY 1
- #endif
-diff --git a/gfx/harfbuzz/src/hb-common.h b/gfx/harfbuzz/src/hb-common.h
---- a/gfx/harfbuzz/src/hb-common.h
-+++ b/gfx/harfbuzz/src/hb-common.h
-@@ -353,17 +353,17 @@ typedef enum
-   /*11.0*/HB_SCRIPT_GUNJALA_GONDI		= HB_TAG ('G','o','n','g'),
-   /*11.0*/HB_SCRIPT_HANIFI_ROHINGYA		= HB_TAG ('R','o','h','g'),
-   /*11.0*/HB_SCRIPT_MAKASAR			= HB_TAG ('M','a','k','a'),
-   /*11.0*/HB_SCRIPT_MEDEFAIDRIN			= HB_TAG ('M','e','d','f'),
-   /*11.0*/HB_SCRIPT_OLD_SOGDIAN			= HB_TAG ('S','o','g','o'),
-   /*11.0*/HB_SCRIPT_SOGDIAN			= HB_TAG ('S','o','g','d'),
- 
-   /*
--   * Since REPLACEME
-+   * Since 2.4.0
-    */
-   /*12.0*/HB_SCRIPT_ELYMAIC			= HB_TAG ('E','l','y','m'),
-   /*12.0*/HB_SCRIPT_NANDINAGARI			= HB_TAG ('N','a','n','d'),
-   /*12.0*/HB_SCRIPT_NYIAKENG_PUACHUE_HMONG	= HB_TAG ('H','m','n','p'),
-   /*12.0*/HB_SCRIPT_WANCHO			= HB_TAG ('W','c','h','o'),
- 
-   /* No script set. */
-   HB_SCRIPT_INVALID				= HB_TAG_NONE,
-@@ -462,45 +462,27 @@ hb_variation_to_string (hb_variation_t *
-  * Data type for holding color values.
-  *
-  * Since: 2.1.0
-  */
- typedef uint32_t hb_color_t;
- 
- #define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
- 
--/**
-- * hb_color_get_alpha:
-- *
-- *
-- *
-- * Since: 2.1.0
-- */
-+HB_EXTERN uint8_t
-+hb_color_get_alpha (hb_color_t color);
- #define hb_color_get_alpha(color)	((color) & 0xFF)
--/**
-- * hb_color_get_red:
-- *
-- *
-- *
-- * Since: 2.1.0
-- */
-+
-+HB_EXTERN uint8_t
-+hb_color_get_red (hb_color_t color);
- #define hb_color_get_red(color)		(((color) >> 8) & 0xFF)
--/**
-- * hb_color_get_green:
-- *
-- *
-- *
-- * Since: 2.1.0
-- */
-+
-+HB_EXTERN uint8_t
-+hb_color_get_green (hb_color_t color);
- #define hb_color_get_green(color)	(((color) >> 16) & 0xFF)
--/**
-- * hb_color_get_blue:
-- *
-- *
-- *
-- * Since: 2.1.0
-- */
-+
-+HB_EXTERN uint8_t
-+hb_color_get_blue (hb_color_t color);
- #define hb_color_get_blue(color)	(((color) >> 24) & 0xFF)
- 
--
- HB_END_DECLS
- 
- #endif /* HB_COMMON_H */
-diff --git a/gfx/harfbuzz/src/hb-config.hh b/gfx/harfbuzz/src/hb-config.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-config.hh
-@@ -0,0 +1,130 @@
-+/*
-+ * Copyright © 2019  Facebook, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Facebook Author(s): Behdad Esfahbod
-+ */
-+
-+#ifndef HB_CONFIG_HH
-+#define HB_CONFIG_HH
-+
-+#if 0 /* Make test happy. */
-+#include "hb.hh"
-+#endif
-+
-+#ifdef HAVE_CONFIG_H
-+#include "config.h"
-+#endif
-+
-+
-+#ifdef HB_TINY
-+#define HB_LEAN
-+#define HB_MINI
-+#define HB_NO_MT
-+#ifndef NDEBUG
-+#define NDEBUG
-+#endif
-+#ifndef __OPTIMIZE_SIZE__
-+#define __OPTIMIZE_SIZE__
-+#endif
-+#endif
-+
-+#ifdef HB_LEAN
-+#define HB_DISABLE_DEPRECATED
-+#define HB_NDEBUG
-+#define HB_NO_ATEXIT
-+#define HB_NO_BUFFER_SERIALIZE
-+#define HB_NO_BITMAP
-+#define HB_NO_CFF
-+#define HB_NO_COLOR
-+#define HB_NO_GETENV
-+#define HB_NO_LAYOUT_UNUSED
-+#define HB_NO_MATH
-+#define HB_NO_NAME
-+#define HB_NO_SUBSET_LAYOUT
-+#endif
-+
-+#ifdef HB_MINI
-+#define HB_NO_AAT
-+#define HB_NO_LEGACY
-+#endif
-+
-+/* Closure. */
-+
-+#ifdef HB_DISABLE_DEPRECATED
-+#define HB_IF_NOT_DEPRECATED(x)
-+#else
-+#define HB_IF_NOT_DEPRECATED(x) x
-+#endif
-+
-+#ifdef HB_NO_AAT
-+#define HB_NO_OT_NAME_LANGUAGE_AAT
-+#define HB_NO_SHAPE_AAT
-+#endif
-+
-+#ifdef HB_NO_BITMAP
-+#define HB_NO_OT_FONT_BITMAP
-+#endif
-+
-+#ifdef HB_NO_CFF
-+#define HB_NO_OT_FONT_CFF
-+#define HB_NO_SUBSET_CFF
-+#endif
-+
-+#ifdef HB_NO_GETENV
-+#define HB_NO_UNISCRIBE_BUG_COMPATIBLE
-+#endif
-+
-+#ifdef HB_NO_LEGACY
-+#define HB_NO_OT_LAYOUT_BLACKLIST
-+#define HB_NO_OT_SHAPE_FALLBACK
-+#endif
-+
-+#ifdef HB_NO_NAME
-+#define HB_NO_OT_NAME_LANGUAGE
-+#endif
-+
-+#ifdef HB_NO_OT_SHAPE_FALLBACK
-+#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
-+#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
-+#define HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
-+#define HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
-+#endif
-+
-+#ifdef NDEBUG
-+#ifndef HB_NDEBUG
-+#define HB_NDEBUG
-+#endif
-+#endif
-+
-+#ifdef __OPTIMIZE_SIZE__
-+#ifndef HB_OPTIMIZE_SIZE
-+#define HB_OPTIMIZE_SIZE
-+#endif
-+#endif
-+
-+#ifdef HAVE_CONFIG_OVERRIDE_H
-+#include "config-override.h"
-+#endif
-+
-+
-+#endif /* HB_CONFIG_HH */
-diff --git a/gfx/harfbuzz/src/hb-coretext.cc b/gfx/harfbuzz/src/hb-coretext.cc
---- a/gfx/harfbuzz/src/hb-coretext.cc
-+++ b/gfx/harfbuzz/src/hb-coretext.cc
-@@ -50,23 +50,23 @@ static CGFloat
- coretext_font_size_from_ptem (float ptem)
- {
-   /* CoreText points are CSS pixels (96 per inch),
-    * NOT typographic points (72 per inch).
-    *
-    * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
-    */
-   ptem *= 96.f / 72.f;
--  return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem;
-+  return (CGFloat) (ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem);
- }
- static float
- coretext_font_size_to_ptem (CGFloat size)
- {
--  size *= 72.f / 96.f;
--  return size <= 0.f ? 0 : size;
-+  size *= 72. / 96.;
-+  return size <= 0 ? 0 : size;
- }
- 
- static void
- release_table_data (void *user_data)
- {
-   CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
-   CFRelease(cf_data);
- }
-@@ -405,17 +405,17 @@ struct feature_record_t {
-   unsigned int feature;
-   unsigned int setting;
- };
- 
- struct active_feature_t {
-   feature_record_t rec;
-   unsigned int order;
- 
--  static int cmp (const void *pa, const void *pb) {
-+  HB_INTERNAL static int cmp (const void *pa, const void *pb) {
-     const active_feature_t *a = (const active_feature_t *) pa;
-     const active_feature_t *b = (const active_feature_t *) pb;
-     return a->rec.feature < b->rec.feature ? -1 : a->rec.feature > b->rec.feature ? 1 :
- 	   a->order < b->order ? -1 : a->order > b->order ? 1 :
- 	   a->rec.setting < b->rec.setting ? -1 : a->rec.setting > b->rec.setting ? 1 :
- 	   0;
-   }
-   bool operator== (const active_feature_t *f) {
-@@ -423,17 +423,17 @@ struct active_feature_t {
-   }
- };
- 
- struct feature_event_t {
-   unsigned int index;
-   bool start;
-   active_feature_t feature;
- 
--  static int cmp (const void *pa, const void *pb) {
-+  HB_INTERNAL static int cmp (const void *pa, const void *pb) {
-     const feature_event_t *a = (const feature_event_t *) pa;
-     const feature_event_t *b = (const feature_event_t *) pb;
-     return a->index < b->index ? -1 : a->index > b->index ? 1 :
- 	   a->start < b->start ? -1 : a->start > b->start ? 1 :
- 	   active_feature_t::cmp (&a->feature, &b->feature);
-   }
- };
- 
-@@ -593,36 +593,36 @@ hb_bool_t
-       }
- 
-       if (event->start)
-       {
-         active_features.push (event->feature);
-       } else {
-         active_feature_t *feature = active_features.find (&event->feature);
- 	if (feature)
--	  active_features.remove (feature - active_features.arrayZ ());
-+	  active_features.remove (feature - active_features.arrayZ);
-       }
-     }
-   }
- 
-   unsigned int scratch_size;
-   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
- 
- #define ALLOCATE_ARRAY(Type, name, len, on_no_room) \
-   Type *name = (Type *) scratch; \
--  { \
-+  do { \
-     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
-     if (unlikely (_consumed > scratch_size)) \
-     { \
-       on_no_room; \
-       assert (0); \
-     } \
-     scratch += _consumed; \
-     scratch_size -= _consumed; \
--  }
-+  } while (0)
- 
-   ALLOCATE_ARRAY (UniChar, pchars, buffer->len * 2, /*nothing*/);
-   unsigned int chars_len = 0;
-   for (unsigned int i = 0; i < buffer->len; i++) {
-     hb_codepoint_t c = buffer->info[i].codepoint;
-     if (likely (c <= 0xFFFFu))
-       pchars[chars_len++] = c;
-     else if (unlikely (c > 0x10FFFFu))
-@@ -766,17 +766,17 @@ resize_and_retry:
- 	CFNumberRef zero = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &zeroint);
- 	for (unsigned int i = 0; i < num_features; i++)
- 	{
- 	  const hb_feature_t &feature = features[i];
- 	  if (feature.tag == HB_TAG('k','e','r','n') &&
- 	      feature.start < chars_len && feature.start < feature.end)
- 	  {
- 	    CFRange feature_range = CFRangeMake (feature.start,
--	                                         MIN (feature.end, chars_len) - feature.start);
-+	                                         hb_min (feature.end, chars_len) - feature.start);
- 	    if (feature.value)
- 	      CFAttributedStringRemoveAttribute (attr_string, feature_range, kCTKernAttributeName);
- 	    else
- 	      CFAttributedStringSetAttribute (attr_string, feature_range, kCTKernAttributeName, zero);
- 	  }
- 	}
- 	CFRelease (zero);
-       }
-@@ -1064,17 +1064,17 @@ resize_and_retry:
-      * directions.  As such, disable the assert...  It wouldn't crash, but
-      * cursoring will be off...
-      *
-      * https://crbug.com/419769
-      */
-     if (false)
-     {
-       /* Make sure all runs had the expected direction. */
--      bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
-+      HB_UNUSED bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
-       assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
-       assert (bool (status_or  & kCTRunStatusRightToLeft) == backward);
-     }
- 
-     buffer->clear_positions ();
- 
-     unsigned int count = buffer->len;
-     hb_glyph_info_t *info = buffer->info;
-@@ -1111,26 +1111,26 @@ resize_and_retry:
-     if (count > 1 && (status_or & kCTRunStatusNonMonotonic))
-     {
-       hb_glyph_info_t *info = buffer->info;
-       if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
-       {
- 	unsigned int cluster = info[count - 1].cluster;
- 	for (unsigned int i = count - 1; i > 0; i--)
- 	{
--	  cluster = MIN (cluster, info[i - 1].cluster);
-+	  cluster = hb_min (cluster, info[i - 1].cluster);
- 	  info[i - 1].cluster = cluster;
- 	}
-       }
-       else
-       {
- 	unsigned int cluster = info[0].cluster;
- 	for (unsigned int i = 1; i < count; i++)
- 	{
--	  cluster = MIN (cluster, info[i].cluster);
-+	  cluster = hb_min (cluster, info[i].cluster);
- 	  info[i].cluster = cluster;
- 	}
-       }
-     }
-   }
- 
-   buffer->unsafe_to_break_all ();
- 
-@@ -1143,64 +1143,8 @@ fail:
-     CFRelease (line);
- 
-   for (unsigned int i = 0; i < range_records.length; i++)
-     if (range_records[i].font)
-       CFRelease (range_records[i].font);
- 
-   return ret;
- }
--
--
--/*
-- * AAT shaper
-- */
--
--/*
-- * shaper face data
-- */
--
--struct hb_coretext_aat_face_data_t {};
--
--hb_coretext_aat_face_data_t *
--_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
--{
--  return hb_aat_layout_has_substitution (face) || hb_aat_layout_has_positioning (face) ?
--	 (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
--}
--
--void
--_hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
--{
--}
--
--
--/*
-- * shaper font data
-- */
--
--struct hb_coretext_aat_font_data_t {};
--
--hb_coretext_aat_font_data_t *
--_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
--{
--  return font->data.coretext ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
--}
--
--void
--_hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
--{
--}
--
--
--/*
-- * shaper
-- */
--
--hb_bool_t
--_hb_coretext_aat_shape (hb_shape_plan_t    *shape_plan,
--			hb_font_t          *font,
--			hb_buffer_t        *buffer,
--			const hb_feature_t *features,
--			unsigned int        num_features)
--{
--  return _hb_coretext_shape (shape_plan, font, buffer, features, num_features);
--}
-diff --git a/gfx/harfbuzz/src/hb-debug.hh b/gfx/harfbuzz/src/hb-debug.hh
---- a/gfx/harfbuzz/src/hb-debug.hh
-+++ b/gfx/harfbuzz/src/hb-debug.hh
-@@ -24,17 +24,17 @@
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #ifndef HB_DEBUG_HH
- #define HB_DEBUG_HH
- 
- #include "hb.hh"
- #include "hb-atomic.hh"
--#include "hb-dsalgs.hh"
-+#include "hb-algs.hh"
- 
- 
- #ifndef HB_DEBUG
- #define HB_DEBUG 0
- #endif
- 
- 
- /*
-@@ -58,16 +58,19 @@ static_assert ((sizeof (hb_atomic_int_t)
- HB_INTERNAL void
- _hb_options_init ();
- 
- extern HB_INTERNAL hb_atomic_int_t _hb_options;
- 
- static inline hb_options_t
- hb_options ()
- {
-+#ifdef HB_NO_GETENV
-+  return hb_options_t ();
-+#endif
-   /* Make a local copy, so we can access bitfield threadsafely. */
-   hb_options_union_t u;
-   u.i = _hb_options.get_relaxed ();
- 
-   if (unlikely (!u.i))
-   {
-     _hb_options_init ();
-     u.i = _hb_options.get_relaxed ();
-@@ -153,17 +156,17 @@ template <int max_level> static inline v
-     static const char bars[] =
-       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR
-       VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR VBAR;
-     fprintf (stderr, "%2u %s" VRBAR "%s",
- 	     level,
--	     bars + sizeof (bars) - 1 - MIN ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
-+	     bars + sizeof (bars) - 1 - hb_min ((unsigned int) sizeof (bars) - 1, (unsigned int) (sizeof (VBAR) - 1) * level),
- 	     level_dir ? (level_dir > 0 ? DLBAR : ULBAR) : LBAR);
-   } else
-     fprintf (stderr, "   " VRBAR LBAR);
- 
-   _hb_print_func (func);
- 
-   if (message)
-   {
-@@ -241,34 +244,34 @@ struct hb_printer_t {
- };
- 
- template <>
- struct hb_printer_t<bool> {
-   const char *print (bool v) { return v ? "true" : "false"; }
- };
- 
- template <>
--struct hb_printer_t<hb_void_t> {
--  const char *print (hb_void_t) { return ""; }
-+struct hb_printer_t<hb_empty_t> {
-+  const char *print (hb_empty_t) { return ""; }
- };
- 
- 
- /*
-  * Trace
-  */
- 
- template <typename T>
- static inline void _hb_warn_no_return (bool returned)
- {
-   if (unlikely (!returned)) {
-     fprintf (stderr, "OUCH, returned with no call to return_trace().  This is a bug, please report.\n");
-   }
- }
- template <>
--/*static*/ inline void _hb_warn_no_return<hb_void_t> (bool returned HB_UNUSED)
-+/*static*/ inline void _hb_warn_no_return<hb_empty_t> (bool returned HB_UNUSED)
- {}
- 
- template <int max_level, typename ret_t>
- struct hb_auto_trace_t
- {
-   explicit inline hb_auto_trace_t (unsigned int *plevel_,
- 				   const char *what_,
- 				   const void *obj_,
-@@ -322,28 +325,30 @@ struct hb_auto_trace_t<0, ret_t>
- {
-   explicit inline hb_auto_trace_t (unsigned int *plevel_,
- 				   const char *what_,
- 				   const void *obj_,
- 				   const char *func,
- 				   const char *message,
- 				   ...) HB_PRINTF_FUNC(6, 7) {}
- 
--  ret_t ret (ret_t v,
--	     const char *func HB_UNUSED = nullptr,
--	     unsigned int line HB_UNUSED = 0) { return v; }
-+  template <typename T>
-+  T ret (T&& v,
-+	 const char *func HB_UNUSED = nullptr,
-+	 unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
- };
- 
- /* For disabled tracing; optimize out everything.
-  * https://github.com/harfbuzz/harfbuzz/pull/605 */
- template <typename ret_t>
- struct hb_no_trace_t {
--  ret_t ret (ret_t v,
--	     const char *func HB_UNUSED = "",
--	     unsigned int line HB_UNUSED = 0) { return v; }
-+  template <typename T>
-+  T ret (T&& v,
-+	 const char *func HB_UNUSED = nullptr,
-+	 unsigned int line HB_UNUSED = 0) { return hb_forward<T> (v); }
- };
- 
- #define return_trace(RET) return trace.ret (RET, HB_FUNC, __LINE__)
- 
- 
- /*
-  * Instances.
-  */
-@@ -432,35 +437,22 @@ struct hb_no_trace_t {
- #define TRACE_SUBSET(this) \
-   hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \
-   (&c->debug_depth, c->get_name (), this, HB_FUNC, \
-    " ");
- #else
- #define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
- #endif
- 
--#ifndef HB_DEBUG_WOULD_APPLY
--#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
--#endif
--#if HB_DEBUG_WOULD_APPLY
--#define TRACE_WOULD_APPLY(this) \
--	hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
--	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
--	 "%d glyphs", c->len);
--#else
--#define TRACE_WOULD_APPLY(this) hb_no_trace_t<bool> trace
--#endif
--
- #ifndef HB_DEBUG_DISPATCH
- #define HB_DEBUG_DISPATCH ( \
- 	HB_DEBUG_APPLY + \
- 	HB_DEBUG_SANITIZE + \
- 	HB_DEBUG_SERIALIZE + \
--  HB_DEBUG_SUBSET + \
--	HB_DEBUG_WOULD_APPLY + \
-+	HB_DEBUG_SUBSET + \
- 	0)
- #endif
- #if HB_DEBUG_DISPATCH
- #define TRACE_DISPATCH(this, format) \
- 	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
- 	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
- 	 "format %d", (int) format);
- #else
-diff --git a/gfx/harfbuzz/src/hb-deprecated.h b/gfx/harfbuzz/src/hb-deprecated.h
---- a/gfx/harfbuzz/src/hb-deprecated.h
-+++ b/gfx/harfbuzz/src/hb-deprecated.h
-@@ -58,17 +58,17 @@ HB_BEGIN_DECLS
- #define HB_BUFFER_FLAGS_DEFAULT			HB_BUFFER_FLAG_DEFAULT
- #define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT	HB_BUFFER_SERIALIZE_FLAG_DEFAULT
- 
- typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data,
- 					       hb_codepoint_t unicode, hb_codepoint_t variation_selector,
- 					       hb_codepoint_t *glyph,
- 					       void *user_data);
- 
--HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func or hb_font_funcs_set_variation_glyph_func) void
-+HB_EXTERN HB_DEPRECATED_FOR(hb_font_funcs_set_nominal_glyph_func and hb_font_funcs_set_variation_glyph_func) void
- hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
- 			      hb_font_get_glyph_func_t func,
- 			      void *user_data, hb_destroy_func_t destroy);
- 
- HB_EXTERN HB_DEPRECATED void
- hb_set_invert (hb_set_t *set);
- 
- /**
-diff --git a/gfx/harfbuzz/src/hb-directwrite.cc b/gfx/harfbuzz/src/hb-directwrite.cc
---- a/gfx/harfbuzz/src/hb-directwrite.cc
-+++ b/gfx/harfbuzz/src/hb-directwrite.cc
-@@ -525,22 +525,22 @@ static hb_bool_t
- 
-   IDWriteTextAnalyzer* analyzer;
-   dwriteFactory->CreateTextAnalyzer (&analyzer);
- 
-   unsigned int scratch_size;
-   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
- #define ALLOCATE_ARRAY(Type, name, len) \
-   Type *name = (Type *) scratch; \
--  { \
-+  do { \
-     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
-     assert (_consumed <= scratch_size); \
-     scratch += _consumed; \
-     scratch_size -= _consumed; \
--  }
-+  } while (0)
- 
- #define utf16_index() var1.u32
- 
-   ALLOCATE_ARRAY (wchar_t, textString, buffer->len * 2);
- 
-   unsigned int chars_len = 0;
-   for (unsigned int i = 0; i < buffer->len; i++)
-   {
-@@ -773,17 +773,17 @@ retry_getglyphs:
- 
-   /* Calculate visual-clusters.  That's what we ship. */
-   for (unsigned int i = 0; i < glyphCount; i++)
-     vis_clusters[i] = (uint32_t) -1;
-   for (unsigned int i = 0; i < buffer->len; i++)
-   {
-     uint32_t *p =
-       &vis_clusters[log_clusters[buffer->info[i].utf16_index ()]];
--    *p = MIN (*p, buffer->info[i].cluster);
-+    *p = hb_min (*p, buffer->info[i].cluster);
-   }
-   for (unsigned int i = 1; i < glyphCount; i++)
-     if (vis_clusters[i] == (uint32_t) -1)
-       vis_clusters[i] = vis_clusters[i - 1];
- 
- #undef utf16_index
- 
-   if (unlikely (!buffer->ensure (glyphCount)))
-@@ -841,20 +841,33 @@ hb_bool_t
- 		       hb_buffer_t        *buffer,
- 		       const hb_feature_t *features,
- 		       unsigned int        num_features)
- {
-   return _hb_directwrite_shape_full (shape_plan, font, buffer,
- 				     features, num_features, 0);
- }
- 
--/*
-- * Public [experimental] API
-- */
--
-+/**
-+ * hb_directwrite_shape_experimental_width:
-+ * Experimental API to test DirectWrite's justification algorithm.
-+ *
-+ * It inserts Kashida at wrong order so don't use the API ever.
-+ *
-+ * It doesn't work with cygwin/msys due to header bugs so one
-+ * should use MSVC toolchain in order to use it for now.
-+ *
-+ * @font:
-+ * @buffer:
-+ * @features:
-+ * @num_features:
-+ * @width:
-+ *
-+ * Since: 1.4.2
-+ **/
- hb_bool_t
- hb_directwrite_shape_experimental_width (hb_font_t          *font,
- 					 hb_buffer_t        *buffer,
- 					 const hb_feature_t *features,
- 					 unsigned int        num_features,
- 					 float               width)
- {
-   static const char *shapers = "directwrite";
-@@ -912,19 +925,36 @@ static void
- _hb_directwrite_font_release (void *data)
- {
-   if (data)
-     ((IDWriteFontFace *) data)->Release ();
- }
- 
- /**
-  * hb_directwrite_face_create:
-- * @font_face:
-- * Since: REPLACEME
-+ * @font_face: a DirectWrite IDWriteFontFace object.
-+ *
-+ * Return value: #hb_face_t object corresponding to the given input
-+ *
-+ * Since: 2.4.0
-  **/
- hb_face_t *
- hb_directwrite_face_create (IDWriteFontFace *font_face)
- {
-   if (font_face)
-     font_face->AddRef ();
-   return hb_face_create_for_tables (reference_table, font_face,
- 				    _hb_directwrite_font_release);
- }
-+
-+/**
-+* hb_directwrite_face_get_font_face:
-+* @face: a #hb_face_t object
-+*
-+* Return value: DirectWrite IDWriteFontFace object corresponding to the given input
-+*
-+* Since: REPLACEME
-+**/
-+IDWriteFontFace *
-+hb_directwrite_face_get_font_face (hb_face_t *face)
-+{
-+  return face->data.directwrite->fontFace;
-+}
-diff --git a/gfx/harfbuzz/src/hb-directwrite.h b/gfx/harfbuzz/src/hb-directwrite.h
---- a/gfx/harfbuzz/src/hb-directwrite.h
-+++ b/gfx/harfbuzz/src/hb-directwrite.h
-@@ -32,11 +32,14 @@ HB_BEGIN_DECLS
- HB_EXTERN hb_bool_t
- hb_directwrite_shape_experimental_width (hb_font_t *font, hb_buffer_t *buffer,
- 					 const hb_feature_t *features,
- 					 unsigned int num_features, float width);
- 
- HB_EXTERN hb_face_t *
- hb_directwrite_face_create (IDWriteFontFace *font_face);
- 
-+HB_EXTERN IDWriteFontFace *
-+hb_directwrite_face_get_font_face (hb_face_t *face);
-+
- HB_END_DECLS
- 
- #endif /* HB_DIRECTWRITE_H */
-diff --git a/gfx/harfbuzz/src/hb-dispatch.hh b/gfx/harfbuzz/src/hb-dispatch.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-dispatch.hh
-@@ -0,0 +1,58 @@
-+/*
-+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
-+ * Copyright © 2012,2018  Google, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Red Hat Author(s): Behdad Esfahbod
-+ * Google Author(s): Behdad Esfahbod
-+ */
-+
-+#ifndef HB_DISPATCH_HH
-+#define HB_DISPATCH_HH
-+
-+#include "hb.hh"
-+
-+/*
-+ * Dispatch
-+ */
-+
-+template <typename Context, typename Return, unsigned int MaxDebugDepth>
-+struct hb_dispatch_context_t
-+{
-+  private:
-+  /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-+  const Context* thiz () const { return static_cast<const Context *> (this); }
-+        Context* thiz ()       { return static_cast<      Context *> (this); }
-+  public:
-+  static constexpr unsigned max_debug_depth = MaxDebugDepth;
-+  typedef Return return_t;
-+  template <typename T, typename F>
-+  bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
-+  template <typename T, typename ...Ts>
-+  return_t dispatch (const T &obj, Ts&&... ds)
-+  { return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); }
-+  static return_t no_dispatch_return_value () { return Context::default_return_value (); }
-+  static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
-+};
-+
-+
-+#endif /* HB_DISPATCH_HH */
-diff --git a/gfx/harfbuzz/src/hb-dsalgs.hh b/gfx/harfbuzz/src/hb-dsalgs.hh
-deleted file mode 100644
---- a/gfx/harfbuzz/src/hb-dsalgs.hh
-+++ /dev/null
-@@ -1,627 +0,0 @@
--/*
-- * Copyright © 2017  Google, Inc.
-- *
-- *  This is part of HarfBuzz, a text shaping library.
-- *
-- * Permission is hereby granted, without written agreement and without
-- * license or royalty fees, to use, copy, modify, and distribute this
-- * software and its documentation for any purpose, provided that the
-- * above copyright notice and the following two paragraphs appear in
-- * all copies of this software.
-- *
-- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-- * DAMAGE.
-- *
-- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-- *
-- * Google Author(s): Behdad Esfahbod
-- */
--
--#ifndef HB_DSALGS_HH
--#define HB_DSALGS_HH
--
--#include "hb.hh"
--#include "hb-null.hh"
--
--
--/* Void! For when we need a expression-type of void. */
--typedef const struct _hb_void_t *hb_void_t;
--#define HB_VOID ((const _hb_void_t *) nullptr)
--
--
--/*
-- * Bithacks.
-- */
--
--/* Return the number of 1 bits in v. */
--template <typename T>
--static inline HB_CONST_FUNC unsigned int
--hb_popcount (T v)
--{
--#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
--  if (sizeof (T) <= sizeof (unsigned int))
--    return __builtin_popcount (v);
--
--  if (sizeof (T) <= sizeof (unsigned long))
--    return __builtin_popcountl (v);
--
--  if (sizeof (T) <= sizeof (unsigned long long))
--    return __builtin_popcountll (v);
--#endif
--
--  if (sizeof (T) <= 4)
--  {
--    /* "HACKMEM 169" */
--    uint32_t y;
--    y = (v >> 1) &033333333333;
--    y = v - y - ((y >>1) & 033333333333);
--    return (((y + (y >> 3)) & 030707070707) % 077);
--  }
--
--  if (sizeof (T) == 8)
--  {
--    unsigned int shift = 32;
--    return hb_popcount<uint32_t> ((uint32_t) v) + hb_popcount ((uint32_t) (v >> shift));
--  }
--
--  if (sizeof (T) == 16)
--  {
--    unsigned int shift = 64;
--    return hb_popcount<uint64_t> ((uint64_t) v) + hb_popcount ((uint64_t) (v >> shift));
--  }
--
--  assert (0);
--  return 0; /* Shut up stupid compiler. */
--}
--
--/* Returns the number of bits needed to store number */
--template <typename T>
--static inline HB_CONST_FUNC unsigned int
--hb_bit_storage (T v)
--{
--  if (unlikely (!v)) return 0;
--
--#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
--  if (sizeof (T) <= sizeof (unsigned int))
--    return sizeof (unsigned int) * 8 - __builtin_clz (v);
--
--  if (sizeof (T) <= sizeof (unsigned long))
--    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
--
--  if (sizeof (T) <= sizeof (unsigned long long))
--    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
--#endif
--
--#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
--  if (sizeof (T) <= sizeof (unsigned int))
--  {
--    unsigned long where;
--    _BitScanReverse (&where, v);
--    return 1 + where;
--  }
--# if defined(_WIN64)
--  if (sizeof (T) <= 8)
--  {
--    unsigned long where;
--    _BitScanReverse64 (&where, v);
--    return 1 + where;
--  }
--# endif
--#endif
--
--  if (sizeof (T) <= 4)
--  {
--    /* "bithacks" */
--    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
--    const unsigned int S[] = {1, 2, 4, 8, 16};
--    unsigned int r = 0;
--    for (int i = 4; i >= 0; i--)
--      if (v & b[i])
--      {
--	v >>= S[i];
--	r |= S[i];
--      }
--    return r + 1;
--  }
--  if (sizeof (T) <= 8)
--  {
--    /* "bithacks" */
--    const uint64_t b[] = {0x2ULL, 0xCULL, 0xF0ULL, 0xFF00ULL, 0xFFFF0000ULL, 0xFFFFFFFF00000000ULL};
--    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
--    unsigned int r = 0;
--    for (int i = 5; i >= 0; i--)
--      if (v & b[i])
--      {
--	v >>= S[i];
--	r |= S[i];
--      }
--    return r + 1;
--  }
--  if (sizeof (T) == 16)
--  {
--    unsigned int shift = 64;
--    return (v >> shift) ? hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift :
--			  hb_bit_storage<uint64_t> ((uint64_t) v);
--  }
--
--  assert (0);
--  return 0; /* Shut up stupid compiler. */
--}
--
--/* Returns the number of zero bits in the least significant side of v */
--template <typename T>
--static inline HB_CONST_FUNC unsigned int
--hb_ctz (T v)
--{
--  if (unlikely (!v)) return 0;
--
--#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
--  if (sizeof (T) <= sizeof (unsigned int))
--    return __builtin_ctz (v);
--
--  if (sizeof (T) <= sizeof (unsigned long))
--    return __builtin_ctzl (v);
--
--  if (sizeof (T) <= sizeof (unsigned long long))
--    return __builtin_ctzll (v);
--#endif
--
--#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
--  if (sizeof (T) <= sizeof (unsigned int))
--  {
--    unsigned long where;
--    _BitScanForward (&where, v);
--    return where;
--  }
--# if defined(_WIN64)
--  if (sizeof (T) <= 8)
--  {
--    unsigned long where;
--    _BitScanForward64 (&where, v);
--    return where;
--  }
--# endif
--#endif
--
--  if (sizeof (T) <= 4)
--  {
--    /* "bithacks" */
--    unsigned int c = 32;
--    v &= - (int32_t) v;
--    if (v) c--;
--    if (v & 0x0000FFFF) c -= 16;
--    if (v & 0x00FF00FF) c -= 8;
--    if (v & 0x0F0F0F0F) c -= 4;
--    if (v & 0x33333333) c -= 2;
--    if (v & 0x55555555) c -= 1;
--    return c;
--  }
--  if (sizeof (T) <= 8)
--  {
--    /* "bithacks" */
--    unsigned int c = 64;
--    v &= - (int64_t) (v);
--    if (v) c--;
--    if (v & 0x00000000FFFFFFFFULL) c -= 32;
--    if (v & 0x0000FFFF0000FFFFULL) c -= 16;
--    if (v & 0x00FF00FF00FF00FFULL) c -= 8;
--    if (v & 0x0F0F0F0F0F0F0F0FULL) c -= 4;
--    if (v & 0x3333333333333333ULL) c -= 2;
--    if (v & 0x5555555555555555ULL) c -= 1;
--    return c;
--  }
--  if (sizeof (T) == 16)
--  {
--    unsigned int shift = 64;
--    return (uint64_t) v ? hb_bit_storage<uint64_t> ((uint64_t) v) :
--			  hb_bit_storage<uint64_t> ((uint64_t) (v >> shift)) + shift;
--  }
--
--  assert (0);
--  return 0; /* Shut up stupid compiler. */
--}
--
--
--/*
-- * Tiny stuff.
-- */
--
--template <typename T>
--static inline T* hb_addressof (T& arg)
--{
--#pragma GCC diagnostic push
--#pragma GCC diagnostic ignored "-Wcast-align"
--  /* https://en.cppreference.com/w/cpp/memory/addressof */
--  return reinterpret_cast<T*>(
--	   &const_cast<char&>(
--	      reinterpret_cast<const volatile char&>(arg)));
--#pragma GCC diagnostic pop
--}
--
--/* ASCII tag/character handling */
--static inline bool ISALPHA (unsigned char c)
--{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
--static inline bool ISALNUM (unsigned char c)
--{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
--static inline bool ISSPACE (unsigned char c)
--{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
--static inline unsigned char TOUPPER (unsigned char c)
--{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
--static inline unsigned char TOLOWER (unsigned char c)
--{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
--
--#undef MIN
--template <typename Type>
--static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
--
--#undef MAX
--template <typename Type>
--static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
--
--static inline unsigned int DIV_CEIL (const unsigned int a, unsigned int b)
--{ return (a + (b - 1)) / b; }
--
--
--#undef  ARRAY_LENGTH
--template <typename Type, unsigned int n>
--static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
--/* A const version, but does not detect erratically being called on pointers. */
--#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
--
--
--static inline int
--hb_memcmp (const void *a, const void *b, unsigned int len)
--{
--  /* It's illegal to pass NULL to memcmp(), even if len is zero.
--   * So, wrap it.
--   * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
--  if (!len) return 0;
--  return memcmp (a, b, len);
--}
--
--static inline bool
--hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
--{
--  return (size > 0) && (count >= ((unsigned int) -1) / size);
--}
--
--static inline unsigned int
--hb_ceil_to_4 (unsigned int v)
--{
--  return ((v - 1) | 3) + 1;
--}
--
--template <typename T> struct hb_is_signed;
--/* https://github.com/harfbuzz/harfbuzz/issues/1535 */
--template <> struct hb_is_signed<int8_t> { enum { value = true }; };
--template <> struct hb_is_signed<int16_t> { enum { value = true }; };
--template <> struct hb_is_signed<int32_t> { enum { value = true }; };
--template <> struct hb_is_signed<int64_t> { enum { value = true }; };
--template <> struct hb_is_signed<uint8_t> { enum { value = false }; };
--template <> struct hb_is_signed<uint16_t> { enum { value = false }; };
--template <> struct hb_is_signed<uint32_t> { enum { value = false }; };
--template <> struct hb_is_signed<uint64_t> { enum { value = false }; };
--
--template <typename T> static inline bool
--hb_in_range (T u, T lo, T hi)
--{
--  static_assert (!hb_is_signed<T>::value, "");
--
--  /* The casts below are important as if T is smaller than int,
--   * the subtract results will become a signed int! */
--  return (T)(u - lo) <= (T)(hi - lo);
--}
--template <typename T> static inline bool
--hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
--{
--  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
--}
--template <typename T> static inline bool
--hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
--{
--  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
--}
--
--
--/*
-- * Sort and search.
-- */
--
--static inline void *
--hb_bsearch (const void *key, const void *base,
--	    size_t nmemb, size_t size,
--	    int (*compar)(const void *_key, const void *_item))
--{
--  int min = 0, max = (int) nmemb - 1;
--  while (min <= max)
--  {
--    int mid = (min + max) / 2;
--    const void *p = (const void *) (((const char *) base) + (mid * size));
--    int c = compar (key, p);
--    if (c < 0)
--      max = mid - 1;
--    else if (c > 0)
--      min = mid + 1;
--    else
--      return (void *) p;
--  }
--  return nullptr;
--}
--
--static inline void *
--hb_bsearch_r (const void *key, const void *base,
--	      size_t nmemb, size_t size,
--	      int (*compar)(const void *_key, const void *_item, void *_arg),
--	      void *arg)
--{
--  int min = 0, max = (int) nmemb - 1;
--  while (min <= max)
--  {
--    int mid = ((unsigned int) min + (unsigned int) max) / 2;
--    const void *p = (const void *) (((const char *) base) + (mid * size));
--    int c = compar (key, p, arg);
--    if (c < 0)
--      max = mid - 1;
--    else if (c > 0)
--      min = mid + 1;
--    else
--      return (void *) p;
--  }
--  return nullptr;
--}
--
--
--/* From https://github.com/noporpoise/sort_r
-- * With following modifications:
-- *
-- * 10 November 2018:
-- * https://github.com/noporpoise/sort_r/issues/7
-- */
--
--/* Isaac Turner 29 April 2014 Public Domain */
--
--/*
--
--hb_sort_r function to be exported.
--
--Parameters:
--  base is the array to be sorted
--  nel is the number of elements in the array
--  width is the size in bytes of each element of the array
--  compar is the comparison function
--  arg is a pointer to be passed to the comparison function
--
--void hb_sort_r(void *base, size_t nel, size_t width,
--               int (*compar)(const void *_a, const void *_b, void *_arg),
--               void *arg);
--*/
--
--
--/* swap a, b iff a>b */
--/* __restrict is same as restrict but better support on old machines */
--static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
--			  int (*compar)(const void *_a, const void *_b,
--					void *_arg),
--			  void *arg)
--{
--  char tmp, *end = a+w;
--  if(compar(a, b, arg) > 0) {
--    for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
--    return 1;
--  }
--  return 0;
--}
--
--/* Note: quicksort is not stable, equivalent values may be swapped */
--static inline void sort_r_simple(void *base, size_t nel, size_t w,
--				 int (*compar)(const void *_a, const void *_b,
--					       void *_arg),
--				 void *arg)
--{
--  char *b = (char *)base, *end = b + nel*w;
--  if(nel < 7) {
--    /* Insertion sort for arbitrarily small inputs */
--    char *pi, *pj;
--    for(pi = b+w; pi < end; pi += w) {
--      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
--    }
--  }
--  else
--  {
--    /* nel > 6; Quicksort */
--
--    /* Use median of first, middle and last items as pivot */
--    char *x, *y, *xend, ch;
--    char *pl, *pm, *pr;
--    char *last = b+w*(nel-1), *tmp;
--    char *l[3];
--    l[0] = b;
--    l[1] = b+w*(nel/2);
--    l[2] = last;
--
--    if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
--    if(compar(l[1],l[2],arg) > 0) {
--      tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
--      if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
--    }
--
--    /* swap l[id], l[2] to put pivot as last element */
--    for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
--      ch = *x; *x = *y; *y = ch;
--    }
--
--    pl = b;
--    pr = last;
--
--    while(pl < pr) {
--      pm = pl+((pr-pl+1)>>1);
--      for(; pl < pm; pl += w) {
--        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
--          pr -= w; /* pivot now at pl */
--          break;
--        }
--      }
--      pm = pl+((pr-pl)>>1);
--      for(; pm < pr; pr -= w) {
--        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
--          pl += w; /* pivot now at pr */
--          break;
--        }
--      }
--    }
--
--    sort_r_simple(b, (pl-b)/w, w, compar, arg);
--    sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
--  }
--}
--
--static inline void hb_sort_r(void *base, size_t nel, size_t width,
--			     int (*compar)(const void *_a, const void *_b, void *_arg),
--			     void *arg)
--{
--    sort_r_simple(base, nel, width, compar, arg);
--}
--
--
--template <typename T, typename T2> static inline void
--hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *), T2 *array2)
--{
--  for (unsigned int i = 1; i < len; i++)
--  {
--    unsigned int j = i;
--    while (j && compar (&array[j - 1], &array[i]) > 0)
--      j--;
--    if (i == j)
--      continue;
--    /* Move item i to occupy place for item j, shift what's in between. */
--    {
--      T t = array[i];
--      memmove (&array[j + 1], &array[j], (i - j) * sizeof (T));
--      array[j] = t;
--    }
--    if (array2)
--    {
--      T2 t = array2[i];
--      memmove (&array2[j + 1], &array2[j], (i - j) * sizeof (T2));
--      array2[j] = t;
--    }
--  }
--}
--
--template <typename T> static inline void
--hb_stable_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
--{
--  hb_stable_sort (array, len, compar, (int *) nullptr);
--}
--
--static inline hb_bool_t
--hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
--{
--  /* Pain because we don't know whether s is nul-terminated. */
--  char buf[64];
--  len = MIN (ARRAY_LENGTH (buf) - 1, len);
--  strncpy (buf, s, len);
--  buf[len] = '\0';
--
--  char *end;
--  errno = 0;
--  unsigned long v = strtoul (buf, &end, base);
--  if (errno) return false;
--  if (*end) return false;
--  *out = v;
--  return true;
--}
--
--
--struct HbOpOr
--{
--  static constexpr bool passthru_left = true;
--  static constexpr bool passthru_right = true;
--  template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
--};
--struct HbOpAnd
--{
--  static constexpr bool passthru_left = false;
--  static constexpr bool passthru_right = false;
--  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
--};
--struct HbOpMinus
--{
--  static constexpr bool passthru_left = true;
--  static constexpr bool passthru_right = false;
--  template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
--};
--struct HbOpXor
--{
--  static constexpr bool passthru_left = true;
--  static constexpr bool passthru_right = true;
--  template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
--};
--
--
--/* Compiler-assisted vectorization. */
--
--/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
-- * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
-- * Define that to 0 to disable. */
--template <typename elt_t, unsigned int byte_size>
--struct hb_vector_size_t
--{
--  elt_t& operator [] (unsigned int i) { return u.v[i]; }
--  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
--
--  void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
--
--  template <class Op>
--  hb_vector_size_t process (const hb_vector_size_t &o) const
--  {
--    hb_vector_size_t r;
--#if HB_VECTOR_SIZE
--    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
--      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
--	Op::process (r.u.vec[i], u.vec[i], o.u.vec[i]);
--    else
--#endif
--      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
--	Op::process (r.u.v[i], u.v[i], o.u.v[i]);
--    return r;
--  }
--  hb_vector_size_t operator | (const hb_vector_size_t &o) const
--  { return process<HbOpOr> (o); }
--  hb_vector_size_t operator & (const hb_vector_size_t &o) const
--  { return process<HbOpAnd> (o); }
--  hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
--  { return process<HbOpXor> (o); }
--  hb_vector_size_t operator ~ () const
--  {
--    hb_vector_size_t r;
--#if HB_VECTOR_SIZE && 0
--    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
--      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
--	r.u.vec[i] = ~u.vec[i];
--    else
--#endif
--    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
--      r.u.v[i] = ~u.v[i];
--    return r;
--  }
--
--  private:
--  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
--  union {
--    elt_t v[byte_size / sizeof (elt_t)];
--#if HB_VECTOR_SIZE
--    hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
--#endif
--  } u;
--};
--
--
--#endif /* HB_DSALGS_HH */
-diff --git a/gfx/harfbuzz/src/hb-font.cc b/gfx/harfbuzz/src/hb-font.cc
---- a/gfx/harfbuzz/src/hb-font.cc
-+++ b/gfx/harfbuzz/src/hb-font.cc
-@@ -331,16 +331,17 @@ hb_font_get_glyph_v_origin_default (hb_f
- 				    void *user_data HB_UNUSED)
- {
-   hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
-   if (ret)
-     font->parent_scale_position (x, y);
-   return ret;
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- static hb_position_t
- hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
- 				 void *font_data HB_UNUSED,
- 				 hb_codepoint_t left_glyph HB_UNUSED,
- 				 hb_codepoint_t right_glyph HB_UNUSED,
- 				 void *user_data HB_UNUSED)
- {
-   return 0;
-@@ -368,16 +369,17 @@ static hb_position_t
- hb_font_get_glyph_v_kerning_default (hb_font_t *font,
- 				     void *font_data HB_UNUSED,
- 				     hb_codepoint_t top_glyph,
- 				     hb_codepoint_t bottom_glyph,
- 				     void *user_data HB_UNUSED)
- {
-   return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
- }
-+#endif
- 
- static hb_bool_t
- hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
- 			       void *font_data HB_UNUSED,
- 			       hb_codepoint_t glyph HB_UNUSED,
- 			       hb_glyph_extents_t *extents,
- 			       void *user_data HB_UNUSED)
- {
-@@ -920,16 +922,17 @@ hb_font_get_glyph_h_origin (hb_font_t *f
- hb_bool_t
- hb_font_get_glyph_v_origin (hb_font_t *font,
- 			    hb_codepoint_t glyph,
- 			    hb_position_t *x, hb_position_t *y)
- {
-   return font->get_glyph_v_origin (glyph, x, y);
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_font_get_glyph_h_kerning:
-  * @font: a font.
-  * @left_glyph: 
-  * @right_glyph: 
-  *
-  * 
-  *
-@@ -959,16 +962,17 @@ hb_font_get_glyph_h_kerning (hb_font_t *
-  * Deprecated: 2.0.0
-  **/
- hb_position_t
- hb_font_get_glyph_v_kerning (hb_font_t *font,
- 			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
- {
-   return font->get_glyph_v_kerning (top_glyph, bottom_glyph);
- }
-+#endif
- 
- /**
-  * hb_font_get_glyph_extents:
-  * @font: a font.
-  * @glyph: 
-  * @extents: (out): 
-  *
-  * 
-@@ -1168,16 +1172,17 @@ void
- hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
- 					     hb_codepoint_t glyph,
- 					     hb_direction_t direction,
- 					     hb_position_t *x, hb_position_t *y)
- {
-   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_font_get_glyph_kerning_for_direction:
-  * @font: a font.
-  * @first_glyph: 
-  * @second_glyph: 
-  * @direction: 
-  * @x: (out): 
-  * @y: (out): 
-@@ -1190,16 +1195,17 @@ hb_font_subtract_glyph_origin_for_direct
- void
- hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
- 					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
- 					 hb_direction_t direction,
- 					 hb_position_t *x, hb_position_t *y)
- {
-   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
- }
-+#endif
- 
- /**
-  * hb_font_get_glyph_extents_for_origin:
-  * @font: a font.
-  * @glyph: 
-  * @direction: 
-  * @extents: (out): 
-  *
-@@ -1342,18 +1348,20 @@ static hb_font_t *
-  *
-  * Since: 0.9.2
-  **/
- hb_font_t *
- hb_font_create (hb_face_t *face)
- {
-   hb_font_t *font = _hb_font_create (face);
- 
-+#ifndef HB_NO_OT_FONT
-   /* Install our in-house, very lightweight, funcs. */
-   hb_ot_font_set_funcs (font);
-+#endif
- 
-   return font;
- }
- 
- /**
-  * hb_font_create_sub_font:
-  * @parent: parent font.
-  *
-@@ -1909,16 +1917,17 @@ hb_font_get_var_coords_normalized (hb_fo
- {
-   if (length)
-     *length = font->num_coords;
- 
-   return font->coords;
- }
- 
- 
-+#ifndef HB_DISABLE_DEPRECATED
- /*
-  * Deprecated get_glyph_func():
-  */
- 
- struct hb_trampoline_closure_t
- {
-   void *user_data;
-   hb_destroy_func_t destroy;
-@@ -2031,8 +2040,9 @@ hb_font_funcs_set_glyph_func (hb_font_fu
- 					trampoline_destroy);
- 
-   trampoline_reference (&trampoline->closure);
-   hb_font_funcs_set_variation_glyph_func (ffuncs,
- 					  hb_font_get_variation_glyph_trampoline,
- 					  trampoline,
- 					  trampoline_destroy);
- }
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-font.hh b/gfx/harfbuzz/src/hb-font.hh
---- a/gfx/harfbuzz/src/hb-font.hh
-+++ b/gfx/harfbuzz/src/hb-font.hh
-@@ -46,18 +46,18 @@
-   HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
-   HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
--  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
--  HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning) \
-+  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning)) \
-+  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_name) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
-   /* ^--- Add new callbacks here */
- 
- struct hb_font_funcs_t
- {
-@@ -299,27 +299,35 @@ struct hb_font_t
-     return klass->get.f.glyph_v_origin (this, user_data,
- 					glyph, x, y,
- 					klass->user_data.glyph_v_origin);
-   }
- 
-   hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
- 				     hb_codepoint_t right_glyph)
-   {
-+#ifdef HB_DISABLE_DEPRECATED
-+    return 0;
-+#else
-     return klass->get.f.glyph_h_kerning (this, user_data,
- 					 left_glyph, right_glyph,
- 					 klass->user_data.glyph_h_kerning);
-+#endif
-   }
- 
-   hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph,
- 				     hb_codepoint_t bottom_glyph)
-   {
-+#ifdef HB_DISABLE_DEPRECATED
-+    return 0;
-+#else
-     return klass->get.f.glyph_v_kerning (this, user_data,
- 					 top_glyph, bottom_glyph,
- 					 klass->user_data.glyph_v_kerning);
-+#endif
-   }
- 
-   hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
- 				      hb_glyph_extents_t *extents)
-   {
-     memset (extents, 0, sizeof (*extents));
-     return klass->get.f.glyph_extents (this, user_data,
- 				       glyph,
-@@ -602,16 +610,16 @@ struct hb_font_t
-   hb_position_t em_scale (int16_t v, int scale)
-   {
-     int upem = face->get_upem ();
-     int64_t scaled = v * (int64_t) scale;
-     scaled += scaled >= 0 ? upem/2 : -upem/2; /* Round. */
-     return (hb_position_t) (scaled / upem);
-   }
-   hb_position_t em_scalef (float v, int scale)
--  { return (hb_position_t) round (v * scale / face->get_upem ()); }
-+  { return (hb_position_t) roundf (v * scale / face->get_upem ()); }
-   float em_fscale (int16_t v, int scale)
-   { return (float) v * scale / face->get_upem (); }
- };
- DECLARE_NULL_INSTANCE (hb_font_t);
- 
- 
- #endif /* HB_FONT_HH */
-diff --git a/gfx/harfbuzz/src/hb-ft.cc b/gfx/harfbuzz/src/hb-ft.cc
---- a/gfx/harfbuzz/src/hb-ft.cc
-+++ b/gfx/harfbuzz/src/hb-ft.cc
-@@ -91,17 +91,17 @@ static hb_ft_font_t *
- 
-   ft_font->lock.init ();
-   ft_font->ft_face = ft_face;
-   ft_font->symbol = symbol;
-   ft_font->unref = unref;
- 
-   ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- 
--  ft_font->cached_x_scale.set (0);
-+  ft_font->cached_x_scale.set_relaxed (0);
-   ft_font->advance_cache.init ();
- 
-   return ft_font;
- }
- 
- static void
- _hb_ft_face_destroy (void *data)
- {
-@@ -434,17 +434,17 @@ hb_ft_get_glyph_from_name (hb_font_t *fo
-   hb_lock_t lock (ft_font->lock);
-   FT_Face ft_face = ft_font->ft_face;
- 
-   if (len < 0)
-     *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name);
-   else {
-     /* Make a nul-terminated version. */
-     char buf[128];
--    len = MIN (len, (int) sizeof (buf) - 1);
-+    len = hb_min (len, (int) sizeof (buf) - 1);
-     strncpy (buf, name, len);
-     buf[len] = '\0';
-     *glyph = FT_Get_Name_Index (ft_face, buf);
-   }
- 
-   if (*glyph == 0)
-   {
-     /* Check whether the given name was actually the name of glyph 0. */
-@@ -743,17 +743,17 @@ hb_ft_font_create_referenced (FT_Face ft
-   FT_Reference_Face (ft_face);
-   return hb_ft_font_create (ft_face, _hb_ft_face_destroy);
- }
- 
- #if HB_USE_ATEXIT
- static void free_static_ft_library ();
- #endif
- 
--static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer (FT_Library),
-+static struct hb_ft_library_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<FT_Library>,
- 							     hb_ft_library_lazy_loader_t>
- {
-   static FT_Library create ()
-   {
-     FT_Library l;
-     if (FT_Init_FreeType (&l))
-       return nullptr;
- 
-diff --git a/gfx/harfbuzz/src/hb-graphite2.cc b/gfx/harfbuzz/src/hb-graphite2.cc
---- a/gfx/harfbuzz/src/hb-graphite2.cc
-+++ b/gfx/harfbuzz/src/hb-graphite2.cc
-@@ -197,27 +197,29 @@ hb_graphite2_font_data_t *
-   return (hb_graphite2_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
- }
- 
- void
- _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED)
- {
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_graphite2_font_get_gr_font:
-  *
-  * Since: 0.9.10
-  * Deprecated: 1.4.2
-  */
- gr_font *
- hb_graphite2_font_get_gr_font (hb_font_t *font HB_UNUSED)
- {
-   return nullptr;
- }
-+#endif
- 
- 
- /*
-  * shaper
-  */
- 
- struct hb_graphite2_cluster_t {
-   unsigned int base_char;
-@@ -303,22 +305,22 @@ hb_bool_t
-       gr_seg_destroy (seg);
-       return false;
-     }
-     scratch = buffer->get_scratch_buffer (&scratch_size);
-   }
- 
- #define ALLOCATE_ARRAY(Type, name, len) \
-   Type *name = (Type *) scratch; \
--  { \
-+  do { \
-     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
-     assert (_consumed <= scratch_size); \
-     scratch += _consumed; \
-     scratch_size -= _consumed; \
--  }
-+  } while (0)
- 
-   ALLOCATE_ARRAY (hb_graphite2_cluster_t, clusters, buffer->len);
-   ALLOCATE_ARRAY (hb_codepoint_t, gids, glyph_count);
- 
- #undef ALLOCATE_ARRAY
- 
-   memset (clusters, 0, sizeof (clusters[0]) * buffer->len);
- 
-diff --git a/gfx/harfbuzz/src/hb-icu.cc b/gfx/harfbuzz/src/hb-icu.cc
---- a/gfx/harfbuzz/src/hb-icu.cc
-+++ b/gfx/harfbuzz/src/hb-icu.cc
-@@ -44,16 +44,19 @@
-  * SECTION:hb-icu
-  * @title: hb-icu
-  * @short_description: ICU integration
-  * @include: hb-icu.h
-  *
-  * Functions for using HarfBuzz with the ICU library to provide Unicode data.
-  **/
- 
-+/* ICU doesn't do-while(0) around their statements.  Ugh!
-+ * https://unicode-org.atlassian.net/browse/CLDR-13027 */
-+#define HB_ICU_STMT(S) do { S } while (0)
- 
- hb_script_t
- hb_icu_script_to_script (UScriptCode script)
- {
-   if (unlikely (script == USCRIPT_INVALID_CODE))
-     return HB_SCRIPT_INVALID;
- 
-   return hb_script_from_string (uscript_getShortName (script), -1);
-@@ -178,27 +181,27 @@ hb_icu_unicode_compose (hb_unicode_funcs
- 
-   UChar utf16[4], normalized[5];
-   unsigned int len;
-   hb_bool_t ret, err;
-   UErrorCode icu_err;
- 
-   len = 0;
-   err = false;
--  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err);
-+  HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), a, err));
-   if (err) return false;
--  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err);
-+  HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), b, err));
-   if (err) return false;
- 
-   icu_err = U_ZERO_ERROR;
-   len = unorm2_normalize (unorm2_getNFCInstance (&icu_err), utf16, len, normalized, ARRAY_LENGTH (normalized), &icu_err);
-   if (U_FAILURE (icu_err))
-     return false;
-   if (u_countChar32 (normalized, len) == 1) {
--    U16_GET_UNSAFE (normalized, 0, *ab);
-+    HB_ICU_STMT (U16_GET_UNSAFE (normalized, 0, *ab));
-     ret = true;
-   } else {
-     ret = false;
-   }
- 
-   return ret;
- }
- 
-@@ -216,89 +219,89 @@ hb_icu_unicode_decompose (hb_unicode_fun
-     int len;
-     UErrorCode icu_err = U_ZERO_ERROR;
-     len = unorm2_getRawDecomposition (normalizer, ab, decomposed,
- 				      ARRAY_LENGTH (decomposed), &icu_err);
-     if (U_FAILURE (icu_err) || len < 0) return false;
- 
-     len = u_countChar32 (decomposed, len);
-     if (len == 1) {
--      U16_GET_UNSAFE (decomposed, 0, *a);
-+      HB_ICU_STMT (U16_GET_UNSAFE (decomposed, 0, *a));
-       *b = 0;
-       return *a != ab;
-     } else if (len == 2) {
-       len =0;
--      U16_NEXT_UNSAFE (decomposed, len, *a);
--      U16_NEXT_UNSAFE (decomposed, len, *b);
-+      HB_ICU_STMT (U16_NEXT_UNSAFE (decomposed, len, *a));
-+      HB_ICU_STMT (U16_NEXT_UNSAFE (decomposed, len, *b));
-     }
-     return true;
-   }
- #endif
- 
-   /* We don't ifdef-out the fallback code such that compiler always
-    * sees it and makes sure it's compilable. */
- 
--  UChar utf16[2], normalized[2 * HB_UNICODE_MAX_DECOMPOSITION_LEN + 1];
-+  UChar utf16[2], normalized[2 * 19/*HB_UNICODE_MAX_DECOMPOSITION_LEN*/ + 1];
-   unsigned int len;
-   hb_bool_t ret, err;
-   UErrorCode icu_err;
- 
-   /* This function is a monster! Maybe it wasn't a good idea adding a
-    * pairwise decompose API... */
-   /* Watchout for the dragons.  Err, watchout for macros changing len. */
- 
-   len = 0;
-   err = false;
--  U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err);
-+  HB_ICU_STMT (U16_APPEND (utf16, len, ARRAY_LENGTH (utf16), ab, err));
-   if (err) return false;
- 
-   icu_err = U_ZERO_ERROR;
-   len = unorm2_normalize (unorm2_getNFDInstance (&icu_err), utf16, len, normalized, ARRAY_LENGTH (normalized), &icu_err);
-   if (U_FAILURE (icu_err))
-     return false;
- 
-   len = u_countChar32 (normalized, len);
- 
-   if (len == 1) {
--    U16_GET_UNSAFE (normalized, 0, *a);
-+    HB_ICU_STMT (U16_GET_UNSAFE (normalized, 0, *a));
-     *b = 0;
-     ret = *a != ab;
-   } else if (len == 2) {
-     len =0;
--    U16_NEXT_UNSAFE (normalized, len, *a);
--    U16_NEXT_UNSAFE (normalized, len, *b);
-+    HB_ICU_STMT (U16_NEXT_UNSAFE (normalized, len, *a));
-+    HB_ICU_STMT (U16_NEXT_UNSAFE (normalized, len, *b));
- 
-     /* Here's the ugly part: if ab decomposes to a single character and
-      * that character decomposes again, we have to detect that and undo
-      * the second part :-(. */
-     UChar recomposed[20];
-     icu_err = U_ZERO_ERROR;
-     unorm2_normalize (unorm2_getNFCInstance (&icu_err), normalized, len, recomposed, ARRAY_LENGTH (recomposed), &icu_err);
-     if (U_FAILURE (icu_err))
-       return false;
-     hb_codepoint_t c;
--    U16_GET_UNSAFE (recomposed, 0, c);
-+    HB_ICU_STMT (U16_GET_UNSAFE (recomposed, 0, c));
-     if (c != *a && c != ab) {
-       *a = c;
-       *b = 0;
-     }
-     ret = true;
-   } else {
-     /* If decomposed to more than two characters, take the last one,
-      * and recompose the rest to get the first component. */
--    U16_PREV_UNSAFE (normalized, len, *b); /* Changes len in-place. */
-+    HB_ICU_STMT (U16_PREV_UNSAFE (normalized, len, *b)); /* Changes len in-place. */
-     UChar recomposed[18 * 2];
-     icu_err = U_ZERO_ERROR;
-     len = unorm2_normalize (unorm2_getNFCInstance (&icu_err), normalized, len, recomposed, ARRAY_LENGTH (recomposed), &icu_err);
-     if (U_FAILURE (icu_err))
-       return false;
-     /* We expect that recomposed has exactly one character now. */
-     if (unlikely (u_countChar32 (recomposed, len) != 1))
-       return false;
--    U16_GET_UNSAFE (recomposed, 0, *a);
-+    HB_ICU_STMT (U16_GET_UNSAFE (recomposed, 0, *a));
-     ret = true;
-   }
- 
-   return ret;
- }
- 
- 
- #if HB_USE_ATEXIT
-diff --git a/gfx/harfbuzz/src/hb-iter.hh b/gfx/harfbuzz/src/hb-iter.hh
---- a/gfx/harfbuzz/src/hb-iter.hh
-+++ b/gfx/harfbuzz/src/hb-iter.hh
-@@ -1,10 +1,11 @@
- /*
-  * Copyright © 2018  Google, Inc.
-+ * Copyright © 2019  Facebook, Inc.
-  *
-  *  This is part of HarfBuzz, a text shaping library.
-  *
-  * Permission is hereby granted, without written agreement and without
-  * license or royalty fees, to use, copy, modify, and distribute this
-  * software and its documentation for any purpose, provided that the
-  * above copyright notice and the following two paragraphs appear in
-  * all copies of this software.
-@@ -17,137 +18,815 @@
-  *
-  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-+ * Facebook Author(s): Behdad Esfahbod
-  */
- 
- #ifndef HB_ITER_HH
- #define HB_ITER_HH
- 
- #include "hb.hh"
--#include "hb-null.hh"
-+#include "hb-algs.hh"
-+#include "hb-meta.hh"
- 
- 
- /* Unified iterator object.
-  *
-  * The goal of this template is to make the same iterator interface
-  * available to all types, and make it very easy and compact to use.
-  * hb_iter_tator objects are small, light-weight, objects that can be
-  * copied by value.  If the collection / object being iterated on
-  * is writable, then the iterator returns lvalues, otherwise it
-  * returns rvalues.
-+ *
-+ * TODO Document more.
-+ *
-+ * If iterator implementation implements operator!=, then can be
-+ * used in range-based for loop.  That comes free if the iterator
-+ * is random-access.  Otherwise, the range-based for loop incurs
-+ * one traversal to find end(), which can be avoided if written
-+ * as a while-style for loop, or if iterator implements a faster
-+ * __end__() method.
-+ * TODO When opting in for C++17, address this by changing return
-+ * type of .end()?
-+ */
-+
-+/*
-+ * Base classes for iterators.
-  */
- 
- /* Base class for all iterators. */
--template <typename Iter, typename Item = typename Iter::__item_type__>
-+template <typename iter_t, typename Item = typename iter_t::__item_t__>
- struct hb_iter_t
- {
--  typedef Iter iter_t;
--  typedef iter_t const_iter_t;
-   typedef Item item_t;
-   static constexpr unsigned item_size = hb_static_size (Item);
-+  static constexpr bool is_iterator = true;
-+  static constexpr bool is_random_access_iterator = false;
-+  static constexpr bool is_sorted_iterator = false;
- 
-   private:
-   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-   const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
-         iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
-   public:
- 
-+  /* TODO:
-+   * Port operators below to use hb_enable_if to sniff which method implements
-+   * an operator and use it, and remove hb_iter_fallback_mixin_t completely. */
-+
-   /* Operators. */
--  operator iter_t () { return iter(); }
--  explicit_operator bool () const { return more (); }
--  item_t& operator * () const { return item (); }
--  item_t& operator [] (signed i) const { return item_at ((unsigned) i); }
--  iter_t& operator += (unsigned count) { forward (count); return *thiz(); }
--  iter_t& operator ++ () { next (); return *thiz(); }
--  iter_t& operator -= (unsigned count) { rewind (count); return *thiz(); }
--  iter_t& operator -- () { prev (); return *thiz(); }
--  iter_t operator + (unsigned count) { iter_t c (*thiz()); c += count; return c; }
-+  iter_t iter () const { return *thiz(); }
-+  iter_t operator + () const { return *thiz(); }
-+  iter_t begin () const { return *thiz(); }
-+  iter_t end () const { return thiz()->__end__ (); }
-+  explicit operator bool () const { return thiz()->__more__ (); }
-+  unsigned len () const { return thiz()->__len__ (); }
-+  /* The following can only be enabled if item_t is reference type.  Otherwise
-+   * it will be returning pointer to temporary rvalue.
-+   * TODO Use a wrapper return type to fix for non-reference type. */
-+  template <typename T = item_t,
-+	    hb_enable_if (hb_is_reference (T))>
-+  hb_remove_reference<item_t>* operator -> () const { return hb_addressof (**thiz()); }
-+  item_t operator * () const { return thiz()->__item__ (); }
-+  item_t operator * () { return thiz()->__item__ (); }
-+  item_t operator [] (unsigned i) const { return thiz()->__item_at__ (i); }
-+  item_t operator [] (unsigned i) { return thiz()->__item_at__ (i); }
-+  iter_t& operator += (unsigned count) &  { thiz()->__forward__ (count); return *thiz(); }
-+  iter_t  operator += (unsigned count) && { thiz()->__forward__ (count); return *thiz(); }
-+  iter_t& operator ++ () &  { thiz()->__next__ (); return *thiz(); }
-+  iter_t  operator ++ () && { thiz()->__next__ (); return *thiz(); }
-+  iter_t& operator -= (unsigned count) &  { thiz()->__rewind__ (count); return *thiz(); }
-+  iter_t  operator -= (unsigned count) && { thiz()->__rewind__ (count); return *thiz(); }
-+  iter_t& operator -- () &  { thiz()->__prev__ (); return *thiz(); }
-+  iter_t  operator -- () && { thiz()->__prev__ (); return *thiz(); }
-+  iter_t operator + (unsigned count) const { auto c = thiz()->iter (); c += count; return c; }
-+  friend iter_t operator + (unsigned count, const iter_t &it) { return it + count; }
-   iter_t operator ++ (int) { iter_t c (*thiz()); ++*thiz(); return c; }
--  iter_t operator - (unsigned count) { iter_t c (*thiz()); c -= count; return c; }
-+  iter_t operator - (unsigned count) const { auto c = thiz()->iter (); c -= count; return c; }
-   iter_t operator -- (int) { iter_t c (*thiz()); --*thiz(); return c; }
--
--  /* Methods. */
--  iter_t iter () const { return *thiz(); }
--  const_iter_t const_iter () const { return iter (); }
--  item_t& item () const { return thiz()->__item__ (); }
--  item_t& item_at (unsigned i) const { return thiz()->__item_at__ (i); }
--  bool more () const { return thiz()->__more__ (); }
--  unsigned len () const { return thiz()->__len__ (); }
--  void next () { thiz()->__next__ (); }
--  void forward (unsigned n) { thiz()->__forward__ (n); }
--  void prev () { thiz()->__prev__ (); }
--  void rewind (unsigned n) { thiz()->__rewind__ (n); }
--  bool random_access () const { return thiz()->__random_access__ (); }
-+  template <typename T>
-+  iter_t& operator >> (T &v) &  { v = **thiz(); ++*thiz(); return *thiz(); }
-+  template <typename T>
-+  iter_t  operator >> (T &v) && { v = **thiz(); ++*thiz(); return *thiz(); }
-+  template <typename T>
-+  iter_t& operator << (const T v) &  { **thiz() = v; ++*thiz(); return *thiz(); }
-+  template <typename T>
-+  iter_t  operator << (const T v) && { **thiz() = v; ++*thiz(); return *thiz(); }
- 
-   protected:
--  hb_iter_t () {}
--  hb_iter_t (const hb_iter_t &o HB_UNUSED) {}
--  void operator = (const hb_iter_t &o HB_UNUSED) {}
-+  hb_iter_t () = default;
-+  hb_iter_t (const hb_iter_t &o HB_UNUSED) = default;
-+  hb_iter_t (hb_iter_t &&o HB_UNUSED) = default;
-+  hb_iter_t& operator = (const hb_iter_t &o HB_UNUSED) = default;
-+  hb_iter_t& operator = (hb_iter_t &&o HB_UNUSED) = default;
- };
- 
--/* Base class for sorted iterators.  Does not enforce anything.
-- * Just for class taxonomy and requirements. */
--template <typename Iter, typename Item = typename Iter::__item_type__>
--struct hb_sorted_iter_t : hb_iter_t<Iter, Item>
-+#define HB_ITER_USING(Name) \
-+  using item_t = typename Name::item_t; \
-+  using Name::begin; \
-+  using Name::end; \
-+  using Name::item_size; \
-+  using Name::is_iterator; \
-+  using Name::iter; \
-+  using Name::operator bool; \
-+  using Name::len; \
-+  using Name::operator ->; \
-+  using Name::operator *; \
-+  using Name::operator []; \
-+  using Name::operator +=; \
-+  using Name::operator ++; \
-+  using Name::operator -=; \
-+  using Name::operator --; \
-+  using Name::operator +; \
-+  using Name::operator -; \
-+  using Name::operator >>; \
-+  using Name::operator <<; \
-+  static_assert (true, "")
-+
-+/* Returns iterator / item type of a type. */
-+template <typename Iterable>
-+using hb_iter_type = decltype (hb_deref (hb_declval (Iterable)).iter ());
-+template <typename Iterable>
-+using hb_item_type = decltype (*hb_deref (hb_declval (Iterable)).iter ());
-+
-+
-+template <typename> struct hb_array_t;
-+
-+struct
- {
--  protected:
--  hb_sorted_iter_t () {}
--  hb_sorted_iter_t (const hb_sorted_iter_t &o) : hb_iter_t<Iter, Item> (o) {}
--  void operator = (const hb_sorted_iter_t &o HB_UNUSED) {}
--};
-+  template <typename T> hb_iter_type<T>
-+  operator () (T&& c) const
-+  { return hb_deref (hb_forward<T> (c)).iter (); }
-+
-+  /* Specialization for C arrays. */
-+
-+  template <typename Type> inline hb_array_t<Type>
-+  operator () (Type *array, unsigned int length) const
-+  { return hb_array_t<Type> (array, length); }
-+
-+  template <typename Type, unsigned int length> hb_array_t<Type>
-+  operator () (Type (&array)[length]) const
-+  { return hb_array_t<Type> (array, length); }
-+
-+}
-+HB_FUNCOBJ (hb_iter);
- 
- /* Mixin to fill in what the subclass doesn't provide. */
--template <typename iter_t, typename item_t = typename iter_t::__item_type__>
--struct hb_iter_mixin_t
-+template <typename iter_t, typename item_t = typename iter_t::__item_t__>
-+struct hb_iter_fallback_mixin_t
- {
-   private:
-   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
-   const iter_t* thiz () const { return static_cast<const iter_t *> (this); }
-         iter_t* thiz ()       { return static_cast<      iter_t *> (this); }
-   public:
- 
-   /* Access: Implement __item__(), or __item_at__() if random-access. */
--  item_t& __item__ () const { return thiz()->item_at (0); }
--  item_t& __item_at__ (unsigned i) const { return *(thiz() + i); }
-+  item_t __item__ () const { return (*thiz())[0]; }
-+  item_t __item_at__ (unsigned i) const { return *(*thiz() + i); }
- 
-   /* Termination: Implement __more__(), or __len__() if random-access. */
--  bool __more__ () const { return thiz()->__len__ (); }
-+  bool __more__ () const { return bool (thiz()->len ()); }
-   unsigned __len__ () const
--  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; }; return l; }
-+  { iter_t c (*thiz()); unsigned l = 0; while (c) { c++; l++; } return l; }
- 
-   /* Advancing: Implement __next__(), or __forward__() if random-access. */
--  void __next__ () { thiz()->forward (1); }
--  void __forward__ (unsigned n) { while (n--) thiz()->next (); }
-+  void __next__ () { *thiz() += 1; }
-+  void __forward__ (unsigned n) { while (*thiz() && n--) ++*thiz(); }
- 
-   /* Rewinding: Implement __prev__() or __rewind__() if bidirectional. */
--  void __prev__ () { thiz()->rewind (1); }
--  void __rewind__ (unsigned n) { while (n--) thiz()->prev (); }
-+  void __prev__ () { *thiz() -= 1; }
-+  void __rewind__ (unsigned n) { while (*thiz() && n--) --*thiz(); }
-+
-+  /* Range-based for: Implement __end__() if can be done faster,
-+   * and operator!=. */
-+  iter_t __end__ () const
-+  {
-+    if (thiz()->is_random_access_iterator)
-+      return *thiz() + thiz()->len ();
-+    /* Above expression loops twice. Following loops once. */
-+    auto it = *thiz();
-+    while (it) ++it;
-+    return it;
-+  }
-+
-+  protected:
-+  hb_iter_fallback_mixin_t () = default;
-+  hb_iter_fallback_mixin_t (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default;
-+  hb_iter_fallback_mixin_t (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default;
-+  hb_iter_fallback_mixin_t& operator = (const hb_iter_fallback_mixin_t &o HB_UNUSED) = default;
-+  hb_iter_fallback_mixin_t& operator = (hb_iter_fallback_mixin_t &&o HB_UNUSED) = default;
-+};
-+
-+template <typename iter_t, typename item_t = typename iter_t::__item_t__>
-+struct hb_iter_with_fallback_t :
-+  hb_iter_t<iter_t, item_t>,
-+  hb_iter_fallback_mixin_t<iter_t, item_t>
-+{
-+  protected:
-+  hb_iter_with_fallback_t () = default;
-+  hb_iter_with_fallback_t (const hb_iter_with_fallback_t &o HB_UNUSED) = default;
-+  hb_iter_with_fallback_t (hb_iter_with_fallback_t &&o HB_UNUSED) = default;
-+  hb_iter_with_fallback_t& operator = (const hb_iter_with_fallback_t &o HB_UNUSED) = default;
-+  hb_iter_with_fallback_t& operator = (hb_iter_with_fallback_t &&o HB_UNUSED) = default;
-+};
-+
-+/*
-+ * Meta-programming predicates.
-+ */
-+
-+/* hb_is_iterator() / hb_is_iterator_of() */
-+
-+template<typename Iter, typename Item>
-+struct hb_is_iterator_of
-+{
-+  template <typename Item2 = Item>
-+  static hb_true_type impl (hb_priority<2>, hb_iter_t<Iter, hb_type_identity<Item2>> *);
-+  static hb_false_type impl (hb_priority<0>, const void *);
-+
-+  public:
-+  static constexpr bool value = decltype (impl (hb_prioritize, hb_declval (Iter*)))::value;
-+};
-+#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
-+#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
-+
-+/* hb_is_iterable() */
-+
-+template <typename T>
-+struct hb_is_iterable
-+{
-+  private:
-+
-+  template <typename U>
-+  static auto impl (hb_priority<1>) -> decltype (hb_declval (U).iter (), hb_true_type ());
-+
-+  template <typename>
-+  static hb_false_type impl (hb_priority<0>);
-+
-+  public:
-+  static constexpr bool value = decltype (impl<T> (hb_prioritize))::value;
-+};
-+#define hb_is_iterable(Iterable) hb_is_iterable<Iterable>::value
-+
-+/* hb_is_source_of() / hb_is_sink_of() */
-+
-+template<typename Iter, typename Item>
-+struct hb_is_source_of
-+{
-+  private:
-+  template <typename Iter2 = Iter,
-+	    hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<hb_add_const<Item>>))>
-+  static hb_true_type impl (hb_priority<2>);
-+  template <typename Iter2 = Iter>
-+  static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) >> hb_declval (Item &), hb_true_type ());
-+  static hb_false_type impl (hb_priority<0>);
-+
-+  public:
-+  static constexpr bool value = decltype (impl (hb_prioritize))::value;
-+};
-+#define hb_is_source_of(Iter, Item) hb_is_source_of<Iter, Item>::value
-+
-+template<typename Iter, typename Item>
-+struct hb_is_sink_of
-+{
-+  private:
-+  template <typename Iter2 = Iter,
-+	    hb_enable_if (hb_is_convertible (typename Iter2::item_t, hb_add_lvalue_reference<Item>))>
-+  static hb_true_type impl (hb_priority<2>);
-+  template <typename Iter2 = Iter>
-+  static auto impl (hb_priority<1>) -> decltype (hb_declval (Iter2) << hb_declval (Item), hb_true_type ());
-+  static hb_false_type impl (hb_priority<0>);
-+
-+  public:
-+  static constexpr bool value = decltype (impl (hb_prioritize))::value;
-+};
-+#define hb_is_sink_of(Iter, Item) hb_is_sink_of<Iter, Item>::value
-+
-+/* This is commonly used, so define: */
-+#define hb_is_sorted_source_of(Iter, Item) \
-+	(hb_is_source_of(Iter, Item) && Iter::is_sorted_iterator)
-+
-+
-+/* Range-based 'for' for iterables. */
-+
-+template <typename Iterable,
-+	  hb_requires (hb_is_iterable (Iterable))>
-+static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ())
-+
-+template <typename Iterable,
-+	  hb_requires (hb_is_iterable (Iterable))>
-+static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ())
-+
-+/* begin()/end() are NOT looked up non-ADL.  So each namespace must declare them.
-+ * Do it for namespace OT. */
-+namespace OT {
-+
-+template <typename Iterable,
-+	  hb_requires (hb_is_iterable (Iterable))>
-+static inline auto begin (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).begin ())
-+
-+template <typename Iterable,
-+	  hb_requires (hb_is_iterable (Iterable))>
-+static inline auto end (Iterable&& iterable) HB_AUTO_RETURN (hb_iter (iterable).end ())
-+
-+}
-+
-+
-+/*
-+ * Adaptors, combiners, etc.
-+ */
-+
-+template <typename Lhs, typename Rhs,
-+	  hb_requires (hb_is_iterator (Lhs))>
-+static inline auto
-+operator | (Lhs&& lhs, Rhs&& rhs) HB_AUTO_RETURN (hb_forward<Rhs> (rhs) (hb_forward<Lhs> (lhs)))
-+
-+/* hb_map(), hb_filter(), hb_reduce() */
- 
--  /* Random access: Return true if item_at(), len(), forward() are fast. */
--  bool __random_access__ () const { return false; }
-+enum  class hb_function_sortedness_t {
-+  NOT_SORTED,
-+  RETAINS_SORTING,
-+  SORTED,
-+};
-+
-+template <typename Iter, typename Proj, hb_function_sortedness_t Sorted,
-+	 hb_requires (hb_is_iterator (Iter))>
-+struct hb_map_iter_t :
-+  hb_iter_t<hb_map_iter_t<Iter, Proj, Sorted>,
-+	    decltype (hb_get (hb_declval (Proj), *hb_declval (Iter)))>
-+{
-+  hb_map_iter_t (const Iter& it, Proj f_) : it (it), f (f_) {}
-+
-+  typedef decltype (hb_get (hb_declval (Proj), *hb_declval (Iter))) __item_t__;
-+  static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
-+  static constexpr bool is_sorted_iterator =
-+    Sorted == hb_function_sortedness_t::SORTED ? true :
-+    Sorted == hb_function_sortedness_t::RETAINS_SORTING ? Iter::is_sorted_iterator :
-+    false;
-+  __item_t__ __item__ () const { return hb_get (f.get (), *it); }
-+  __item_t__ __item_at__ (unsigned i) const { return hb_get (f.get (), it[i]); }
-+  bool __more__ () const { return bool (it); }
-+  unsigned __len__ () const { return it.len (); }
-+  void __next__ () { ++it; }
-+  void __forward__ (unsigned n) { it += n; }
-+  void __prev__ () { --it; }
-+  void __rewind__ (unsigned n) { it -= n; }
-+  hb_map_iter_t __end__ () const { return hb_map_iter_t (it.end (), f); }
-+  bool operator != (const hb_map_iter_t& o) const
-+  { return it != o.it; }
-+
-+  private:
-+  Iter it;
-+  hb_reference_wrapper<Proj> f;
-+};
-+
-+template <typename Proj, hb_function_sortedness_t Sorted>
-+struct hb_map_iter_factory_t
-+{
-+  hb_map_iter_factory_t (Proj f) : f (f) {}
-+
-+  template <typename Iter,
-+	    hb_requires (hb_is_iterator (Iter))>
-+  hb_map_iter_t<Iter, Proj, Sorted>
-+  operator () (Iter it)
-+  { return hb_map_iter_t<Iter, Proj, Sorted> (it, f); }
-+
-+  private:
-+  Proj f;
- };
-+struct
-+{
-+  template <typename Proj>
-+  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::NOT_SORTED>
-+  operator () (Proj&& f) const
-+  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::NOT_SORTED> (f); }
-+}
-+HB_FUNCOBJ (hb_map);
-+struct
-+{
-+  template <typename Proj>
-+  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::RETAINS_SORTING>
-+  operator () (Proj&& f) const
-+  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::RETAINS_SORTING> (f); }
-+}
-+HB_FUNCOBJ (hb_map_retains_sorting);
-+struct
-+{
-+  template <typename Proj>
-+  hb_map_iter_factory_t<Proj, hb_function_sortedness_t::SORTED>
-+  operator () (Proj&& f) const
-+  { return hb_map_iter_factory_t<Proj, hb_function_sortedness_t::SORTED> (f); }
-+}
-+HB_FUNCOBJ (hb_map_sorted);
-+
-+template <typename Iter, typename Pred, typename Proj,
-+	 hb_requires (hb_is_iterator (Iter))>
-+struct hb_filter_iter_t :
-+  hb_iter_with_fallback_t<hb_filter_iter_t<Iter, Pred, Proj>,
-+			  typename Iter::item_t>
-+{
-+  hb_filter_iter_t (const Iter& it_, Pred p_, Proj f_) : it (it_), p (p_), f (f_)
-+  { while (it && !hb_has (p.get (), hb_get (f.get (), *it))) ++it; }
-+
-+  typedef typename Iter::item_t __item_t__;
-+  static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
-+  __item_t__ __item__ () const { return *it; }
-+  bool __more__ () const { return bool (it); }
-+  void __next__ () { do ++it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
-+  void __prev__ () { do --it; while (it && !hb_has (p.get (), hb_get (f.get (), *it))); }
-+  hb_filter_iter_t __end__ () const { return hb_filter_iter_t (it.end (), p, f); }
-+  bool operator != (const hb_filter_iter_t& o) const
-+  { return it != o.it; }
-+
-+  private:
-+  Iter it;
-+  hb_reference_wrapper<Pred> p;
-+  hb_reference_wrapper<Proj> f;
-+};
-+template <typename Pred, typename Proj>
-+struct hb_filter_iter_factory_t
-+{
-+  hb_filter_iter_factory_t (Pred p, Proj f) : p (p), f (f) {}
-+
-+  template <typename Iter,
-+	    hb_requires (hb_is_iterator (Iter))>
-+  hb_filter_iter_t<Iter, Pred, Proj>
-+  operator () (Iter it)
-+  { return hb_filter_iter_t<Iter, Pred, Proj> (it, p, f); }
-+
-+  private:
-+  Pred p;
-+  Proj f;
-+};
-+struct
-+{
-+  template <typename Pred = decltype ((hb_identity)),
-+	    typename Proj = decltype ((hb_identity))>
-+  hb_filter_iter_factory_t<Pred, Proj>
-+  operator () (Pred&& p = hb_identity, Proj&& f = hb_identity) const
-+  { return hb_filter_iter_factory_t<Pred, Proj> (p, f); }
-+}
-+HB_FUNCOBJ (hb_filter);
-+
-+template <typename Redu, typename InitT>
-+struct hb_reduce_t
-+{
-+  hb_reduce_t (Redu r, InitT init_value) : r (r), init_value (init_value) {}
-+
-+  template <typename Iter,
-+	    hb_requires (hb_is_iterator (Iter)),
-+	    typename AccuT = decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>
-+  AccuT
-+  operator () (Iter it)
-+  {
-+    AccuT value = init_value;
-+    for (; it; ++it)
-+      value = r (value, *it);
-+    return value;
-+  }
-+
-+  private:
-+  Redu r;
-+  InitT init_value;
-+};
-+struct
-+{
-+  template <typename Redu, typename InitT>
-+  hb_reduce_t<Redu, InitT>
-+  operator () (Redu&& r, InitT init_value) const
-+  { return hb_reduce_t<Redu, InitT> (r, init_value); }
-+}
-+HB_FUNCOBJ (hb_reduce);
- 
- 
--/* Functions operating on iterators or iteratables. */
-+/* hb_zip() */
-+
-+template <typename A, typename B>
-+struct hb_zip_iter_t :
-+  hb_iter_t<hb_zip_iter_t<A, B>,
-+	    hb_pair_t<typename A::item_t, typename B::item_t>>
-+{
-+  hb_zip_iter_t () {}
-+  hb_zip_iter_t (const A& a, const B& b) : a (a), b (b) {}
-+
-+  typedef hb_pair_t<typename A::item_t, typename B::item_t> __item_t__;
-+  static constexpr bool is_random_access_iterator =
-+    A::is_random_access_iterator &&
-+    B::is_random_access_iterator;
-+  /* Note.  The following categorization is only valid if A is strictly sorted,
-+   * ie. does NOT have duplicates.  Previously I tried to categorize sortedness
-+   * more granularly, see commits:
-+   *
-+   *   513762849a683914fc266a17ddf38f133cccf072
-+   *   4d3cf2adb669c345cc43832d11689271995e160a
-+   *
-+   * However, that was not enough, since hb_sorted_array_t, hb_sorted_vector_t,
-+   * SortedArrayOf, etc all needed to be updated to add more variants.  At that
-+   * point I saw it not worth the effort, and instead we now deem all sorted
-+   * collections as essentially strictly-sorted for the purposes of zip.
-+   *
-+   * The above assumption is not as bad as it sounds.  Our "sorted" comes with
-+   * no guarantees.  It's just a contract, put in place to help you remember,
-+   * and think about, whether an iterator you receive is expected to be
-+   * sorted or not.  As such, it's not perfect by definition, and should not
-+   * be treated so.  The inaccuracy here just errs in the direction of being
-+   * more permissive, so your code compiles instead of erring on the side of
-+   * marking your zipped iterator unsorted in which case your code won't
-+   * compile.
-+   *
-+   * This semantical limitation does NOT affect logic in any other place I
-+   * know of as of this writing.
-+   */
-+  static constexpr bool is_sorted_iterator = A::is_sorted_iterator;
-+
-+  __item_t__ __item__ () const { return __item_t__ (*a, *b); }
-+  __item_t__ __item_at__ (unsigned i) const { return __item_t__ (a[i], b[i]); }
-+  bool __more__ () const { return bool (a) && bool (b); }
-+  unsigned __len__ () const { return hb_min (a.len (), b.len ()); }
-+  void __next__ () { ++a; ++b; }
-+  void __forward__ (unsigned n) { a += n; b += n; }
-+  void __prev__ () { --a; --b; }
-+  void __rewind__ (unsigned n) { a -= n; b -= n; }
-+  hb_zip_iter_t __end__ () const { return hb_zip_iter_t (a.end (), b.end ()); }
-+  /* Note, we should stop if ANY of the iters reaches end.  As such two compare
-+   * unequal if both items are unequal, NOT if either is unequal. */
-+  bool operator != (const hb_zip_iter_t& o) const
-+  { return a != o.a && b != o.b; }
-+
-+  private:
-+  A a;
-+  B b;
-+};
-+struct
-+{
-+  template <typename A, typename B,
-+	    hb_requires (hb_is_iterable (A) && hb_is_iterable (B))>
-+  hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>>
-+  operator () (A&& a, B&& b) const
-+  { return hb_zip_iter_t<hb_iter_type<A>, hb_iter_type<B>> (hb_iter (a), hb_iter (b)); }
-+}
-+HB_FUNCOBJ (hb_zip);
-+
-+/* hb_apply() */
-+
-+template <typename Appl>
-+struct hb_apply_t
-+{
-+  hb_apply_t (Appl a) : a (a) {}
-+
-+  template <typename Iter,
-+	    hb_requires (hb_is_iterator (Iter))>
-+  void operator () (Iter it)
-+  {
-+    for (; it; ++it)
-+      (void) hb_invoke (a, *it);
-+  }
-+
-+  private:
-+  Appl a;
-+};
-+struct
-+{
-+  template <typename Appl> hb_apply_t<Appl>
-+  operator () (Appl&& a) const
-+  { return hb_apply_t<Appl> (a); }
-+
-+  template <typename Appl> hb_apply_t<Appl&>
-+  operator () (Appl *a) const
-+  { return hb_apply_t<Appl&> (*a); }
-+}
-+HB_FUNCOBJ (hb_apply);
-+
-+/* hb_iota()/hb_range() */
-+
-+template <typename T, typename S>
-+struct hb_counter_iter_t :
-+  hb_iter_t<hb_counter_iter_t<T, S>, T>
-+{
-+  hb_counter_iter_t (T start, T end_, S step) : v (start), end_ (end_for (start, end_, step)), step (step) {}
-+
-+  typedef T __item_t__;
-+  static constexpr bool is_random_access_iterator = true;
-+  static constexpr bool is_sorted_iterator = true;
-+  __item_t__ __item__ () const { return +v; }
-+  __item_t__ __item_at__ (unsigned j) const { return v + j * step; }
-+  bool __more__ () const { return v != end_; }
-+  unsigned __len__ () const { return !step ? UINT_MAX : (end_ - v) / step; }
-+  void __next__ () { v += step; }
-+  void __forward__ (unsigned n) { v += n * step; }
-+  void __prev__ () { v -= step; }
-+  void __rewind__ (unsigned n) { v -= n * step; }
-+  hb_counter_iter_t __end__ () const { return hb_counter_iter_t (end_, end_, step); }
-+  bool operator != (const hb_counter_iter_t& o) const
-+  { return v != o.v; }
-+
-+  private:
-+  static inline T end_for (T start, T end_, S step)
-+  {
-+    if (!step)
-+      return end_;
-+    auto res = (end_ - start) % step;
-+    if (!res)
-+      return end_;
-+    end_ += step - res;
-+    return end_;
-+  }
-+
-+  private:
-+  T v;
-+  T end_;
-+  S step;
-+};
-+struct
-+{
-+  template <typename T = unsigned, typename S = unsigned> hb_counter_iter_t<T, S>
-+  operator () (T start = 0u, S&& step = 1u) const
-+  { return hb_counter_iter_t<T, S> (start, step >= 0 ? hb_int_max (T) : hb_int_min (T), step); }
-+}
-+HB_FUNCOBJ (hb_iota);
-+struct
-+{
-+  template <typename T = unsigned> hb_counter_iter_t<T, unsigned>
-+  operator () (T end = (unsigned) -1) const
-+  { return hb_counter_iter_t<T, unsigned> (0, end, 1u); }
-+
-+  template <typename T, typename S = unsigned> hb_counter_iter_t<T, S>
-+  operator () (T start, T end, S&& step = 1u) const
-+  { return hb_counter_iter_t<T, S> (start, end, step); }
-+}
-+HB_FUNCOBJ (hb_range);
- 
--template <typename C, typename V> inline void
--hb_fill (const C& c, const V &v)
-+/* hb_enumerate */
-+
-+struct
-+{
-+  template <typename Iterable,
-+	    typename Index = unsigned,
-+	    hb_requires (hb_is_iterable (Iterable))>
-+  auto operator () (Iterable&& it, Index start = 0u) const HB_AUTO_RETURN
-+  ( hb_zip (hb_iota (start), it) )
-+}
-+HB_FUNCOBJ (hb_enumerate);
-+
-+
-+/* hb_sink() */
-+
-+template <typename Sink>
-+struct hb_sink_t
-+{
-+  hb_sink_t (Sink s) : s (s) {}
-+
-+  template <typename Iter,
-+	    hb_requires (hb_is_iterator (Iter))>
-+  void operator () (Iter it)
-+  {
-+    for (; it; ++it)
-+      s << *it;
-+  }
-+
-+  private:
-+  Sink s;
-+};
-+struct
-+{
-+  template <typename Sink> hb_sink_t<Sink>
-+  operator () (Sink&& s) const
-+  { return hb_sink_t<Sink> (s); }
-+
-+  template <typename Sink> hb_sink_t<Sink&>
-+  operator () (Sink *s) const
-+  { return hb_sink_t<Sink&> (*s); }
-+}
-+HB_FUNCOBJ (hb_sink);
-+
-+/* hb-drain: hb_sink to void / blackhole / /dev/null. */
-+
-+struct
-+{
-+  template <typename Iter,
-+	    hb_requires (hb_is_iterator (Iter))>
-+  void operator () (Iter it) const
-+  {
-+    for (; it; ++it)
-+      (void) *it;
-+  }
-+}
-+HB_FUNCOBJ (hb_drain);
-+
-+/* hb_unzip(): unzip and sink to two sinks. */
-+
-+template <typename Sink1, typename Sink2>
-+struct hb_unzip_t
- {
--  for (typename C::iter_t i (c); i; i++)
--    hb_assign (*i, v);
-+  hb_unzip_t (Sink1 s1, Sink2 s2) : s1 (s1), s2 (s2) {}
-+
-+  template <typename Iter,
-+	    hb_requires (hb_is_iterator (Iter))>
-+  void operator () (Iter it)
-+  {
-+    for (; it; ++it)
-+    {
-+      const auto &v = *it;
-+      s1 << v.first;
-+      s2 << v.second;
-+    }
-+  }
-+
-+  private:
-+  Sink1 s1;
-+  Sink2 s2;
-+};
-+struct
-+{
-+  template <typename Sink1, typename Sink2> hb_unzip_t<Sink1, Sink2>
-+  operator () (Sink1&& s1, Sink2&& s2) const
-+  { return hb_unzip_t<Sink1, Sink2> (s1, s2); }
-+
-+  template <typename Sink1, typename Sink2> hb_unzip_t<Sink1&, Sink2&>
-+  operator () (Sink1 *s1, Sink2 *s2) const
-+  { return hb_unzip_t<Sink1&, Sink2&> (*s1, *s2); }
-+}
-+HB_FUNCOBJ (hb_unzip);
-+
-+
-+/* hb-all, hb-any, hb-none. */
-+
-+struct
-+{
-+  template <typename Iterable,
-+	    typename Pred = decltype ((hb_identity)),
-+	    typename Proj = decltype ((hb_identity)),
-+	    hb_requires (hb_is_iterable (Iterable))>
-+  bool operator () (Iterable&& c,
-+		    Pred&& p = hb_identity,
-+		    Proj&& f = hb_identity) const
-+  {
-+    for (auto it = hb_iter (c); it; ++it)
-+      if (!hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
-+	return false;
-+    return true;
-+  }
-+}
-+HB_FUNCOBJ (hb_all);
-+struct
-+{
-+  template <typename Iterable,
-+	    typename Pred = decltype ((hb_identity)),
-+	    typename Proj = decltype ((hb_identity)),
-+	    hb_requires (hb_is_iterable (Iterable))>
-+  bool operator () (Iterable&& c,
-+		    Pred&& p = hb_identity,
-+		    Proj&& f = hb_identity) const
-+  {
-+    for (auto it = hb_iter (c); it; ++it)
-+      if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
-+	return true;
-+    return false;
-+  }
-+}
-+HB_FUNCOBJ (hb_any);
-+struct
-+{
-+  template <typename Iterable,
-+	    typename Pred = decltype ((hb_identity)),
-+	    typename Proj = decltype ((hb_identity)),
-+	    hb_requires (hb_is_iterable (Iterable))>
-+  bool operator () (Iterable&& c,
-+		    Pred&& p = hb_identity,
-+		    Proj&& f = hb_identity) const
-+  {
-+    for (auto it = hb_iter (c); it; ++it)
-+      if (hb_match (hb_forward<Pred> (p), hb_get (hb_forward<Proj> (f), *it)))
-+	return false;
-+    return true;
-+  }
-+}
-+HB_FUNCOBJ (hb_none);
-+
-+/*
-+ * Algorithms operating on iterators.
-+ */
-+
-+template <typename C, typename V,
-+	  hb_requires (hb_is_iterable (C))>
-+inline void
-+hb_fill (C& c, const V &v)
-+{
-+  for (auto i = hb_iter (c); i; i++)
-+    *i = v;
- }
- 
--template <typename S, typename D> inline bool
--hb_copy (hb_iter_t<D> &id, hb_iter_t<S> &is)
-+template <typename S, typename D>
-+inline void
-+hb_copy (S&& is, D&& id)
- {
--  for (; id && is; ++id, ++is)
--    *id = *is;
--  return !is;
-+  hb_iter (is) | hb_sink (id);
- }
- 
- 
- #endif /* HB_ITER_HH */
-diff --git a/gfx/harfbuzz/src/hb-machinery.hh b/gfx/harfbuzz/src/hb-machinery.hh
---- a/gfx/harfbuzz/src/hb-machinery.hh
-+++ b/gfx/harfbuzz/src/hb-machinery.hh
-@@ -27,18 +27,19 @@
-  */
- 
- #ifndef HB_MACHINERY_HH
- #define HB_MACHINERY_HH
- 
- #include "hb.hh"
- #include "hb-blob.hh"
- 
--#include "hb-array.hh"
--#include "hb-vector.hh"
-+#include "hb-dispatch.hh"
-+#include "hb-sanitize.hh"
-+#include "hb-serialize.hh"
- 
- 
- /*
-  * Casts
-  */
- 
- /* Cast to struct T, reference to reference */
- template<typename Type, typename TObject>
-@@ -138,627 +139,16 @@ static inline Type& StructAfter(TObject 
-   static constexpr unsigned null_size = (size); \
-   static constexpr unsigned min_size = (size)
- 
- #define DEFINE_SIZE_ARRAY_SIZED(size, array) \
-   unsigned int get_size () const { return (size - (array).min_size + (array).get_size ()); } \
-   DEFINE_SIZE_ARRAY(size, array)
- 
- 
--/*
-- * Dispatch
-- */
--
--template <typename Context, typename Return, unsigned int MaxDebugDepth>
--struct hb_dispatch_context_t
--{
--  static constexpr unsigned max_debug_depth = MaxDebugDepth;
--  typedef Return return_t;
--  template <typename T, typename F>
--  bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
--  static return_t no_dispatch_return_value () { return Context::default_return_value (); }
--  static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; }
--};
--
--
--/*
-- * Sanitize
-- *
-- *
-- * === Introduction ===
-- *
-- * The sanitize machinery is at the core of our zero-cost font loading.  We
-- * mmap() font file into memory and create a blob out of it.  Font subtables
-- * are returned as a readonly sub-blob of the main font blob.  These table
-- * blobs are then sanitized before use, to ensure invalid memory access does
-- * not happen.  The toplevel sanitize API use is like, eg. to load the 'head'
-- * table:
-- *
-- *   hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<OT::head> (face);
-- *
-- * The blob then can be converted to a head table struct with:
-- *
-- *   const head *head_table = head_blob->as<head> ();
-- *
-- * What the reference_table does is, to call hb_face_reference_table() to load
-- * the table blob, sanitize it and return either the sanitized blob, or empty
-- * blob if sanitization failed.  The blob->as() function returns the null
-- * object of its template type argument if the blob is empty.  Otherwise, it
-- * just casts the blob contents to the desired type.
-- *
-- * Sanitizing a blob of data with a type T works as follows (with minor
-- * simplification):
-- *
-- *   - Cast blob content to T*, call sanitize() method of it,
-- *   - If sanitize succeeded, return blob.
-- *   - Otherwise, if blob is not writable, try making it writable,
-- *     or copy if cannot be made writable in-place,
-- *   - Call sanitize() again.  Return blob if sanitize succeeded.
-- *   - Return empty blob otherwise.
-- *
-- *
-- * === The sanitize() contract ===
-- *
-- * The sanitize() method of each object type shall return true if it's safe to
-- * call other methods of the object, and false otherwise.
-- *
-- * Note that what sanitize() checks for might align with what the specification
-- * describes as valid table data, but does not have to be.  In particular, we
-- * do NOT want to be pedantic and concern ourselves with validity checks that
-- * are irrelevant to our use of the table.  On the contrary, we want to be
-- * lenient with error handling and accept invalid data to the extent that it
-- * does not impose extra burden on us.
-- *
-- * Based on the sanitize contract, one can see that what we check for depends
-- * on how we use the data in other table methods.  Ie. if other table methods
-- * assume that offsets do NOT point out of the table data block, then that's
-- * something sanitize() must check for (GSUB/GPOS/GDEF/etc work this way).  On
-- * the other hand, if other methods do such checks themselves, then sanitize()
-- * does not have to bother with them (glyf/local work this way).  The choice
-- * depends on the table structure and sanitize() performance.  For example, to
-- * check glyf/loca offsets in sanitize() would cost O(num-glyphs).  We try hard
-- * to avoid such costs during font loading.  By postponing such checks to the
-- * actual glyph loading, we reduce the sanitize cost to O(1) and total runtime
-- * cost to O(used-glyphs).  As such, this is preferred.
-- *
-- * The same argument can be made re GSUB/GPOS/GDEF, but there, the table
-- * structure is so complicated that by checking all offsets at sanitize() time,
-- * we make the code much simpler in other methods, as offsets and referenced
-- * objects do not need to be validated at each use site.
-- */
--
--/* This limits sanitizing time on really broken fonts. */
--#ifndef HB_SANITIZE_MAX_EDITS
--#define HB_SANITIZE_MAX_EDITS 32
--#endif
--#ifndef HB_SANITIZE_MAX_OPS_FACTOR
--#define HB_SANITIZE_MAX_OPS_FACTOR 8
--#endif
--#ifndef HB_SANITIZE_MAX_OPS_MIN
--#define HB_SANITIZE_MAX_OPS_MIN 16384
--#endif
--#ifndef HB_SANITIZE_MAX_OPS_MAX
--#define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF
--#endif
--
--struct hb_sanitize_context_t :
--       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
--{
--  hb_sanitize_context_t () :
--	debug_depth (0),
--	start (nullptr), end (nullptr),
--	max_ops (0),
--	writable (false), edit_count (0),
--	blob (nullptr),
--	num_glyphs (65536),
--	num_glyphs_set (false) {}
--
--  const char *get_name () { return "SANITIZE"; }
--  template <typename T, typename F>
--  bool may_dispatch (const T *obj HB_UNUSED, const F *format)
--  { return format->sanitize (this); }
--  template <typename T>
--  return_t dispatch (const T &obj) { return obj.sanitize (this); }
--  static return_t default_return_value () { return true; }
--  static return_t no_dispatch_return_value () { return false; }
--  bool stop_sublookup_iteration (const return_t r) const { return !r; }
--
--  void init (hb_blob_t *b)
--  {
--    this->blob = hb_blob_reference (b);
--    this->writable = false;
--  }
--
--  void set_num_glyphs (unsigned int num_glyphs_)
--  {
--    num_glyphs = num_glyphs_;
--    num_glyphs_set = true;
--  }
--  unsigned int get_num_glyphs () { return num_glyphs; }
--
--  void set_max_ops (int max_ops_) { max_ops = max_ops_; }
--
--  template <typename T>
--  void set_object (const T *obj)
--  {
--    reset_object ();
--
--    if (!obj) return;
--
--    const char *obj_start = (const char *) obj;
--    if (unlikely (obj_start < this->start || this->end <= obj_start))
--      this->start = this->end = nullptr;
--    else
--    {
--      this->start = obj_start;
--      this->end   = obj_start + MIN<uintptr_t> (this->end - obj_start, obj->get_size ());
--    }
--  }
--
--  void reset_object ()
--  {
--    this->start = this->blob->data;
--    this->end = this->start + this->blob->length;
--    assert (this->start <= this->end); /* Must not overflow. */
--  }
--
--  void start_processing ()
--  {
--    reset_object ();
--    this->max_ops = MAX ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
--			 (unsigned) HB_SANITIZE_MAX_OPS_MIN);
--    this->edit_count = 0;
--    this->debug_depth = 0;
--
--    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
--		     "start [%p..%p] (%lu bytes)",
--		     this->start, this->end,
--		     (unsigned long) (this->end - this->start));
--  }
--
--  void end_processing ()
--  {
--    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
--		     "end [%p..%p] %u edit requests",
--		     this->start, this->end, this->edit_count);
--
--    hb_blob_destroy (this->blob);
--    this->blob = nullptr;
--    this->start = this->end = nullptr;
--  }
--
--  bool check_range (const void *base,
--		    unsigned int len) const
--  {
--    const char *p = (const char *) base;
--    bool ok = !len ||
--	      (this->start <= p &&
--	       p <= this->end &&
--	       (unsigned int) (this->end - p) >= len &&
--	       this->max_ops-- > 0);
--
--    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
--		     "check_range [%p..%p]"
--		     " (%d bytes) in [%p..%p] -> %s",
--		     p, p + len, len,
--		     this->start, this->end,
--		     ok ? "OK" : "OUT-OF-RANGE");
--
--    return likely (ok);
--  }
--
--  template <typename T>
--  bool check_range (const T *base,
--		    unsigned int a,
--		    unsigned int b) const
--  {
--    return !hb_unsigned_mul_overflows (a, b) &&
--	   this->check_range (base, a * b);
--  }
--
--  template <typename T>
--  bool check_range (const T *base,
--		    unsigned int a,
--		    unsigned int b,
--		    unsigned int c) const
--  {
--    return !hb_unsigned_mul_overflows (a, b) &&
--	   this->check_range (base, a * b, c);
--  }
--
--  template <typename T>
--  bool check_array (const T *base, unsigned int len) const
--  {
--    return this->check_range (base, len, hb_static_size (T));
--  }
--
--  template <typename T>
--  bool check_array (const T *base,
--		    unsigned int a,
--		    unsigned int b) const
--  {
--    return this->check_range (base, a, b, hb_static_size (T));
--  }
--
--  template <typename Type>
--  bool check_struct (const Type *obj) const
--  { return likely (this->check_range (obj, obj->min_size)); }
--
--  bool may_edit (const void *base, unsigned int len)
--  {
--    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
--      return false;
--
--    const char *p = (const char *) base;
--    this->edit_count++;
--
--    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
--       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
--       this->edit_count,
--       p, p + len, len,
--       this->start, this->end,
--       this->writable ? "GRANTED" : "DENIED");
--
--    return this->writable;
--  }
--
--  template <typename Type, typename ValueType>
--  bool try_set (const Type *obj, const ValueType &v)
--  {
--    if (this->may_edit (obj, hb_static_size (Type)))
--    {
--      hb_assign (* const_cast<Type *> (obj), v);
--      return true;
--    }
--    return false;
--  }
--
--  template <typename Type>
--  hb_blob_t *sanitize_blob (hb_blob_t *blob)
--  {
--    bool sane;
--
--    init (blob);
--
--  retry:
--    DEBUG_MSG_FUNC (SANITIZE, start, "start");
--
--    start_processing ();
--
--    if (unlikely (!start))
--    {
--      end_processing ();
--      return blob;
--    }
--
--    Type *t = CastP<Type> (const_cast<char *> (start));
--
--    sane = t->sanitize (this);
--    if (sane)
--    {
--      if (edit_count)
--      {
--	DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
--
--        /* sanitize again to ensure no toe-stepping */
--        edit_count = 0;
--	sane = t->sanitize (this);
--	if (edit_count) {
--	  DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
--	  sane = false;
--	}
--      }
--    }
--    else
--    {
--      if (edit_count && !writable) {
--        start = hb_blob_get_data_writable (blob, nullptr);
--	end = start + blob->length;
--
--	if (start)
--	{
--	  writable = true;
--	  /* ok, we made it writable by relocating.  try again */
--	  DEBUG_MSG_FUNC (SANITIZE, start, "retry");
--	  goto retry;
--	}
--      }
--    }
--
--    end_processing ();
--
--    DEBUG_MSG_FUNC (SANITIZE, start, sane ? "PASSED" : "FAILED");
--    if (sane)
--    {
--      hb_blob_make_immutable (blob);
--      return blob;
--    }
--    else
--    {
--      hb_blob_destroy (blob);
--      return hb_blob_get_empty ();
--    }
--  }
--
--  template <typename Type>
--  hb_blob_t *reference_table (const hb_face_t *face, hb_tag_t tableTag = Type::tableTag)
--  {
--    if (!num_glyphs_set)
--      set_num_glyphs (hb_face_get_glyph_count (face));
--    return sanitize_blob<Type> (hb_face_reference_table (face, tableTag));
--  }
--
--  mutable unsigned int debug_depth;
--  const char *start, *end;
--  mutable int max_ops;
--  private:
--  bool writable;
--  unsigned int edit_count;
--  hb_blob_t *blob;
--  unsigned int num_glyphs;
--  bool  num_glyphs_set;
--};
--
--struct hb_sanitize_with_object_t
--{
--  template <typename T>
--  hb_sanitize_with_object_t (hb_sanitize_context_t *c,
--				    const T& obj) : c (c)
--  { c->set_object (obj); }
--  ~hb_sanitize_with_object_t ()
--  { c->reset_object (); }
--
--  private:
--  hb_sanitize_context_t *c;
--};
--
--
--/*
-- * Serialize
-- */
--
--struct hb_serialize_context_t
--{
--  hb_serialize_context_t (void *start_, unsigned int size)
--  {
--    this->start = (char *) start_;
--    this->end = this->start + size;
--    reset ();
--  }
--
--  bool in_error () const { return !this->successful; }
--
--  void reset ()
--  {
--    this->successful = true;
--    this->head = this->start;
--    this->debug_depth = 0;
--  }
--
--  bool propagate_error (bool e)
--  { return this->successful = this->successful && e; }
--  template <typename T> bool propagate_error (const T &obj)
--  { return this->successful = this->successful && !obj.in_error (); }
--  template <typename T> bool propagate_error (const T *obj)
--  { return this->successful = this->successful && !obj->in_error (); }
--  template <typename T1, typename T2> bool propagate_error (T1 &o1, T2 &o2)
--  { return propagate_error (o1) && propagate_error (o2); }
--  template <typename T1, typename T2> bool propagate_error (T1 *o1, T2 *o2)
--  { return propagate_error (o1) && propagate_error (o2); }
--  template <typename T1, typename T2, typename T3>
--  bool propagate_error (T1 &o1, T2 &o2, T3 &o3)
--  { return propagate_error (o1) && propagate_error (o2, o3); }
--  template <typename T1, typename T2, typename T3>
--  bool propagate_error (T1 *o1, T2 *o2, T3 *o3)
--  { return propagate_error (o1) && propagate_error (o2, o3); }
--
--  /* To be called around main operation. */
--  template <typename Type>
--  Type *start_serialize ()
--  {
--    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
--		     "start [%p..%p] (%lu bytes)",
--		     this->start, this->end,
--		     (unsigned long) (this->end - this->start));
--
--    return start_embed<Type> ();
--  }
--  void end_serialize ()
--  {
--    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
--		     "end [%p..%p] serialized %d bytes; %s",
--		     this->start, this->end,
--		     (int) (this->head - this->start),
--		     this->successful ? "successful" : "UNSUCCESSFUL");
--  }
--
--  unsigned int length () const { return this->head - this->start; }
--
--  void align (unsigned int alignment)
--  {
--    unsigned int l = length () % alignment;
--    if (l)
--      allocate_size<void> (alignment - l);
--  }
--
--  template <typename Type>
--  Type *start_embed (const Type *_ HB_UNUSED = nullptr) const
--  {
--    Type *ret = reinterpret_cast<Type *> (this->head);
--    return ret;
--  }
--
--  template <typename Type>
--  Type *allocate_size (unsigned int size)
--  {
--    if (unlikely (!this->successful || this->end - this->head < ptrdiff_t (size))) {
--      this->successful = false;
--      return nullptr;
--    }
--    memset (this->head, 0, size);
--    char *ret = this->head;
--    this->head += size;
--    return reinterpret_cast<Type *> (ret);
--  }
--
--  template <typename Type>
--  Type *allocate_min ()
--  {
--    return this->allocate_size<Type> (Type::min_size);
--  }
--
--  template <typename Type>
--  Type *embed (const Type &obj)
--  {
--    unsigned int size = obj.get_size ();
--    Type *ret = this->allocate_size<Type> (size);
--    if (unlikely (!ret)) return nullptr;
--    memcpy (ret, &obj, size);
--    return ret;
--  }
--  template <typename Type>
--  hb_serialize_context_t &operator << (const Type &obj) { embed (obj); return *this; }
--
--  template <typename Type>
--  Type *extend_size (Type &obj, unsigned int size)
--  {
--    assert (this->start <= (char *) &obj);
--    assert ((char *) &obj <= this->head);
--    assert ((char *) &obj + size >= this->head);
--    if (unlikely (!this->allocate_size<Type> (((char *) &obj) + size - this->head))) return nullptr;
--    return reinterpret_cast<Type *> (&obj);
--  }
--
--  template <typename Type>
--  Type *extend_min (Type &obj) { return extend_size (obj, obj.min_size); }
--
--  template <typename Type>
--  Type *extend (Type &obj) { return extend_size (obj, obj.get_size ()); }
--
--  /* Output routines. */
--  template <typename Type>
--  Type *copy () const
--  {
--    assert (this->successful);
--    unsigned int len = this->head - this->start;
--    void *p = malloc (len);
--    if (p)
--      memcpy (p, this->start, len);
--    return reinterpret_cast<Type *> (p);
--  }
--  hb_bytes_t copy_bytes () const
--  {
--    assert (this->successful);
--    unsigned int len = this->head - this->start;
--    void *p = malloc (len);
--    if (p)
--      memcpy (p, this->start, len);
--    else
--      return hb_bytes_t ();
--    return hb_bytes_t ((char *) p, len);
--  }
--  hb_blob_t *copy_blob () const
--  {
--    assert (this->successful);
--    return hb_blob_create (this->start,
--			   this->head - this->start,
--			   HB_MEMORY_MODE_DUPLICATE,
--			   nullptr, nullptr);
--  }
--
--  public:
--  unsigned int debug_depth;
--  char *start, *end, *head;
--  bool successful;
--};
--
--
--
--/*
-- * Big-endian integers.
-- */
--
--template <typename Type, int Bytes> struct BEInt;
--
--template <typename Type>
--struct BEInt<Type, 1>
--{
--  public:
--  void set (Type V)      { v = V; }
--  operator Type () const { return v; }
--  private: uint8_t v;
--};
--template <typename Type>
--struct BEInt<Type, 2>
--{
--  public:
--  void set (Type V)
--  {
--    v[0] = (V >>  8) & 0xFF;
--    v[1] = (V      ) & 0xFF;
--  }
--  operator Type () const
--  {
--#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
--    defined(__BYTE_ORDER) && \
--    (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
--    /* Spoon-feed the compiler a big-endian integer with alignment 1.
--     * https://github.com/harfbuzz/harfbuzz/pull/1398 */
--    struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
--#if __BYTE_ORDER == __LITTLE_ENDIAN
--    return __builtin_bswap16 (((packed_uint16_t *) this)->v);
--#else /* __BYTE_ORDER == __BIG_ENDIAN */
--    return ((packed_uint16_t *) this)->v;
--#endif
--#endif
--    return (v[0] <<  8)
--         + (v[1]      );
--  }
--  private: uint8_t v[2];
--};
--template <typename Type>
--struct BEInt<Type, 3>
--{
--  public:
--  void set (Type V)
--  {
--    v[0] = (V >> 16) & 0xFF;
--    v[1] = (V >>  8) & 0xFF;
--    v[2] = (V      ) & 0xFF;
--  }
--  operator Type () const
--  {
--    return (v[0] << 16)
--         + (v[1] <<  8)
--         + (v[2]      );
--  }
--  private: uint8_t v[3];
--};
--template <typename Type>
--struct BEInt<Type, 4>
--{
--  public:
--  typedef Type type;
--  void set (Type V)
--  {
--    v[0] = (V >> 24) & 0xFF;
--    v[1] = (V >> 16) & 0xFF;
--    v[2] = (V >>  8) & 0xFF;
--    v[3] = (V      ) & 0xFF;
--  }
--  operator Type () const
--  {
--    return (v[0] << 24)
--         + (v[1] << 16)
--         + (v[2] <<  8)
--         + (v[3]      );
--  }
--  private: uint8_t v[4];
--};
--
- 
- /*
-  * Lazy loaders.
-  */
- 
- template <typename Data, unsigned int WheresData>
- struct hb_data_wrapper_t
- {
-@@ -811,17 +201,17 @@ struct hb_lazy_loader_t : hb_data_wrappe
-   static void do_destroy (Stored *p)
-   {
-     if (p && p != const_cast<Stored *> (Funcs::get_null ()))
-       Funcs::destroy (p);
-   }
- 
-   const Returned * operator -> () const { return get (); }
-   const Returned & operator * () const  { return *get (); }
--  explicit_operator bool () const
-+  explicit operator bool () const
-   { return get_stored () != Funcs::get_null (); }
-   template <typename C> operator const C * () const { return get (); }
- 
-   Stored * get_stored () const
-   {
-   retry:
-     Stored *p = this->instance.get ();
-     if (unlikely (!p))
-diff --git a/gfx/harfbuzz/src/hb-map.hh b/gfx/harfbuzz/src/hb-map.hh
---- a/gfx/harfbuzz/src/hb-map.hh
-+++ b/gfx/harfbuzz/src/hb-map.hh
-@@ -25,41 +25,49 @@
-  */
- 
- #ifndef HB_MAP_HH
- #define HB_MAP_HH
- 
- #include "hb.hh"
- 
- 
--template <typename T>
--inline uint32_t Hash (const T &v)
--{
--  /* Knuth's multiplicative method: */
--  return (uint32_t) v * 2654435761u;
--}
--
--
- /*
-- * hb_map_t
-+ * hb_hashmap_t
-  */
- 
--struct hb_map_t
-+template <typename K, typename V,
-+	  K kINVALID = hb_is_pointer (K) ? 0 : hb_is_signed (K) ? hb_int_min (K) : (K) -1,
-+	  V vINVALID = hb_is_pointer (V) ? 0 : hb_is_signed (V) ? hb_int_min (V) : (V) -1>
-+struct hb_hashmap_t
- {
--  HB_NO_COPY_ASSIGN (hb_map_t);
--  hb_map_t ()  { init (); }
--  ~hb_map_t () { fini (); }
-+  HB_DELETE_COPY_ASSIGN (hb_hashmap_t);
-+  hb_hashmap_t ()  { init (); }
-+  ~hb_hashmap_t () { fini (); }
- 
-+  static_assert (hb_is_integral (K) || hb_is_pointer (K), "");
-+  static_assert (hb_is_integral (V) || hb_is_pointer (V), "");
-+
-+  /* TODO If key type is a pointer, keep hash in item_t and use to:
-+   * 1. avoid rehashing when resizing table, and
-+   * 2. compare hash before comparing keys, for speed.
-+   */
-   struct item_t
-   {
--    hb_codepoint_t key;
--    hb_codepoint_t value;
-+    K key;
-+    V value;
-+
-+    void clear () { key = kINVALID; value = vINVALID; }
- 
--    bool is_unused () const    { return key == INVALID; }
--    bool is_tombstone () const { return key != INVALID && value == INVALID; }
-+    bool operator == (K o) { return hb_deref (key) == hb_deref (o); }
-+    bool operator == (const item_t &o) { return *this == o.key; }
-+    bool is_unused () const    { return key == kINVALID; }
-+    bool is_tombstone () const { return key != kINVALID && value == vINVALID; }
-+    bool is_real () const { return key != kINVALID && value != vINVALID; }
-+    hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
-   };
- 
-   hb_object_header_t header;
-   bool successful; /* Allocations successful */
-   unsigned int population; /* Not including tombstones. */
-   unsigned int occupancy; /* Including tombstones. */
-   unsigned int mask;
-   unsigned int prime;
-@@ -77,68 +85,78 @@ struct hb_map_t
-   {
-     hb_object_init (this);
-     init_shallow ();
-   }
-   void fini_shallow ()
-   {
-     free (items);
-     items = nullptr;
-+    population = occupancy = 0;
-   }
-   void fini ()
-   {
--    population = occupancy = 0;
-     hb_object_fini (this);
-     fini_shallow ();
-   }
- 
-+  void reset ()
-+  {
-+    if (unlikely (hb_object_is_immutable (this)))
-+      return;
-+    successful = true;
-+    clear ();
-+  }
-+
-   bool in_error () const { return !successful; }
- 
-   bool resize ()
-   {
-     if (unlikely (!successful)) return false;
- 
-     unsigned int power = hb_bit_storage (population * 2 + 8);
-     unsigned int new_size = 1u << power;
-     item_t *new_items = (item_t *) malloc ((size_t) new_size * sizeof (item_t));
-     if (unlikely (!new_items))
-     {
-       successful = false;
-       return false;
-     }
--    memset (new_items, 0xFF, (size_t) new_size * sizeof (item_t));
-+    + hb_iter (new_items, new_size)
-+    | hb_apply (&item_t::clear)
-+    ;
- 
-     unsigned int old_size = mask + 1;
-     item_t *old_items = items;
- 
-     /* Switch to new, empty, array. */
-     population = occupancy = 0;
-     mask = new_size - 1;
-     prime = prime_for (power);
-     items = new_items;
- 
-     /* Insert back old items. */
-     if (old_items)
-       for (unsigned int i = 0; i < old_size; i++)
--	if (old_items[i].key != INVALID && old_items[i].value != INVALID)
-+	if (old_items[i].is_real ())
- 	  set (old_items[i].key, old_items[i].value);
- 
-     free (old_items);
- 
-     return true;
-   }
- 
--  void set (hb_codepoint_t key, hb_codepoint_t value)
-+  void set (K key, V value)
-   {
-     if (unlikely (!successful)) return;
--    if (unlikely (key == INVALID)) return;
-+    if (unlikely (key == kINVALID)) return;
-     if ((occupancy + occupancy / 2) >= mask && !resize ()) return;
-     unsigned int i = bucket_for (key);
- 
--    if (value == INVALID && items[i].key != key)
-+    if (value == vINVALID && items[i].key != key)
-       return; /* Trying to delete non-existent key. */
- 
-     if (!items[i].is_unused ())
-     {
-       occupancy--;
-       if (items[i].is_tombstone ())
- 	population--;
-     }
-@@ -146,59 +164,98 @@ struct hb_map_t
-     items[i].key = key;
-     items[i].value = value;
- 
-     occupancy++;
-     if (!items[i].is_tombstone ())
-       population++;
- 
-   }
--  hb_codepoint_t get (hb_codepoint_t key) const
-+  V get (K key) const
-   {
--    if (unlikely (!items)) return INVALID;
-+    if (unlikely (!items)) return vINVALID;
-     unsigned int i = bucket_for (key);
--    return items[i].key == key ? items[i].value : INVALID;
-+    return items[i].is_real () && items[i] == key ? items[i].value : vINVALID;
-   }
- 
--  void del (hb_codepoint_t key) { set (key, INVALID); }
--
--  bool has (hb_codepoint_t key) const
--  { return get (key) != INVALID; }
-+  void del (K key) { set (key, vINVALID); }
- 
--  hb_codepoint_t operator [] (unsigned int key) const
--  { return get (key); }
--
--  static constexpr hb_codepoint_t INVALID = HB_MAP_VALUE_INVALID;
-+  /* Has interface. */
-+  static constexpr V SENTINEL = vINVALID;
-+  typedef V value_t;
-+  value_t operator [] (K k) const { return get (k); }
-+  bool has (K k, V *vp = nullptr) const
-+  {
-+    V v = (*this)[k];
-+    if (vp) *vp = v;
-+    return v != SENTINEL;
-+  }
-+  /* Projection. */
-+  V operator () (K k) const { return get (k); }
- 
-   void clear ()
-   {
--    if (items) memset (items, 0xFF, ((size_t) mask + 1) * sizeof (item_t));
-+    if (unlikely (hb_object_is_immutable (this)))
-+      return;
-+    if (items)
-+      + hb_iter (items, mask + 1)
-+      | hb_apply (&item_t::clear)
-+      ;
-+
-     population = occupancy = 0;
-   }
- 
-   bool is_empty () const { return population == 0; }
- 
-   unsigned int get_population () const { return population; }
- 
-+  /*
-+   * Iterator
-+   */
-+  auto iter () const HB_AUTO_RETURN
-+  (
-+    + hb_array (items, mask ? mask + 1 : 0)
-+    | hb_filter (&item_t::is_real)
-+    | hb_map (&item_t::get_pair)
-+  )
-+  auto keys () const HB_AUTO_RETURN
-+  (
-+    + hb_array (items, mask ? mask + 1 : 0)
-+    | hb_filter (&item_t::is_real)
-+    | hb_map (&item_t::key)
-+    | hb_map (hb_ridentity)
-+  )
-+  auto values () const HB_AUTO_RETURN
-+  (
-+    + hb_array (items, mask ? mask + 1 : 0)
-+    | hb_filter (&item_t::is_real)
-+    | hb_map (&item_t::value)
-+    | hb_map (hb_ridentity)
-+  )
-+
-+  /* Sink interface. */
-+  hb_hashmap_t<K, V, kINVALID, vINVALID>& operator << (const hb_pair_t<K, V>& v)
-+  { set (v.first, v.second); return *this; }
-+
-   protected:
- 
--  unsigned int bucket_for (hb_codepoint_t key) const
-+  unsigned int bucket_for (K key) const
-   {
--    unsigned int i = Hash (key) % prime;
-+    unsigned int i = hb_hash (key) % prime;
-     unsigned int step = 0;
--    unsigned int tombstone = INVALID;
-+    unsigned int tombstone = (unsigned) -1;
-     while (!items[i].is_unused ())
-     {
--      if (items[i].key == key)
--        return i;
--      if (tombstone == INVALID && items[i].is_tombstone ())
--        tombstone = i;
-+      if (items[i] == key)
-+	return i;
-+      if (tombstone == (unsigned) -1 && items[i].is_tombstone ())
-+	tombstone = i;
-       i = (i + ++step) & mask;
-     }
--    return tombstone == INVALID ? i : tombstone;
-+    return tombstone == (unsigned) -1 ? i : tombstone;
-   }
- 
-   static unsigned int prime_for (unsigned int shift)
-   {
-     /* Following comment and table copied from glib. */
-     /* Each table size has an associated prime modulo (the first prime
-      * lower than the table size) used to find the initial bucket. Probing
-      * then works modulo 2^n. The prime modulo is necessary to get a
-@@ -243,10 +300,19 @@ struct hb_map_t
- 
-     if (unlikely (shift >= ARRAY_LENGTH (prime_mod)))
-       return prime_mod[ARRAY_LENGTH (prime_mod) - 1];
- 
-     return prime_mod[shift];
-   }
- };
- 
-+/*
-+ * hb_map_t
-+ */
-+
-+struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
-+			       hb_codepoint_t,
-+			       HB_MAP_VALUE_INVALID,
-+			       HB_MAP_VALUE_INVALID> {};
-+
- 
- #endif /* HB_MAP_HH */
-diff --git a/gfx/harfbuzz/src/hb-meta.hh b/gfx/harfbuzz/src/hb-meta.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-meta.hh
-@@ -0,0 +1,400 @@
-+/*
-+ * Copyright © 2018  Google, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Google Author(s): Behdad Esfahbod
-+ */
-+
-+#ifndef HB_META_HH
-+#define HB_META_HH
-+
-+#include "hb.hh"
-+
-+
-+/*
-+ * C++ template meta-programming & fundamentals used with them.
-+ */
-+
-+/* Void!  For when we need a expression-type of void. */
-+struct hb_empty_t {};
-+
-+/* https://en.cppreference.com/w/cpp/types/void_t */
-+template<typename... Ts> struct _hb_void_t { typedef void type; };
-+template<typename... Ts> using hb_void_t = typename _hb_void_t<Ts...>::type;
-+
-+template<typename Head, typename... Ts> struct _hb_head_t { typedef Head type; };
-+template<typename... Ts> using hb_head_t = typename _hb_head_t<Ts...>::type;
-+
-+template <typename T, T v> struct hb_integral_constant { static constexpr T value = v; };
-+template <bool b> using hb_bool_constant = hb_integral_constant<bool, b>;
-+using hb_true_type = hb_bool_constant<true>;
-+using hb_false_type = hb_bool_constant<false>;
-+
-+
-+/* Basic type SFINAE. */
-+
-+template <bool B, typename T = void> struct hb_enable_if {};
-+template <typename T>                struct hb_enable_if<true, T> { typedef T type; };
-+#define hb_enable_if(Cond) typename hb_enable_if<(Cond)>::type* = nullptr
-+/* Concepts/Requires alias: */
-+#define hb_requires(Cond) hb_enable_if((Cond))
-+
-+template <typename T, typename T2> struct hb_is_same : hb_false_type {};
-+template <typename T>              struct hb_is_same<T, T> : hb_true_type {};
-+#define hb_is_same(T, T2) hb_is_same<T, T2>::value
-+
-+/* Function overloading SFINAE and priority. */
-+
-+#define HB_RETURN(Ret, E) -> hb_head_t<Ret, decltype ((E))> { return (E); }
-+#define HB_AUTO_RETURN(E) -> decltype ((E)) { return (E); }
-+#define HB_VOID_RETURN(E) -> hb_void_t<decltype ((E))> { (E); }
-+
-+template <unsigned Pri> struct hb_priority : hb_priority<Pri - 1> {};
-+template <>             struct hb_priority<0> {};
-+#define hb_prioritize hb_priority<16> ()
-+
-+#define HB_FUNCOBJ(x) static_const x HB_UNUSED
-+
-+
-+template <typename T> struct hb_type_identity_t { typedef T type; };
-+template <typename T> using hb_type_identity = typename hb_type_identity_t<T>::type;
-+
-+struct
-+{
-+  template <typename T>
-+  T* operator () (T& arg) const
-+  {
-+#pragma GCC diagnostic push
-+#pragma GCC diagnostic ignored "-Wcast-align"
-+    /* https://en.cppreference.com/w/cpp/memory/addressof */
-+    return reinterpret_cast<T*> (
-+	     &const_cast<char&> (
-+		reinterpret_cast<const volatile char&> (arg)));
-+#pragma GCC diagnostic pop
-+  }
-+}
-+HB_FUNCOBJ (hb_addressof);
-+
-+template <typename T> static inline T hb_declval ();
-+#define hb_declval(T) (hb_declval<T> ())
-+
-+template <typename T> struct hb_match_const		: hb_type_identity_t<T>, hb_bool_constant<false>{};
-+template <typename T> struct hb_match_const<const T>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
-+template <typename T> using hb_remove_const = typename hb_match_const<T>::type;
-+template <typename T> using hb_add_const = const T;
-+#define hb_is_const(T) hb_match_const<T>::value
-+template <typename T> struct hb_match_reference		: hb_type_identity_t<T>, hb_bool_constant<false>{};
-+template <typename T> struct hb_match_reference<T &>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
-+template <typename T> struct hb_match_reference<T &&>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
-+template <typename T> using hb_remove_reference = typename hb_match_reference<T>::type;
-+template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<1>) -> hb_type_identity<T&>;
-+template <typename T> auto _hb_try_add_lvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
-+template <typename T> using hb_add_lvalue_reference = decltype (_hb_try_add_lvalue_reference<T> (hb_prioritize));
-+template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<1>) -> hb_type_identity<T&&>;
-+template <typename T> auto _hb_try_add_rvalue_reference (hb_priority<0>) -> hb_type_identity<T>;
-+template <typename T> using hb_add_rvalue_reference = decltype (_hb_try_add_rvalue_reference<T> (hb_prioritize));
-+#define hb_is_reference(T) hb_match_reference<T>::value
-+template <typename T> struct hb_match_pointer		: hb_type_identity_t<T>, hb_bool_constant<false>{};
-+template <typename T> struct hb_match_pointer<T *>	: hb_type_identity_t<T>, hb_bool_constant<true>	{};
-+template <typename T> using hb_remove_pointer = typename hb_match_pointer<T>::type;
-+template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<hb_remove_reference<T>*>;
-+template <typename T> auto _hb_try_add_pointer (hb_priority<1>) -> hb_type_identity<T>;
-+template <typename T> using hb_add_pointer = decltype (_hb_try_add_pointer<T> (hb_prioritize));
-+#define hb_is_pointer(T) hb_match_pointer<T>::value
-+
-+
-+/* TODO Add feature-parity to std::decay. */
-+template <typename T> using hb_decay = hb_remove_const<hb_remove_reference<T>>;
-+
-+
-+template<bool B, class T, class F>
-+struct _hb_conditional { typedef T type; };
-+template<class T, class F>
-+struct _hb_conditional<false, T, F> { typedef F type; };
-+template<bool B, class T, class F>
-+using hb_conditional = typename _hb_conditional<B, T, F>::type;
-+
-+
-+template <typename From, typename To>
-+struct hb_is_convertible
-+{
-+  private:
-+  static constexpr bool   from_void = hb_is_same (void, hb_decay<From>);
-+  static constexpr bool     to_void = hb_is_same (void, hb_decay<To>  );
-+  static constexpr bool either_void = from_void || to_void;
-+  static constexpr bool   both_void = from_void && to_void;
-+
-+  static hb_true_type impl2 (hb_conditional<to_void, int, To>);
-+
-+  template <typename T>
-+  static auto impl (hb_priority<1>) -> decltype (impl2 (hb_declval (T)));
-+  template <typename T>
-+  static hb_false_type impl (hb_priority<0>);
-+  public:
-+  static constexpr bool value = both_void ||
-+		       (!either_void &&
-+			decltype (impl<hb_conditional<from_void, int, From>> (hb_prioritize))::value);
-+};
-+#define hb_is_convertible(From,To) hb_is_convertible<From, To>::value
-+
-+template <typename Base, typename Derived>
-+using hb_is_base_of = hb_is_convertible<hb_decay<Derived> *, hb_decay<Base> *>;
-+#define hb_is_base_of(Base,Derived) hb_is_base_of<Base, Derived>::value
-+
-+template <typename From, typename To>
-+using hb_is_cr_convertible = hb_bool_constant<
-+  hb_is_same (hb_decay<From>, hb_decay<To>) &&
-+  (!hb_is_const (From) || hb_is_const (To)) &&
-+  (!hb_is_reference (To) || hb_is_const (To) || hb_is_reference (To))
-+>;
-+#define hb_is_cr_convertible(From,To) hb_is_cr_convertible<From, To>::value
-+
-+/* std::move and std::forward */
-+
-+template <typename T>
-+static hb_remove_reference<T>&& hb_move (T&& t) { return (hb_remove_reference<T>&&) (t); }
-+
-+template <typename T>
-+static T&& hb_forward (hb_remove_reference<T>& t) { return (T&&) t; }
-+template <typename T>
-+static T&& hb_forward (hb_remove_reference<T>&& t) { return (T&&) t; }
-+
-+struct
-+{
-+  template <typename T> auto
-+  operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
-+
-+  template <typename T> auto
-+  operator () (T *v) const HB_AUTO_RETURN (*v)
-+}
-+HB_FUNCOBJ (hb_deref);
-+
-+struct
-+{
-+  template <typename T> auto
-+  operator () (T&& v) const HB_AUTO_RETURN (hb_forward<T> (v))
-+
-+  template <typename T> auto
-+  operator () (T& v) const HB_AUTO_RETURN (hb_addressof (v))
-+}
-+HB_FUNCOBJ (hb_ref);
-+
-+template <typename T>
-+struct hb_reference_wrapper
-+{
-+  hb_reference_wrapper (T v) : v (v) {}
-+  bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
-+  bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
-+  operator T () const { return v; }
-+  T get () const { return v; }
-+  T v;
-+};
-+template <typename T>
-+struct hb_reference_wrapper<T&>
-+{
-+  hb_reference_wrapper (T& v) : v (hb_addressof (v)) {}
-+  bool operator == (const hb_reference_wrapper& o) const { return v == o.v; }
-+  bool operator != (const hb_reference_wrapper& o) const { return v != o.v; }
-+  operator T& () const { return *v; }
-+  T& get () const { return *v; }
-+  T* v;
-+};
-+
-+
-+template <typename T>
-+using hb_is_integral = hb_bool_constant<
-+  hb_is_same (hb_decay<T>, char) ||
-+  hb_is_same (hb_decay<T>, signed char) ||
-+  hb_is_same (hb_decay<T>, unsigned char) ||
-+  hb_is_same (hb_decay<T>, signed int) ||
-+  hb_is_same (hb_decay<T>, unsigned int) ||
-+  hb_is_same (hb_decay<T>, signed short) ||
-+  hb_is_same (hb_decay<T>, unsigned short) ||
-+  hb_is_same (hb_decay<T>, signed long) ||
-+  hb_is_same (hb_decay<T>, unsigned long) ||
-+  hb_is_same (hb_decay<T>, signed long long) ||
-+  hb_is_same (hb_decay<T>, unsigned long long) ||
-+  false
-+>;
-+#define hb_is_integral(T) hb_is_integral<T>::value
-+template <typename T>
-+using hb_is_floating_point = hb_bool_constant<
-+  hb_is_same (hb_decay<T>, float) ||
-+  hb_is_same (hb_decay<T>, double) ||
-+  hb_is_same (hb_decay<T>, long double) ||
-+  false
-+>;
-+#define hb_is_floating_point(T) hb_is_floating_point<T>::value
-+template <typename T>
-+using hb_is_arithmetic = hb_bool_constant<
-+  hb_is_integral (T) ||
-+  hb_is_floating_point (T) ||
-+  false
-+>;
-+#define hb_is_arithmetic(T) hb_is_arithmetic<T>::value
-+
-+
-+template <typename T>
-+using hb_is_signed = hb_conditional<hb_is_arithmetic (T),
-+				    hb_bool_constant<(T) -1 < (T) 0>,
-+				    hb_false_type>;
-+#define hb_is_signed(T) hb_is_signed<T>::value
-+template <typename T>
-+using hb_is_unsigned = hb_conditional<hb_is_arithmetic (T),
-+				      hb_bool_constant<(T) 0 < (T) -1>,
-+				      hb_false_type>;
-+#define hb_is_unsigned(T) hb_is_unsigned<T>::value
-+
-+template <typename T> struct hb_int_min;
-+template <> struct hb_int_min<char>			: hb_integral_constant<char,			CHAR_MIN>	{};
-+template <> struct hb_int_min<signed char>		: hb_integral_constant<signed char,		SCHAR_MIN>	{};
-+template <> struct hb_int_min<unsigned char>		: hb_integral_constant<unsigned char,		0>		{};
-+template <> struct hb_int_min<signed short>		: hb_integral_constant<signed short,		SHRT_MIN>	{};
-+template <> struct hb_int_min<unsigned short>		: hb_integral_constant<unsigned short,		0>		{};
-+template <> struct hb_int_min<signed int>		: hb_integral_constant<signed int,		INT_MIN>	{};
-+template <> struct hb_int_min<unsigned int>		: hb_integral_constant<unsigned int,		0>		{};
-+template <> struct hb_int_min<signed long>		: hb_integral_constant<signed long,		LONG_MIN>	{};
-+template <> struct hb_int_min<unsigned long>		: hb_integral_constant<unsigned long,		0>		{};
-+template <> struct hb_int_min<signed long long>		: hb_integral_constant<signed long long,	LLONG_MIN>	{};
-+template <> struct hb_int_min<unsigned long long>	: hb_integral_constant<unsigned long long,	0>		{};
-+#define hb_int_min(T) hb_int_min<T>::value
-+template <typename T> struct hb_int_max;
-+template <> struct hb_int_max<char>			: hb_integral_constant<char,			CHAR_MAX>	{};
-+template <> struct hb_int_max<signed char>		: hb_integral_constant<signed char,		SCHAR_MAX>	{};
-+template <> struct hb_int_max<unsigned char>		: hb_integral_constant<unsigned char,		UCHAR_MAX>	{};
-+template <> struct hb_int_max<signed short>		: hb_integral_constant<signed short,		SHRT_MAX>	{};
-+template <> struct hb_int_max<unsigned short>		: hb_integral_constant<unsigned short,		USHRT_MAX>	{};
-+template <> struct hb_int_max<signed int>		: hb_integral_constant<signed int,		INT_MAX>	{};
-+template <> struct hb_int_max<unsigned int>		: hb_integral_constant<unsigned int,		UINT_MAX>	{};
-+template <> struct hb_int_max<signed long>		: hb_integral_constant<signed long,		LONG_MAX>	{};
-+template <> struct hb_int_max<unsigned long>		: hb_integral_constant<unsigned long,		ULONG_MAX>	{};
-+template <> struct hb_int_max<signed long long>		: hb_integral_constant<signed long long,	LLONG_MAX>	{};
-+template <> struct hb_int_max<unsigned long long>	: hb_integral_constant<unsigned long long,	ULLONG_MAX>	{};
-+#define hb_int_max(T) hb_int_max<T>::value
-+
-+
-+
-+template <typename T, typename>
-+struct _hb_is_destructible : hb_false_type {};
-+template <typename T>
-+struct _hb_is_destructible<T, hb_void_t<decltype (hb_declval (T).~T ())>> : hb_true_type {};
-+template <typename T>
-+using hb_is_destructible = _hb_is_destructible<T, void>;
-+#define hb_is_destructible(T) hb_is_destructible<T>::value
-+
-+template <typename T, typename, typename ...Ts>
-+struct _hb_is_constructible : hb_false_type {};
-+template <typename T, typename ...Ts>
-+struct _hb_is_constructible<T, hb_void_t<decltype (T (hb_declval (Ts)...))>, Ts...> : hb_true_type {};
-+template <typename T, typename ...Ts>
-+using hb_is_constructible = _hb_is_constructible<T, void, Ts...>;
-+#define hb_is_constructible(...) hb_is_constructible<__VA_ARGS__>::value
-+
-+template <typename T>
-+using hb_is_default_constructible = hb_is_constructible<T>;
-+#define hb_is_default_constructible(T) hb_is_default_constructible<T>::value
-+
-+template <typename T>
-+using hb_is_copy_constructible = hb_is_constructible<T, hb_add_lvalue_reference<hb_add_const<T>>>;
-+#define hb_is_copy_constructible(T) hb_is_copy_constructible<T>::value
-+
-+template <typename T>
-+using hb_is_move_constructible = hb_is_constructible<T, hb_add_rvalue_reference<hb_add_const<T>>>;
-+#define hb_is_move_constructible(T) hb_is_move_constructible<T>::value
-+
-+template <typename T, typename U, typename>
-+struct _hb_is_assignable : hb_false_type {};
-+template <typename T, typename U>
-+struct _hb_is_assignable<T, U, hb_void_t<decltype (hb_declval (T) = hb_declval (U))>> : hb_true_type {};
-+template <typename T, typename U>
-+using hb_is_assignable = _hb_is_assignable<T, U, void>;
-+#define hb_is_assignable(T,U) hb_is_assignable<T, U>::value
-+
-+template <typename T>
-+using hb_is_copy_assignable = hb_is_assignable<hb_add_lvalue_reference<T>,
-+					       hb_add_lvalue_reference<hb_add_const<T>>>;
-+#define hb_is_copy_assignable(T) hb_is_copy_assignable<T>::value
-+
-+template <typename T>
-+using hb_is_move_assignable = hb_is_assignable<hb_add_lvalue_reference<T>,
-+					       hb_add_rvalue_reference<T>>;
-+#define hb_is_move_assignable(T) hb_is_move_assignable<T>::value
-+
-+/* Trivial versions. */
-+
-+template <typename T> union hb_trivial { T value; };
-+
-+/* Don't know how to do the following. */
-+template <typename T>
-+using hb_is_trivially_destructible= hb_is_destructible<hb_trivial<T>>;
-+#define hb_is_trivially_destructible(T) hb_is_trivially_destructible<T>::value
-+
-+/* Don't know how to do the following. */
-+//template <typename T, typename ...Ts>
-+//using hb_is_trivially_constructible= hb_is_constructible<hb_trivial<T>, hb_trivial<Ts>...>;
-+//#define hb_is_trivially_constructible(...) hb_is_trivially_constructible<__VA_ARGS__>::value
-+
-+template <typename T>
-+using hb_is_trivially_default_constructible= hb_is_default_constructible<hb_trivial<T>>;
-+#define hb_is_trivially_default_constructible(T) hb_is_trivially_default_constructible<T>::value
-+
-+template <typename T>
-+using hb_is_trivially_copy_constructible= hb_is_copy_constructible<hb_trivial<T>>;
-+#define hb_is_trivially_copy_constructible(T) hb_is_trivially_copy_constructible<T>::value
-+
-+template <typename T>
-+using hb_is_trivially_move_constructible= hb_is_move_constructible<hb_trivial<T>>;
-+#define hb_is_trivially_move_constructible(T) hb_is_trivially_move_constructible<T>::value
-+
-+/* Don't know how to do the following. */
-+//template <typename T, typename U>
-+//using hb_is_trivially_assignable= hb_is_assignable<hb_trivial<T>, hb_trivial<U>>;
-+//#define hb_is_trivially_assignable(T,U) hb_is_trivially_assignable<T, U>::value
-+
-+template <typename T>
-+using hb_is_trivially_copy_assignable= hb_is_copy_assignable<hb_trivial<T>>;
-+#define hb_is_trivially_copy_assignable(T) hb_is_trivially_copy_assignable<T>::value
-+
-+template <typename T>
-+using hb_is_trivially_move_assignable= hb_is_move_assignable<hb_trivial<T>>;
-+#define hb_is_trivially_move_assignable(T) hb_is_trivially_move_assignable<T>::value
-+
-+template <typename T>
-+using hb_is_trivially_copyable= hb_bool_constant<
-+  hb_is_trivially_destructible (T) &&
-+  (!hb_is_move_assignable (T) || hb_is_trivially_move_assignable (T)) &&
-+  (!hb_is_move_constructible (T) || hb_is_trivially_move_constructible (T)) &&
-+  (!hb_is_copy_assignable (T) || hb_is_trivially_copy_assignable (T)) &&
-+  (!hb_is_copy_constructible (T) || hb_is_trivially_copy_constructible (T)) &&
-+  true
-+>;
-+#define hb_is_trivially_copyable(T) hb_is_trivially_copyable<T>::value
-+
-+template <typename T>
-+using hb_is_trivial= hb_bool_constant<
-+  hb_is_trivially_copyable (T) &&
-+  hb_is_trivially_default_constructible (T)
-+>;
-+#define hb_is_trivial(T) hb_is_trivial<T>::value
-+
-+
-+#endif /* HB_META_HH */
-diff --git a/gfx/harfbuzz/src/hb-mutex.hh b/gfx/harfbuzz/src/hb-mutex.hh
---- a/gfx/harfbuzz/src/hb-mutex.hh
-+++ b/gfx/harfbuzz/src/hb-mutex.hh
-@@ -43,42 +43,42 @@
-  && defined(hb_mutex_impl_init) \
-  && defined(hb_mutex_impl_lock) \
-  && defined(hb_mutex_impl_unlock) \
-  && defined(hb_mutex_impl_finish)
- 
- /* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */
- 
- 
-+#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
-+
-+#include <pthread.h>
-+typedef pthread_mutex_t hb_mutex_impl_t;
-+#define HB_MUTEX_IMPL_INIT	PTHREAD_MUTEX_INITIALIZER
-+#define hb_mutex_impl_init(M)	pthread_mutex_init (M, nullptr)
-+#define hb_mutex_impl_lock(M)	pthread_mutex_lock (M)
-+#define hb_mutex_impl_unlock(M)	pthread_mutex_unlock (M)
-+#define hb_mutex_impl_finish(M)	pthread_mutex_destroy (M)
-+
-+
- #elif !defined(HB_NO_MT) && defined(_WIN32)
- 
- #include <windows.h>
- typedef CRITICAL_SECTION hb_mutex_impl_t;
- #define HB_MUTEX_IMPL_INIT	{0}
- #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
- #define hb_mutex_impl_init(M)	InitializeCriticalSectionEx (M, 0, 0)
- #else
- #define hb_mutex_impl_init(M)	InitializeCriticalSection (M)
- #endif
- #define hb_mutex_impl_lock(M)	EnterCriticalSection (M)
- #define hb_mutex_impl_unlock(M)	LeaveCriticalSection (M)
- #define hb_mutex_impl_finish(M)	DeleteCriticalSection (M)
- 
- 
--#elif !defined(HB_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
--
--#include <pthread.h>
--typedef pthread_mutex_t hb_mutex_impl_t;
--#define HB_MUTEX_IMPL_INIT	PTHREAD_MUTEX_INITIALIZER
--#define hb_mutex_impl_init(M)	pthread_mutex_init (M, nullptr)
--#define hb_mutex_impl_lock(M)	pthread_mutex_lock (M)
--#define hb_mutex_impl_unlock(M)	pthread_mutex_unlock (M)
--#define hb_mutex_impl_finish(M)	pthread_mutex_destroy (M)
--
--
- #elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
- 
- #if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
- # include <sched.h>
- # define HB_SCHED_YIELD() sched_yield ()
- #else
- # define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
- #endif
-@@ -122,18 +122,16 @@ typedef int hb_mutex_impl_t;
- 
- #endif
- 
- 
- #define HB_MUTEX_INIT		{HB_MUTEX_IMPL_INIT}
- 
- struct hb_mutex_t
- {
--  /* TODO Add tracing. */
--
-   hb_mutex_impl_t m;
- 
-   void init   () { hb_mutex_impl_init   (&m); }
-   void lock   () { hb_mutex_impl_lock   (&m); }
-   void unlock () { hb_mutex_impl_unlock (&m); }
-   void fini ()   { hb_mutex_impl_finish (&m); }
- };
- 
-diff --git a/gfx/harfbuzz/src/hb-null.hh b/gfx/harfbuzz/src/hb-null.hh
---- a/gfx/harfbuzz/src/hb-null.hh
-+++ b/gfx/harfbuzz/src/hb-null.hh
-@@ -23,84 +23,57 @@
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #ifndef HB_NULL_HH
- #define HB_NULL_HH
- 
- #include "hb.hh"
-+#include "hb-meta.hh"
- 
- 
- /*
-  * Static pools
-  */
- 
- /* Global nul-content Null pool.  Enlarge as necessary. */
- 
--#define HB_NULL_POOL_SIZE 9880
-+#define HB_NULL_POOL_SIZE 384
- 
- /* Use SFINAE to sniff whether T has min_size; in which case return T::null_size,
-  * otherwise return sizeof(T). */
- 
- /* The hard way...
-  * https://stackoverflow.com/questions/7776448/sfinae-tried-with-bool-gives-compiler-error-template-argument-tvalue-invol
-  */
- 
--template<bool> struct _hb_bool_type {};
--
--template <typename T, typename B>
--struct _hb_null_size
--{ enum { value = sizeof (T) }; };
-+template <typename T, typename>
-+struct _hb_null_size : hb_integral_constant<unsigned, sizeof (T)> {};
- template <typename T>
--struct _hb_null_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
--{ enum { value = T::null_size }; };
-+struct _hb_null_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::null_size> {};
- 
- template <typename T>
--struct hb_null_size
--{ enum { value = _hb_null_size<T, _hb_bool_type<true> >::value }; };
-+using hb_null_size = _hb_null_size<T, void>;
- #define hb_null_size(T) hb_null_size<T>::value
- 
- /* These doesn't belong here, but since is copy/paste from above, put it here. */
- 
- /* hb_static_size (T)
-  * Returns T::static_size if T::min_size is defined, or sizeof (T) otherwise. */
- 
--template <typename T, typename B>
--struct _hb_static_size
--{ enum { value = sizeof (T) }; };
-+template <typename T, typename>
-+struct _hb_static_size : hb_integral_constant<unsigned, sizeof (T)> {};
- template <typename T>
--struct _hb_static_size<T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
--{ enum { value = T::static_size }; };
--
-+struct _hb_static_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::static_size> {};
- template <typename T>
--struct hb_static_size
--{ enum { value = _hb_static_size<T, _hb_bool_type<true> >::value }; };
-+using hb_static_size = _hb_static_size<T, void>;
- #define hb_static_size(T) hb_static_size<T>::value
- 
- 
--/* hb_assign (obj, value)
-- * Calls obj.set (value) if obj.min_size is defined and value has different type
-- * from obj, or obj = v otherwise. */
--
--template <typename T, typename V, typename B>
--struct _hb_assign
--{ static inline void value (T &o, const V v) { o = v; } };
--template <typename T, typename V>
--struct _hb_assign<T, V, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
--{ static inline void value (T &o, const V v) { o.set (v); } };
--template <typename T>
--struct _hb_assign<T, T, _hb_bool_type<(bool) (1 + (unsigned int) T::min_size)> >
--{ static inline void value (T &o, const T v) { o = v; } };
--
--template <typename T, typename V>
--static inline void hb_assign (T &o, const V v)
--{ _hb_assign<T, V, _hb_bool_type<true> >::value (o, v); }
--
--
- /*
-  * Null()
-  */
- 
- extern HB_INTERNAL
- hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
- 
- /* Generic nul-content Null objects. */
-@@ -110,17 +83,17 @@ struct Null {
-   {
-     static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-     return *reinterpret_cast<Type const *> (_hb_NullPool);
-   }
- };
- template <typename QType>
- struct NullHelper
- {
--  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
-+  typedef hb_remove_const<hb_remove_reference<QType>> Type;
-   static const Type & get_null () { return Null<Type>::get_null (); }
- };
- #define Null(Type) NullHelper<Type>::get_null ()
- 
- /* Specializations for arbitrary-content Null objects expressed in bytes. */
- #define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
- 	} /* Close namespace. */ \
- 	extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
-@@ -163,17 +136,17 @@ static inline Type& Crap () {
-   static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-   Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
-   memcpy (obj, &Null(Type), sizeof (*obj));
-   return *obj;
- }
- template <typename QType>
- struct CrapHelper
- {
--  typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
-+  typedef hb_remove_const<hb_remove_reference<QType>> Type;
-   static Type & get_crap () { return Crap<Type> (); }
- };
- #define Crap(Type) CrapHelper<Type>::get_crap ()
- 
- template <typename Type>
- struct CrapOrNullHelper {
-   static Type & get () { return Crap(Type); }
- };
-@@ -186,17 +159,17 @@ struct CrapOrNullHelper<const Type> {
- 
- /*
-  * hb_nonnull_ptr_t
-  */
- 
- template <typename P>
- struct hb_nonnull_ptr_t
- {
--  typedef typename hb_remove_pointer (P) T;
-+  typedef hb_remove_pointer<P> T;
- 
-   hb_nonnull_ptr_t (T *v_ = nullptr) : v (v_) {}
-   T * operator = (T *v_)   { return v = v_; }
-   T * operator -> () const { return get (); }
-   T & operator * () const  { return *get (); }
-   T ** operator & () const { return &v; }
-   /* Only auto-cast to const types. */
-   template <typename C> operator const C * () const { return get (); }
-diff --git a/gfx/harfbuzz/src/hb-open-file.hh b/gfx/harfbuzz/src/hb-open-file.hh
---- a/gfx/harfbuzz/src/hb-open-file.hh
-+++ b/gfx/harfbuzz/src/hb-open-file.hh
-@@ -51,17 +51,17 @@ struct OpenTypeFontFile;
- struct OffsetTable;
- struct TTCHeader;
- 
- 
- typedef struct TableRecord
- {
-   int cmp (Tag t) const { return -t.cmp (tag); }
- 
--  static int cmp (const void *pa, const void *pb)
-+  HB_INTERNAL static int cmp (const void *pa, const void *pb)
-   {
-     const TableRecord *a = (const TableRecord *) pa;
-     const TableRecord *b = (const TableRecord *) pb;
-     return b->cmp (a->tag);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-@@ -81,37 +81,37 @@ typedef struct TableRecord
- typedef struct OffsetTable
- {
-   friend struct OpenTypeFontFile;
- 
-   unsigned int get_table_count () const { return tables.len; }
-   const TableRecord& get_table (unsigned int i) const
-   { return tables[i]; }
-   unsigned int get_table_tags (unsigned int  start_offset,
--				      unsigned int *table_count, /* IN/OUT */
--				      hb_tag_t     *table_tags /* OUT */) const
-+			       unsigned int *table_count, /* IN/OUT */
-+			       hb_tag_t     *table_tags /* OUT */) const
-   {
-     if (table_count)
-     {
-       if (start_offset >= tables.len)
-         *table_count = 0;
-       else
--        *table_count = MIN<unsigned int> (*table_count, tables.len - start_offset);
-+        *table_count = hb_min (*table_count, tables.len - start_offset);
- 
-       const TableRecord *sub_tables = tables.arrayZ + start_offset;
-       unsigned int count = *table_count;
-       for (unsigned int i = 0; i < count; i++)
- 	table_tags[i] = sub_tables[i].tag;
-     }
-     return tables.len;
-   }
-   bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
-   {
-     Tag t;
--    t.set (tag);
-+    t = tag;
-     return tables.bfind (t, table_index, HB_BFIND_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
-   }
-   const TableRecord& get_table_by_tag (hb_tag_t tag) const
-   {
-     unsigned int table_index;
-     find_table_index (tag, &table_index);
-     return get_table (table_index);
-   }
-@@ -122,31 +122,31 @@ typedef struct OffsetTable
-   bool serialize (hb_serialize_context_t *c,
- 		  hb_tag_t sfnt_tag,
- 		  hb_array_t<item_t> items)
-   {
-     TRACE_SERIALIZE (this);
-     /* Alloc 12 for the OTHeader. */
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     /* Write sfntVersion (bytes 0..3). */
--    sfnt_version.set (sfnt_tag);
-+    sfnt_version = sfnt_tag;
-     /* Take space for numTables, searchRange, entrySelector, RangeShift
-      * and the TableRecords themselves.  */
-     if (unlikely (!tables.serialize (c, items.length))) return_trace (false);
- 
-     const char *dir_end = (const char *) c->head;
-     HBUINT32 *checksum_adjustment = nullptr;
- 
-     /* Write OffsetTables, alloc for and write actual table blobs. */
-     for (unsigned int i = 0; i < tables.len; i++)
-     {
-       TableRecord &rec = tables.arrayZ[i];
-       hb_blob_t *blob = items[i].blob;
--      rec.tag.set (items[i].tag);
--      rec.length.set (hb_blob_get_length (blob));
-+      rec.tag = items[i].tag;
-+      rec.length = hb_blob_get_length (blob);
-       rec.offset.serialize (c, this);
- 
-       /* Allocate room for the table and copy it. */
-       char *start = (char *) c->allocate_size<void> (rec.length);
-       if (unlikely (!start)) {return false;}
- 
-       memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
- 
-@@ -154,17 +154,17 @@ typedef struct OffsetTable
-       c->align (4);
-       const char *end = (const char *) c->head;
- 
-       if (items[i].tag == HB_OT_TAG_head &&
- 	  (unsigned) (end - start) >= head::static_size)
-       {
- 	head *h = (head *) start;
- 	checksum_adjustment = &h->checkSumAdjustment;
--	checksum_adjustment->set (0);
-+	*checksum_adjustment = 0;
-       }
- 
-       rec.checkSum.set_for_data (start, end - start);
-     }
- 
-     tables.qsort ();
- 
-     if (checksum_adjustment)
-@@ -172,20 +172,20 @@ typedef struct OffsetTable
-       CheckSum checksum;
- 
-       /* The following line is a slower version of the following block. */
-       //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
-       checksum.set_for_data (this, dir_end - (const char *) this);
-       for (unsigned int i = 0; i < items.length; i++)
-       {
- 	TableRecord &rec = tables.arrayZ[i];
--	checksum.set (checksum + rec.checkSum);
-+	checksum = checksum + rec.checkSum;
-       }
- 
--      checksum_adjustment->set (0xB1B0AFBAu - checksum);
-+      *checksum_adjustment = 0xB1B0AFBAu - checksum;
-     }
- 
-     return_trace (true);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-@@ -217,17 +217,17 @@ struct TTCHeaderVersion1
-     TRACE_SANITIZE (this);
-     return_trace (table.sanitize (c, this));
-   }
- 
-   protected:
-   Tag		ttcTag;		/* TrueType Collection ID string: 'ttcf' */
-   FixedVersion<>version;	/* Version of the TTC Header (1.0),
- 				 * 0x00010000u */
--  LArrayOf<LOffsetTo<OffsetTable> >
-+  LArrayOf<LOffsetTo<OffsetTable>>
- 		table;		/* Array of offsets to the OffsetTable for each font
- 				 * from the beginning of the file */
-   public:
-   DEFINE_SIZE_ARRAY (12, table);
- };
- 
- struct TTCHeader
- {
-@@ -329,17 +329,17 @@ struct ResourceTypeRecord
- 		  resourcesZ.sanitize (c, type_base,
- 				       get_resource_count (),
- 				       data_base));
-   }
- 
-   protected:
-   Tag		tag;		/* Resource type. */
-   HBUINT16	resCountM1;	/* Number of resources minus 1. */
--  NNOffsetTo<UnsizedArrayOf<ResourceRecord> >
-+  NNOffsetTo<UnsizedArrayOf<ResourceRecord>>
- 		resourcesZ;	/* Offset from beginning of resource type list
- 				 * to reference item list for this type. */
-   public:
-   DEFINE_SIZE_STATIC (8);
- };
- 
- struct ResourceMap
- {
-@@ -385,17 +385,17 @@ struct ResourceMap
-   const ResourceTypeRecord& get_type_record (unsigned int i) const
-   { return (this+typeList)[i]; }
- 
-   protected:
-   HBUINT8	reserved0[16];	/* Reserved for copy of resource header */
-   HBUINT32	reserved1;	/* Reserved for handle to next resource map */
-   HBUINT16	resreved2;	/* Reserved for file reference number */
-   HBUINT16	attrs;		/* Resource fork attribute */
--  NNOffsetTo<ArrayOfM1<ResourceTypeRecord> >
-+  NNOffsetTo<ArrayOfM1<ResourceTypeRecord>>
- 		typeList;	/* Offset from beginning of map to
- 				 * resource type list */
-   Offset16	nameList;	/* Offset from beginning of map to
- 				 * resource name list */
-   public:
-   DEFINE_SIZE_STATIC (28);
- };
- 
-@@ -417,17 +417,17 @@ struct ResourceForkHeader
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  data.sanitize (c, this, dataLen) &&
- 		  map.sanitize (c, this, &(this+data)));
-   }
- 
-   protected:
--  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
-+  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
- 		data;		/* Offset from beginning of resource fork
- 				 * to resource data */
-   LNNOffsetTo<ResourceMap >
- 		map;		/* Offset from beginning of resource fork
- 				 * to resource map */
-   HBUINT32	dataLen;	/* Length of resource data */
-   HBUINT32	mapLen;		/* Length of resource map */
-   public:
-diff --git a/gfx/harfbuzz/src/hb-open-type.hh b/gfx/harfbuzz/src/hb-open-type.hh
---- a/gfx/harfbuzz/src/hb-open-type.hh
-+++ b/gfx/harfbuzz/src/hb-open-type.hh
-@@ -47,32 +47,29 @@ namespace OT {
- 
- /* "The following data types are used in the OpenType font file.
-  *  All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
- 
- /*
-  * Int types
-  */
- 
--template <bool is_signed> struct hb_signedness_int;
--template <> struct hb_signedness_int<false> { typedef unsigned int value; };
--template <> struct hb_signedness_int<true>  { typedef   signed int value; };
--
- /* Integer types in big-endian order and no alignment requirement */
- template <typename Type, unsigned int Size>
- struct IntType
- {
-   typedef Type type;
--  typedef typename hb_signedness_int<hb_is_signed<Type>::value>::value wide_type;
-+  typedef hb_conditional<hb_is_signed (Type), signed, unsigned> wide_type;
- 
--  void set (wide_type i) { v.set (i); }
-+  IntType<Type, Size>& operator = (wide_type i) { v = i; return *this; }
-   operator wide_type () const { return v; }
-   bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
-   bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
--  static int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
-+  HB_INTERNAL static int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b)
-+  { return b->cmp (*a); }
-   template <typename Type2>
-   int cmp (Type2 a) const
-   {
-     Type b = v;
-     if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
-       return (int) a - (int) b;
-     else
-       return a < b ? -1 : a == b ? 0 : +1;
-@@ -105,29 +102,31 @@ typedef HBINT16 FWORD;
- typedef HBINT32 FWORD32;
- 
- /* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
- typedef HBUINT16 UFWORD;
- 
- /* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
- struct F2DOT14 : HBINT16
- {
-+  F2DOT14& operator = (uint16_t i ) { HBINT16::operator= (i); return *this; }
-   // 16384 means 1<<14
-   float to_float () const  { return ((int32_t) v) / 16384.f; }
--  void set_float (float f) { v.set (round (f * 16384.f)); }
-+  void set_float (float f) { v = roundf (f * 16384.f); }
-   public:
-   DEFINE_SIZE_STATIC (2);
- };
- 
- /* 32-bit signed fixed-point number (16.16). */
- struct Fixed : HBINT32
- {
-+  Fixed& operator = (uint32_t i) { HBINT32::operator= (i); return *this; }
-   // 65536 means 1<<16
-   float to_float () const  { return ((int32_t) v) / 65536.f; }
--  void set_float (float f) { v.set (round (f * 65536.f)); }
-+  void set_float (float f) { v = roundf (f * 65536.f); }
-   public:
-   DEFINE_SIZE_STATIC (4);
- };
- 
- /* Date represented in number of seconds since 12:00 midnight, January 1,
-  * 1904. The value is represented as a signed 64-bit integer. */
- struct LONGDATETIME
- {
-@@ -142,75 +141,84 @@ struct LONGDATETIME
-   public:
-   DEFINE_SIZE_STATIC (8);
- };
- 
- /* Array of four uint8s (length = 32 bits) used to identify a script, language
-  * system, feature, or baseline */
- struct Tag : HBUINT32
- {
-+  Tag& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
-   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
-   operator const char* () const { return reinterpret_cast<const char *> (&this->v); }
-   operator char* ()             { return reinterpret_cast<char *> (&this->v); }
-   public:
-   DEFINE_SIZE_STATIC (4);
- };
- 
- /* Glyph index number, same as uint16 (length = 16 bits) */
--typedef HBUINT16 GlyphID;
-+struct GlyphID : HBUINT16
-+{
-+  GlyphID& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
-+};
- 
- /* Script/language-system/feature index */
- struct Index : HBUINT16 {
-   static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFu;
-+  Index& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
- };
- DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
- 
- typedef Index NameID;
- 
- /* Offset, Null offset = 0 */
- template <typename Type, bool has_null=true>
- struct Offset : Type
- {
-+  Offset& operator = (typename Type::type i) { Type::operator= (i); return *this; }
-+
-   typedef Type type;
- 
-   bool is_null () const { return has_null && 0 == *this; }
- 
-   void *serialize (hb_serialize_context_t *c, const void *base)
-   {
-     void *t = c->start_embed<void> ();
--    this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
-+    c->check_assign (*this, (unsigned) ((char *) t - (char *) base));
-     return t;
-   }
- 
-   public:
-   DEFINE_SIZE_STATIC (sizeof (Type));
- };
- 
- typedef Offset<HBUINT16> Offset16;
- typedef Offset<HBUINT32> Offset32;
- 
- 
- /* CheckSum */
- struct CheckSum : HBUINT32
- {
-+  CheckSum& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
-+
-   /* This is reference implementation from the spec. */
-   static uint32_t CalcTableChecksum (const HBUINT32 *Table, uint32_t Length)
-   {
-     uint32_t Sum = 0L;
-     assert (0 == (Length & 3));
-     const HBUINT32 *EndPtr = Table + Length / HBUINT32::static_size;
- 
-     while (Table < EndPtr)
-       Sum += *Table++;
-     return Sum;
-   }
- 
-   /* Note: data should be 4byte aligned and have 4byte padding at the end. */
-   void set_for_data (const void *data, unsigned int length)
--  { set (CalcTableChecksum ((const HBUINT32 *) data, length)); }
-+  { *this = CalcTableChecksum ((const HBUINT32 *) data, length); }
- 
-   public:
-   DEFINE_SIZE_STATIC (4);
- };
- 
- 
- /*
-  * Version Numbers
-@@ -250,120 +258,143 @@ struct _hb_has_null<Type, true>
- {
-   static const Type *get_null () { return &Null(Type); }
-   static Type *get_crap ()       { return &Crap(Type); }
- };
- 
- template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
- struct OffsetTo : Offset<OffsetType, has_null>
- {
-+  HB_DELETE_COPY_ASSIGN (OffsetTo);
-+  OffsetTo () = default;
-+
-+  OffsetTo& operator = (typename OffsetType::type i) { OffsetType::operator= (i); return *this; }
-+
-   const Type& operator () (const void *base) const
-   {
-     if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_null ();
-     return StructAtOffset<const Type> (base, *this);
-   }
-   Type& operator () (void *base) const
-   {
-     if (unlikely (this->is_null ())) return *_hb_has_null<Type, has_null>::get_crap ();
-     return StructAtOffset<Type> (base, *this);
-   }
- 
-+  template <typename Base,
-+	    hb_enable_if (hb_is_convertible (const Base, const void *))>
-+  friend const Type& operator + (const Base &base, const OffsetTo &offset) { return offset ((const void *) base); }
-+  template <typename Base,
-+	    hb_enable_if (hb_is_convertible (const Base, const void *))>
-+  friend const Type& operator + (const OffsetTo &offset, const Base &base) { return offset ((const void *) base); }
-+  template <typename Base,
-+	    hb_enable_if (hb_is_convertible (Base, void *))>
-+  friend Type& operator + (Base &&base, OffsetTo &offset) { return offset ((void *) base); }
-+  template <typename Base,
-+	    hb_enable_if (hb_is_convertible (Base, void *))>
-+  friend Type& operator + (OffsetTo &offset, Base &&base) { return offset ((void *) base); }
-+
-   Type& serialize (hb_serialize_context_t *c, const void *base)
-   {
-     return * (Type *) Offset<OffsetType>::serialize (c, base);
-   }
- 
--  template <typename T>
--  void serialize_subset (hb_subset_context_t *c, const T &src, const void *base)
-+  template <typename ...Ts>
-+  bool serialize_subset (hb_subset_context_t *c,
-+			 const OffsetTo& src,
-+			 const void *src_base,
-+			 const void *dst_base,
-+			 Ts&&... ds)
-   {
--    if (&src == &Null (T))
--    {
--      this->set (0);
--      return;
--    }
--    serialize (c->serializer, base);
--    if (!src.subset (c))
--      this->set (0);
-+    *this = 0;
-+    if (src.is_null ())
-+      return false;
-+
-+    auto *s = c->serializer;
-+
-+    s->push ();
-+
-+    bool ret = c->dispatch (src_base+src, hb_forward<Ts> (ds)...);
-+
-+    if (ret || !has_null)
-+      s->add_link (*this, s->pop_pack (), dst_base);
-+    else
-+      s->pop_discard ();
-+
-+    return ret;
-+  }
-+
-+  /* TODO: Somehow merge this with previous function into a serialize_dispatch(). */
-+  template <typename ...Ts>
-+  bool serialize_copy (hb_serialize_context_t *c,
-+		       const OffsetTo& src,
-+		       const void *src_base,
-+		       const void *dst_base,
-+		       Ts&&... ds)
-+  {
-+    *this = 0;
-+    if (src.is_null ())
-+      return false;
-+
-+    c->push ();
-+
-+    bool ret = c->copy (src_base+src, hb_forward<Ts> (ds)...);
-+
-+    c->add_link (*this, c->pop_pack (), dst_base);
-+
-+    return ret;
-   }
- 
-   bool sanitize_shallow (hb_sanitize_context_t *c, const void *base) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!c->check_struct (this))) return_trace (false);
-     if (unlikely (this->is_null ())) return_trace (true);
-     if (unlikely (!c->check_range (base, *this))) return_trace (false);
-     return_trace (true);
-   }
- 
--  bool sanitize (hb_sanitize_context_t *c, const void *base) const
--  {
--    TRACE_SANITIZE (this);
--    return_trace (sanitize_shallow (c, base) &&
--		  (this->is_null () ||
--		   StructAtOffset<Type> (base, *this).sanitize (c) ||
--		   neuter (c)));
--  }
--  template <typename T1>
--  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1) const
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (sanitize_shallow (c, base) &&
- 		  (this->is_null () ||
--		   StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
--		   neuter (c)));
--  }
--  template <typename T1, typename T2>
--  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2) const
--  {
--    TRACE_SANITIZE (this);
--    return_trace (sanitize_shallow (c, base) &&
--		  (this->is_null () ||
--		   StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
--		   neuter (c)));
--  }
--  template <typename T1, typename T2, typename T3>
--  bool sanitize (hb_sanitize_context_t *c, const void *base, T1 d1, T2 d2, T3 d3) const
--  {
--    TRACE_SANITIZE (this);
--    return_trace (sanitize_shallow (c, base) &&
--		  (this->is_null () ||
--		   StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
-+		   c->dispatch (StructAtOffset<Type> (base, *this), hb_forward<Ts> (ds)...) ||
- 		   neuter (c)));
-   }
- 
-   /* Set the offset to Null */
-   bool neuter (hb_sanitize_context_t *c) const
-   {
-     if (!has_null) return false;
-     return c->try_set (this, 0);
-   }
-   DEFINE_SIZE_STATIC (sizeof (OffsetType));
- };
- /* Partial specializations. */
--template <typename Type,                               bool has_null=true> struct   LOffsetTo : OffsetTo<Type, HBUINT32,   has_null> {};
--template <typename Type, typename OffsetType=HBUINT16                    > struct  NNOffsetTo : OffsetTo<Type, OffsetType, false> {};
--template <typename Type                                                  > struct LNNOffsetTo : OffsetTo<Type, HBUINT32,   false> {};
--
--template <typename Base, typename OffsetType, bool has_null, typename Type>
--static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
--template <typename Base, typename OffsetType, bool has_null, typename Type>
--static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
-+template <typename Type, bool has_null=true>
-+using LOffsetTo = OffsetTo<Type, HBUINT32, has_null>;
-+template <typename Type, typename OffsetType=HBUINT16>
-+using NNOffsetTo = OffsetTo<Type, OffsetType, false>;
-+template <typename Type>
-+using LNNOffsetTo = LOffsetTo<Type, false>;
- 
- 
- /*
-  * Array Types
-  */
- 
- template <typename Type>
- struct UnsizedArrayOf
- {
-   typedef Type item_t;
-   static constexpr unsigned item_size = hb_static_size (Type);
- 
--  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
-+  HB_DELETE_CREATE_COPY_ASSIGN (UnsizedArrayOf);
- 
-   const Type& operator [] (int i_) const
-   {
-     unsigned int i = (unsigned int) i_;
-     const Type *p = &arrayZ[i];
-     if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */
-     return *p;
-   }
-@@ -392,48 +423,52 @@ struct UnsizedArrayOf
-   { return *as_array (len).lsearch (x, &not_found); }
-   template <typename T>
-   const Type &lsearch (unsigned int len, const T &x, const Type &not_found = Null (Type)) const
-   { return *as_array (len).lsearch (x, &not_found); }
- 
-   void qsort (unsigned int len, unsigned int start = 0, unsigned int end = (unsigned int) -1)
-   { as_array (len).qsort (start, end); }
- 
--  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-+  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
-+  {
-+    TRACE_SERIALIZE (this);
-+    if (unlikely (!c->extend (*this, items_len))) return_trace (false);
-+    return_trace (true);
-+  }
-+  template <typename Iterator,
-+	    hb_requires (hb_is_source_of (Iterator, Type))>
-+  bool serialize (hb_serialize_context_t *c, Iterator items)
-+  {
-+    TRACE_SERIALIZE (this);
-+    unsigned count = items.len ();
-+    if (unlikely (!serialize (c, count))) return_trace (false);
-+    /* TODO Umm. Just exhaust the iterator instead?  Being extra
-+     * cautious right now.. */
-+    for (unsigned i = 0; i < count; i++, ++items)
-+      arrayZ[i] = *items;
-+    return_trace (true);
-+  }
-+
-+  UnsizedArrayOf* copy (hb_serialize_context_t *c, unsigned count) const
-+  {
-+    TRACE_SERIALIZE (this);
-+    auto *out = c->start_embed (this);
-+    if (unlikely (!as_array (count).copy (c))) return_trace (nullptr);
-+    return_trace (out);
-+  }
-+
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
--
--    /* Note: for structs that do not reference other structs,
--     * we do not need to call their sanitize() as we already did
--     * a bound check on the aggregate array size.  We just include
--     * a small unreachable expression to make sure the structs
--     * pointed to do have a simple sanitize(), ie. they do not
--     * reference other structs via offsets.
--     */
--    (void) (false && arrayZ[0].sanitize (c));
--
--    return_trace (true);
--  }
--  bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base) const
--  {
--    TRACE_SANITIZE (this);
--    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
-+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
-     for (unsigned int i = 0; i < count; i++)
--      if (unlikely (!arrayZ[i].sanitize (c, base)))
--	return_trace (false);
--    return_trace (true);
--  }
--  template <typename T>
--  bool sanitize (hb_sanitize_context_t *c, unsigned int count, const void *base, T user_data) const
--  {
--    TRACE_SANITIZE (this);
--    if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
--    for (unsigned int i = 0; i < count; i++)
--      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-+      if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
- 	return_trace (false);
-     return_trace (true);
-   }
- 
-   bool sanitize_shallow (hb_sanitize_context_t *c, unsigned int count) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_array (arrayZ, count));
-@@ -442,17 +477,17 @@ struct UnsizedArrayOf
-   public:
-   Type		arrayZ[VAR];
-   public:
-   DEFINE_SIZE_UNBOUNDED (0);
- };
- 
- /* Unsized array of offset's */
- template <typename Type, typename OffsetType, bool has_null=true>
--struct UnsizedOffsetArrayOf : UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null> > {};
-+using UnsizedOffsetArrayOf = UnsizedArrayOf<OffsetTo<Type, OffsetType, has_null>>;
- 
- /* Unsized array of offsets relative to the beginning of the array itself. */
- template <typename Type, typename OffsetType, bool has_null=true>
- struct UnsizedOffsetListOf : UnsizedOffsetArrayOf<Type, OffsetType, has_null>
- {
-   const Type& operator [] (int i_) const
-   {
-     unsigned int i = (unsigned int) i_;
-@@ -463,27 +498,22 @@ struct UnsizedOffsetListOf : UnsizedOffs
-   Type& operator [] (int i_)
-   {
-     unsigned int i = (unsigned int) i_;
-     const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
-     if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
-     return this+*p;
-   }
- 
--
--  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, unsigned int count, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
--    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this)));
--  }
--  template <typename T>
--  bool sanitize (hb_sanitize_context_t *c, unsigned int count, T user_data) const
--  {
--    TRACE_SANITIZE (this);
--    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>::sanitize (c, count, this, user_data)));
-+    return_trace ((UnsizedOffsetArrayOf<Type, OffsetType, has_null>
-+		   ::sanitize (c, count, this, hb_forward<Ts> (ds)...)));
-   }
- };
- 
- /* An array with sorted elements.  Supports binary searching. */
- template <typename Type>
- struct SortedUnsizedArrayOf : UnsizedArrayOf<Type>
- {
-   hb_sorted_array_t<Type> as_array (unsigned int len)
-@@ -509,17 +539,17 @@ struct SortedUnsizedArrayOf : UnsizedArr
- 
- /* An array with a number of elements. */
- template <typename Type, typename LenType=HBUINT16>
- struct ArrayOf
- {
-   typedef Type item_t;
-   static constexpr unsigned item_size = hb_static_size (Type);
- 
--  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOf, Type, LenType);
-+  HB_DELETE_CREATE_COPY_ASSIGN (ArrayOf);
- 
-   const Type& operator [] (int i_) const
-   {
-     unsigned int i = (unsigned int) i_;
-     if (unlikely (i >= len)) return Null (Type);
-     return arrayZ[i];
-   }
-   Type& operator [] (int i_)
-@@ -527,84 +557,79 @@ struct ArrayOf
-     unsigned int i = (unsigned int) i_;
-     if (unlikely (i >= len)) return Crap (Type);
-     return arrayZ[i];
-   }
- 
-   unsigned int get_size () const
-   { return len.static_size + len * Type::static_size; }
- 
--  hb_array_t<Type> as_array ()
--  { return hb_array (arrayZ, len); }
--  hb_array_t<const Type> as_array () const
--  { return hb_array (arrayZ, len); }
--  operator hb_array_t<Type> (void)             { return as_array (); }
--  operator hb_array_t<const Type> (void) const { return as_array (); }
-+  explicit operator bool () const { return len; }
-+
-+  hb_array_t<      Type> as_array ()       { return hb_array (arrayZ, len); }
-+  hb_array_t<const Type> as_array () const { return hb_array (arrayZ, len); }
-+
-+  /* Iterator. */
-+  typedef hb_array_t<const Type>   iter_t;
-+  typedef hb_array_t<      Type> writer_t;
-+    iter_t   iter () const { return as_array (); }
-+  writer_t writer ()       { return as_array (); }
-+  operator   iter_t () const { return   iter (); }
-+  operator writer_t ()       { return writer (); }
- 
-   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
-   { return as_array ().sub_array (start_offset, count);}
-   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
-   { return as_array ().sub_array (start_offset, count);}
-   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
-   { return as_array ().sub_array (start_offset, count);}
-   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
-   { return as_array ().sub_array (start_offset, count);}
- 
-   bool serialize (hb_serialize_context_t *c, unsigned int items_len)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
--    len.set (items_len); /* TODO(serialize) Overflow? */
-+    c->check_assign (len, items_len);
-     if (unlikely (!c->extend (*this))) return_trace (false);
-     return_trace (true);
-   }
--  template <typename T>
--  bool serialize (hb_serialize_context_t *c, hb_array_t<const T> items)
-+  template <typename Iterator,
-+	    hb_requires (hb_is_source_of (Iterator, Type))>
-+  bool serialize (hb_serialize_context_t *c, Iterator items)
-   {
-     TRACE_SERIALIZE (this);
--    if (unlikely (!serialize (c, items.length))) return_trace (false);
--    for (unsigned int i = 0; i < items.length; i++)
--      hb_assign (arrayZ[i], items[i]);
-+    unsigned count = items.len ();
-+    if (unlikely (!serialize (c, count))) return_trace (false);
-+    /* TODO Umm. Just exhaust the iterator instead?  Being extra
-+     * cautious right now.. */
-+    for (unsigned i = 0; i < count; i++, ++items)
-+      arrayZ[i] = *items;
-     return_trace (true);
-   }
- 
--  bool sanitize (hb_sanitize_context_t *c) const
-+  ArrayOf* copy (hb_serialize_context_t *c) const
-+  {
-+    TRACE_SERIALIZE (this);
-+    auto *out = c->start_embed (this);
-+    if (unlikely (!c->extend_min (out))) return_trace (nullptr);
-+    c->check_assign (out->len, len);
-+    if (unlikely (!as_array ().copy (c))) return_trace (nullptr);
-+    return_trace (out);
-+  }
-+
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!sanitize_shallow (c))) return_trace (false);
--
--    /* Note: for structs that do not reference other structs,
--     * we do not need to call their sanitize() as we already did
--     * a bound check on the aggregate array size.  We just include
--     * a small unreachable expression to make sure the structs
--     * pointed to do have a simple sanitize(), ie. they do not
--     * reference other structs via offsets.
--     */
--    (void) (false && arrayZ[0].sanitize (c));
--
--    return_trace (true);
--  }
--  bool sanitize (hb_sanitize_context_t *c, const void *base) const
--  {
--    TRACE_SANITIZE (this);
--    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
-     unsigned int count = len;
-     for (unsigned int i = 0; i < count; i++)
--      if (unlikely (!arrayZ[i].sanitize (c, base)))
--	return_trace (false);
--    return_trace (true);
--  }
--  template <typename T>
--  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
--  {
--    TRACE_SANITIZE (this);
--    if (unlikely (!sanitize_shallow (c))) return_trace (false);
--    unsigned int count = len;
--    for (unsigned int i = 0; i < count; i++)
--      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-+      if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
- 	return_trace (false);
-     return_trace (true);
-   }
- 
-   template <typename T>
-   Type &lsearch (const T &x, Type &not_found = Crap (Type))
-   { return *as_array ().lsearch (x, &not_found); }
-   template <typename T>
-@@ -621,26 +646,27 @@ struct ArrayOf
-   }
- 
-   public:
-   LenType	len;
-   Type		arrayZ[VAR];
-   public:
-   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
- };
--template <typename Type> struct LArrayOf : ArrayOf<Type, HBUINT32> {};
--typedef ArrayOf<HBUINT8, HBUINT8> PString;
-+template <typename Type>
-+using LArrayOf = ArrayOf<Type, HBUINT32>;
-+using PString = ArrayOf<HBUINT8, HBUINT8>;
- 
- /* Array of Offset's */
- template <typename Type>
--struct OffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT16> > {};
-+using OffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT16>>;
- template <typename Type>
--struct LOffsetArrayOf : ArrayOf<OffsetTo<Type, HBUINT32> > {};
-+using LOffsetArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>>;
- template <typename Type>
--struct LOffsetLArrayOf : ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32> {};
-+using LOffsetLArrayOf = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
- 
- /* Array of offsets relative to the beginning of the array itself. */
- template <typename Type>
- struct OffsetListOf : OffsetArrayOf<Type>
- {
-   const Type& operator [] (int i_) const
-   {
-     unsigned int i = (unsigned int) i_;
-@@ -656,40 +682,35 @@ struct OffsetListOf : OffsetArrayOf<Type
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
-     struct OffsetListOf<Type> *out = c->serializer->embed (*this);
-     if (unlikely (!out)) return_trace (false);
-     unsigned int count = this->len;
-     for (unsigned int i = 0; i < count; i++)
--      out->arrayZ[i].serialize_subset (c, (*this)[i], out);
-+      out->arrayZ[i].serialize_subset (c, this->arrayZ[i], this, out);
-     return_trace (true);
-   }
- 
--  bool sanitize (hb_sanitize_context_t *c) const
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
--    return_trace (OffsetArrayOf<Type>::sanitize (c, this));
--  }
--  template <typename T>
--  bool sanitize (hb_sanitize_context_t *c, T user_data) const
--  {
--    TRACE_SANITIZE (this);
--    return_trace (OffsetArrayOf<Type>::sanitize (c, this, user_data));
-+    return_trace (OffsetArrayOf<Type>::sanitize (c, this, hb_forward<Ts> (ds)...));
-   }
- };
- 
- /* An array starting at second element. */
- template <typename Type, typename LenType=HBUINT16>
- struct HeadlessArrayOf
- {
-   static constexpr unsigned item_size = Type::static_size;
- 
--  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (HeadlessArrayOf, Type, LenType);
-+  HB_DELETE_CREATE_COPY_ASSIGN (HeadlessArrayOf);
- 
-   const Type& operator [] (int i_) const
-   {
-     unsigned int i = (unsigned int) i_;
-     if (unlikely (i >= lenP1 || !i)) return Null (Type);
-     return arrayZ[i-1];
-   }
-   Type& operator [] (int i_)
-@@ -701,37 +722,33 @@ struct HeadlessArrayOf
-   unsigned int get_size () const
-   { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
- 
-   bool serialize (hb_serialize_context_t *c,
- 		  hb_array_t<const Type> items)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
--    lenP1.set (items.length + 1); /* TODO(serialize) Overflow? */
-+    c->check_assign (lenP1, items.length + 1);
-     if (unlikely (!c->extend (*this))) return_trace (false);
-     for (unsigned int i = 0; i < items.length; i++)
-       arrayZ[i] = items[i];
-     return_trace (true);
-   }
- 
--  bool sanitize (hb_sanitize_context_t *c) const
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!sanitize_shallow (c))) return_trace (false);
--
--    /* Note: for structs that do not reference other structs,
--     * we do not need to call their sanitize() as we already did
--     * a bound check on the aggregate array size.  We just include
--     * a small unreachable expression to make sure the structs
--     * pointed to do have a simple sanitize(), ie. they do not
--     * reference other structs via offsets.
--     */
--    (void) (false && arrayZ[0].sanitize (c));
--
-+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
-+    unsigned int count = lenP1 ? lenP1 - 1 : 0;
-+    for (unsigned int i = 0; i < count; i++)
-+      if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
-+	return_trace (false);
-     return_trace (true);
-   }
- 
-   private:
-   bool sanitize_shallow (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (lenP1.sanitize (c) &&
-@@ -744,41 +761,41 @@ struct HeadlessArrayOf
-   public:
-   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
- };
- 
- /* An array storing length-1. */
- template <typename Type, typename LenType=HBUINT16>
- struct ArrayOfM1
- {
--  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOfM1, Type, LenType);
-+  HB_DELETE_CREATE_COPY_ASSIGN (ArrayOfM1);
- 
-   const Type& operator [] (int i_) const
-   {
-     unsigned int i = (unsigned int) i_;
-     if (unlikely (i > lenM1)) return Null (Type);
-     return arrayZ[i];
-   }
-   Type& operator [] (int i_)
-   {
-     unsigned int i = (unsigned int) i_;
-     if (unlikely (i > lenM1)) return Crap (Type);
-     return arrayZ[i];
-   }
-   unsigned int get_size () const
-   { return lenM1.static_size + (lenM1 + 1) * Type::static_size; }
- 
--  template <typename T>
--  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!sanitize_shallow (c))) return_trace (false);
-     unsigned int count = lenM1 + 1;
-     for (unsigned int i = 0; i < count; i++)
--      if (unlikely (!arrayZ[i].sanitize (c, base, user_data)))
-+      if (unlikely (!c->dispatch (arrayZ[i], hb_forward<Ts> (ds)...)))
- 	return_trace (false);
-     return_trace (true);
-   }
- 
-   private:
-   bool sanitize_shallow (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-@@ -792,31 +809,50 @@ struct ArrayOfM1
-   public:
-   DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
- };
- 
- /* An array with sorted elements.  Supports binary searching. */
- template <typename Type, typename LenType=HBUINT16>
- struct SortedArrayOf : ArrayOf<Type, LenType>
- {
--  hb_sorted_array_t<Type> as_array ()
--  { return hb_sorted_array (this->arrayZ, this->len); }
--  hb_sorted_array_t<const Type> as_array () const
--  { return hb_sorted_array (this->arrayZ, this->len); }
--  operator hb_sorted_array_t<Type> ()             { return as_array (); }
--  operator hb_sorted_array_t<const Type> () const { return as_array (); }
-+  hb_sorted_array_t<      Type> as_array ()       { return hb_sorted_array (this->arrayZ, this->len); }
-+  hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ, this->len); }
-+
-+  /* Iterator. */
-+  typedef hb_sorted_array_t<const Type>   iter_t;
-+  typedef hb_sorted_array_t<      Type> writer_t;
-+    iter_t   iter () const { return as_array (); }
-+  writer_t writer ()       { return as_array (); }
-+  operator   iter_t () const { return   iter (); }
-+  operator writer_t ()       { return writer (); }
- 
--  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
-+  hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
-+  { return as_array ().sub_array (start_offset, count);}
-+  hb_sorted_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
-   { return as_array ().sub_array (start_offset, count);}
--  hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
-+  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
-+  { return as_array ().sub_array (start_offset, count);}
-+  hb_sorted_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
-   { return as_array ().sub_array (start_offset, count);}
--  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
--  { return as_array ().sub_array (start_offset, count);}
--  hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
--  { return as_array ().sub_array (start_offset, count);}
-+
-+  bool serialize (hb_serialize_context_t *c, unsigned int items_len)
-+  {
-+    TRACE_SERIALIZE (this);
-+    bool ret = ArrayOf<Type, LenType>::serialize (c, items_len);
-+    return_trace (ret);
-+  }
-+  template <typename Iterator,
-+	    hb_requires (hb_is_sorted_source_of (Iterator, Type))>
-+  bool serialize (hb_serialize_context_t *c, Iterator items)
-+  {
-+    TRACE_SERIALIZE (this);
-+    bool ret = ArrayOf<Type, LenType>::serialize (c, items);
-+    return_trace (ret);
-+  }
- 
-   template <typename T>
-   Type &bsearch (const T &x, Type &not_found = Crap (Type))
-   { return *as_array ().bsearch (x, &not_found); }
-   template <typename T>
-   const Type &bsearch (const T &x, const Type &not_found = Null (Type)) const
-   { return *as_array ().bsearch (x, &not_found); }
-   template <typename T>
-@@ -836,39 +872,40 @@ struct BinSearchHeader
-   operator uint32_t () const { return len; }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this));
-   }
- 
--  void set (unsigned int v)
-+  BinSearchHeader& operator = (unsigned int v)
-   {
--    len.set (v);
-+    len = v;
-     assert (len == v);
--    entrySelector.set (MAX (1u, hb_bit_storage (v)) - 1);
--    searchRange.set (16 * (1u << entrySelector));
--    rangeShift.set (v * 16 > searchRange
--		    ? 16 * v - searchRange
--		    : 0);
-+    entrySelector = hb_max (1u, hb_bit_storage (v)) - 1;
-+    searchRange = 16 * (1u << entrySelector);
-+    rangeShift = v * 16 > searchRange
-+		 ? 16 * v - searchRange
-+		 : 0;
-+    return *this;
-   }
- 
-   protected:
-   LenType	len;
-   LenType	searchRange;
-   LenType	entrySelector;
-   LenType	rangeShift;
- 
-   public:
-   DEFINE_SIZE_STATIC (8);
- };
- 
- template <typename Type, typename LenType=HBUINT16>
--struct BinSearchArrayOf : SortedArrayOf<Type, BinSearchHeader<LenType> > {};
-+using BinSearchArrayOf = SortedArrayOf<Type, BinSearchHeader<LenType>>;
- 
- 
- struct VarSizedBinSearchHeader
- {
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-@@ -888,17 +925,17 @@ struct VarSizedBinSearchHeader
-   DEFINE_SIZE_STATIC (10);
- };
- 
- template <typename Type>
- struct VarSizedBinSearchArrayOf
- {
-   static constexpr unsigned item_size = Type::static_size;
- 
--  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
-+  HB_DELETE_CREATE_COPY_ASSIGN (VarSizedBinSearchArrayOf);
- 
-   bool last_is_terminator () const
-   {
-     if (unlikely (!header.nUnits)) return false;
- 
-     /* Gah.
-      *
-      * "The number of termination values that need to be included is table-specific.
-@@ -923,50 +960,25 @@ struct VarSizedBinSearchArrayOf
-     if (unlikely (i >= get_length ())) return Crap (Type);
-     return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
-   }
-   unsigned int get_length () const
-   { return header.nUnits - last_is_terminator (); }
-   unsigned int get_size () const
-   { return header.static_size + header.nUnits * header.unitSize; }
- 
--  bool sanitize (hb_sanitize_context_t *c) const
-+  template <typename ...Ts>
-+  bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!sanitize_shallow (c))) return_trace (false);
--
--    /* Note: for structs that do not reference other structs,
--     * we do not need to call their sanitize() as we already did
--     * a bound check on the aggregate array size.  We just include
--     * a small unreachable expression to make sure the structs
--     * pointed to do have a simple sanitize(), ie. they do not
--     * reference other structs via offsets.
--     */
--    (void) (false && StructAtOffset<Type> (&bytesZ, 0).sanitize (c));
--
--    return_trace (true);
--  }
--  bool sanitize (hb_sanitize_context_t *c, const void *base) const
--  {
--    TRACE_SANITIZE (this);
--    if (unlikely (!sanitize_shallow (c))) return_trace (false);
-+    if (!sizeof... (Ts) && hb_is_trivially_copyable (Type)) return_trace (true);
-     unsigned int count = get_length ();
-     for (unsigned int i = 0; i < count; i++)
--      if (unlikely (!(*this)[i].sanitize (c, base)))
--	return_trace (false);
--    return_trace (true);
--  }
--  template <typename T>
--  bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const
--  {
--    TRACE_SANITIZE (this);
--    if (unlikely (!sanitize_shallow (c))) return_trace (false);
--    unsigned int count = get_length ();
--    for (unsigned int i = 0; i < count; i++)
--      if (unlikely (!(*this)[i].sanitize (c, base, user_data)))
-+      if (unlikely (!(*this)[i].sanitize (c, hb_forward<Ts> (ds)...)))
- 	return_trace (false);
-     return_trace (true);
-   }
- 
-   template <typename T>
-   const Type *bsearch (const T &key) const
-   {
-     unsigned int size = header.unitSize;
-diff --git a/gfx/harfbuzz/src/hb-ot-cff-common.hh b/gfx/harfbuzz/src/hb-ot-cff-common.hh
---- a/gfx/harfbuzz/src/hb-ot-cff-common.hh
-+++ b/gfx/harfbuzz/src/hb-ot-cff-common.hh
-@@ -92,22 +92,22 @@ struct CFFIndex
-   }
- 
-   static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
-   { return offSize * (count + 1); }
- 
-   unsigned int offset_array_size () const
-   { return calculate_offset_array_size (offSize, count); }
- 
--  static unsigned int calculate_serialized_size (unsigned int offSize, unsigned int count, unsigned int dataSize)
-+  static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count, unsigned int dataSize)
-   {
-     if (count == 0)
-       return COUNT::static_size;
-     else
--      return min_size + calculate_offset_array_size (offSize, count) + dataSize;
-+      return min_size + calculate_offset_array_size (offSize_, count) + dataSize;
-   }
- 
-   bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
-   {
-     TRACE_SERIALIZE (this);
-     unsigned int size = src.get_size ();
-     CFFIndex *dest = c->allocate_size<CFFIndex> (size);
-     if (unlikely (dest == nullptr)) return_trace (false);
-@@ -119,25 +119,25 @@ struct CFFIndex
- 		  unsigned int offSize_,
- 		  const byte_str_array_t &byteArray)
-   {
-     TRACE_SERIALIZE (this);
-     if (byteArray.length == 0)
-     {
-       COUNT *dest = c->allocate_min<COUNT> ();
-       if (unlikely (dest == nullptr)) return_trace (false);
--      dest->set (0);
-+      *dest = 0;
-     }
-     else
-     {
-       /* serialize CFFIndex header */
-       if (unlikely (!c->extend_min (*this))) return_trace (false);
--      this->count.set (byteArray.length);
--      this->offSize.set (offSize_);
--      if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
-+      this->count = byteArray.length;
-+      this->offSize = offSize_;
-+      if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
- 	return_trace (false);
- 
-       /* serialize indices */
-       unsigned int  offset = 1;
-       unsigned int  i = 0;
-       for (; i < byteArray.length; i++)
-       {
- 	set_offset_at (i, offset);
-@@ -162,31 +162,31 @@ struct CFFIndex
- 		  unsigned int offSize_,
- 		  const str_buff_vec_t &buffArray)
-   {
-     byte_str_array_t  byteArray;
-     byteArray.init ();
-     byteArray.resize (buffArray.length);
-     for (unsigned int i = 0; i < byteArray.length; i++)
-     {
--      byteArray[i] = byte_str_t (buffArray[i].arrayZ (), buffArray[i].length);
-+      byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length);
-     }
-     bool result = this->serialize (c, offSize_, byteArray);
-     byteArray.fini ();
-     return result;
-   }
- 
-   void set_offset_at (unsigned int index, unsigned int offset)
-   {
-     HBUINT8 *p = offsets + offSize * index + offSize;
-     unsigned int size = offSize;
-     for (; size; size--)
-     {
-       --p;
--      p->set (offset & 0xFF);
-+      *p = offset & 0xFF;
-       offset >>= 8;
-     }
-   }
- 
-   unsigned int offset_at (unsigned int index) const
-   {
-     assert (index <= count);
-     const HBUINT8 *p = offsets + offSize * index;
-@@ -270,19 +270,19 @@ struct CFFIndexOf : CFFIndex<COUNT>
- 		  unsigned int dataArrayLen,
- 		  const hb_vector_t<unsigned int> &dataSizeArray,
- 		  const PARAM1 &param1,
- 		  const PARAM2 &param2)
-   {
-     TRACE_SERIALIZE (this);
-     /* serialize CFFIndex header */
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
--    this->count.set (dataArrayLen);
--    this->offSize.set (offSize_);
--    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
-+    this->count = dataArrayLen;
-+    this->offSize = offSize_;
-+    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (dataArrayLen + 1))))
-       return_trace (false);
- 
-     /* serialize indices */
-     unsigned int  offset = 1;
-     unsigned int  i = 0;
-     for (; i < dataArrayLen; i++)
-     {
-       CFFIndex<COUNT>::set_offset_at (i, offset);
-@@ -371,21 +371,21 @@ struct Dict : UnsizedByteStr
-       return false;
- 
-     TRACE_SERIALIZE (this);
-     /* serialize the opcode */
-     HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op));
-     if (unlikely (p == nullptr)) return_trace (false);
-     if (Is_OpCode_ESC (op))
-     {
--      p->set (OpCode_escape);
-+      *p = OpCode_escape;
-       op = Unmake_OpCode_ESC (op);
-       p++;
-     }
--    p->set (op);
-+    *p = op;
-     return_trace (true);
-   }
- 
-   static bool serialize_uint4_op (hb_serialize_context_t *c, op_code_t op, int value)
-   { return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
- 
-   static bool serialize_uint2_op (hb_serialize_context_t *c, op_code_t op, int value)
-   { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
-@@ -472,19 +472,19 @@ struct FDArray : CFFIndexOf<COUNT, FontD
-   template <typename DICTVAL, typename OP_SERIALIZER>
-   bool serialize (hb_serialize_context_t *c,
- 		  unsigned int offSize_,
- 		  const hb_vector_t<DICTVAL> &fontDicts,
- 		  OP_SERIALIZER& opszr)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
--    this->count.set (fontDicts.length);
--    this->offSize.set (offSize_);
--    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
-+    this->count = fontDicts.length;
-+    this->offSize = offSize_;
-+    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
-       return_trace (false);
- 
-     /* serialize font dict offsets */
-     unsigned int  offset = 1;
-     unsigned int fid = 0;
-     for (; fid < fontDicts.length; fid++)
-     {
-       CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
-@@ -509,19 +509,19 @@ struct FDArray : CFFIndexOf<COUNT, FontD
- 		  const hb_vector_t<DICTVAL> &fontDicts,
- 		  unsigned int fdCount,
- 		  const remap_t &fdmap,
- 		  OP_SERIALIZER& opszr,
- 		  const hb_vector_t<table_info_t> &privateInfos)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
--    this->count.set (fdCount);
--    this->offSize.set (offSize_);
--    if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
-+    this->count = fdCount;
-+    this->offSize = offSize_;
-+    if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
-       return_trace (false);
- 
-     /* serialize font dict offsets */
-     unsigned int  offset = 1;
-     unsigned int  fid = 0;
-     for (unsigned i = 0; i < fontDicts.length; i++)
-       if (fdmap.includes (i))
-       {
-@@ -584,17 +584,17 @@ struct FDSelect0 {
- 
-   HBUINT8     fds[VAR];
- 
-   DEFINE_SIZE_MIN (1);
- };
- 
- template <typename GID_TYPE, typename FD_TYPE>
- struct FDSelect3_4_Range {
--  bool sanitize (hb_sanitize_context_t *c, const void */*nullptr*/, unsigned int fdcount) const
-+  bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (first < c->get_num_glyphs () && (fd < fdcount));
-   }
- 
-   GID_TYPE    first;
-   FD_TYPE     fd;
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-cff1-table.cc b/gfx/harfbuzz/src/hb-ot-cff1-table.cc
---- a/gfx/harfbuzz/src/hb-ot-cff1-table.cc
-+++ b/gfx/harfbuzz/src/hb-ot-cff1-table.cc
-@@ -22,16 +22,18 @@
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Adobe Author(s): Michiharu Ariza
-  */
- 
- #include "hb-ot-cff1-table.hh"
- #include "hb-cff1-interp-cs.hh"
- 
-+#ifndef HB_NO_CFF
-+
- using namespace CFF;
- 
- /* SID to code */
- static const uint8_t standard_encoding_to_code [] =
- {
-     0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46,
-    47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62,
-    63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78,
-@@ -160,18 +162,18 @@ hb_codepoint_t OT::cff1::lookup_standard
-   else
-     return CFF_UNDEF_SID;
- }
- 
- struct bounds_t
- {
-   void init ()
-   {
--    min.set_int (0x7FFFFFFF, 0x7FFFFFFF);
--    max.set_int (-0x80000000, -0x80000000);
-+    min.set_int (INT_MAX, INT_MAX);
-+    max.set_int (INT_MIN, INT_MIN);
-   }
- 
-   void update (const point_t &pt)
-   {
-     if (pt.x < min.x) min.x = pt.x;
-     if (pt.x > max.x) max.x = pt.x;
-     if (pt.y < min.y) min.y = pt.y;
-     if (pt.y > max.y) max.y = pt.y;
-@@ -300,16 +302,21 @@ bool _get_bounds (const OT::cff1::accele
-   param.init (cff);
-   if (unlikely (!interp.interpret (param))) return false;
-   bounds = param.bounds;
-   return true;
- }
- 
- bool OT::cff1::accelerator_t::get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
- {
-+#ifdef HB_NO_OT_FONT_CFF
-+  /* XXX Remove check when this code moves to .hh file. */
-+  return true;
-+#endif
-+
-   bounds_t  bounds;
- 
-   if (!_get_bounds (this, glyph, bounds))
-     return false;
- 
-   if (bounds.min.x >= bounds.max.x)
-   {
-     extents->width = 0;
-@@ -378,8 +385,10 @@ bool OT::cff1::accelerator_t::get_seac_c
-   if (param.has_seac ())
-   {
-     *base = param.base;
-     *accent = param.accent;
-     return true;
-   }
-   return false;
- }
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-ot-cff1-table.hh b/gfx/harfbuzz/src/hb-ot-cff1-table.hh
---- a/gfx/harfbuzz/src/hb-ot-cff1-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-cff1-table.hh
-@@ -105,17 +105,18 @@ struct Encoding1 {
-   hb_codepoint_t get_code (hb_codepoint_t glyph) const
-   {
-     assert (glyph > 0);
-     glyph--;
-     for (unsigned int i = 0; i < nRanges (); i++)
-     {
-       if (glyph <= ranges[i].nLeft)
-       {
--	return (hb_codepoint_t)ranges[i].first + glyph;
-+	hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
-+	return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
-       }
-       glyph -= (ranges[i].nLeft + 1);
-     }
-     return CFF_UNDEF_CODE;
-   }
- 
-   HBUINT8 &nRanges () { return ranges.len; }
-   HBUINT8 nRanges () const { return ranges.len; }
-@@ -191,54 +192,54 @@ struct Encoding {
- 		  uint8_t format,
- 		  unsigned int enc_count,
- 		  const hb_vector_t<code_pair_t>& code_ranges,
- 		  const hb_vector_t<code_pair_t>& supp_codes)
-   {
-     TRACE_SERIALIZE (this);
-     Encoding *dest = c->extend_min (*this);
-     if (unlikely (dest == nullptr)) return_trace (false);
--    dest->format.set (format | ((supp_codes.length > 0)? 0x80: 0));
-+    dest->format = format | ((supp_codes.length > 0)? 0x80: 0);
-     if (format == 0)
-     {
-       Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
-     if (unlikely (fmt0 == nullptr)) return_trace (false);
--      fmt0->nCodes ().set (enc_count);
-+      fmt0->nCodes () = enc_count;
-       unsigned int glyph = 0;
-       for (unsigned int i = 0; i < code_ranges.length; i++)
-       {
- 	hb_codepoint_t code = code_ranges[i].code;
- 	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
--	  fmt0->codes[glyph++].set (code++);
-+	  fmt0->codes[glyph++] = code++;
- 	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
- 	  return_trace (false);
-       }
-     }
-     else
-     {
-       Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
-       if (unlikely (fmt1 == nullptr)) return_trace (false);
--      fmt1->nRanges ().set (code_ranges.length);
-+      fmt1->nRanges () = code_ranges.length;
-       for (unsigned int i = 0; i < code_ranges.length; i++)
-       {
- 	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
- 	  return_trace (false);
--	fmt1->ranges[i].first.set (code_ranges[i].code);
--	fmt1->ranges[i].nLeft.set (code_ranges[i].glyph);
-+	fmt1->ranges[i].first = code_ranges[i].code;
-+	fmt1->ranges[i].nLeft = code_ranges[i].glyph;
-       }
-     }
-     if (supp_codes.length > 0)
-     {
-       CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
-       if (unlikely (suppData == nullptr)) return_trace (false);
--      suppData->nSups ().set (supp_codes.length);
-+      suppData->nSups () = supp_codes.length;
-       for (unsigned int i = 0; i < supp_codes.length; i++)
-       {
--	suppData->supps[i].code.set (supp_codes[i].code);
--	suppData->supps[i].glyph.set (supp_codes[i].glyph); /* actually SID */
-+	suppData->supps[i].code = supp_codes[i].code;
-+	suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
-       }
-     }
-     return_trace (true);
-   }
- 
-   /* parallel to above: calculate the size of a subset Encoding */
-   static unsigned int calculate_serialized_size (uint8_t format,
- 						 unsigned int enc_count,
-@@ -464,51 +465,51 @@ struct Charset {
-   bool serialize (hb_serialize_context_t *c,
- 		  uint8_t format,
- 		  unsigned int num_glyphs,
- 		  const hb_vector_t<code_pair_t>& sid_ranges)
-   {
-     TRACE_SERIALIZE (this);
-     Charset *dest = c->extend_min (*this);
-     if (unlikely (dest == nullptr)) return_trace (false);
--    dest->format.set (format);
-+    dest->format = format;
-     if (format == 0)
-     {
-       Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
-     if (unlikely (fmt0 == nullptr)) return_trace (false);
-       unsigned int glyph = 0;
-       for (unsigned int i = 0; i < sid_ranges.length; i++)
-       {
- 	hb_codepoint_t sid = sid_ranges[i].code;
- 	for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
--	  fmt0->sids[glyph++].set (sid++);
-+	  fmt0->sids[glyph++] = sid++;
-       }
-     }
-     else if (format == 1)
-     {
-       Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
-       if (unlikely (fmt1 == nullptr)) return_trace (false);
-       for (unsigned int i = 0; i < sid_ranges.length; i++)
-       {
-       	if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
- 	  return_trace (false);
--	fmt1->ranges[i].first.set (sid_ranges[i].code);
--	fmt1->ranges[i].nLeft.set (sid_ranges[i].glyph);
-+	fmt1->ranges[i].first = sid_ranges[i].code;
-+	fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
-       }
-     }
-     else /* format 2 */
-     {
-       Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
-       if (unlikely (fmt2 == nullptr)) return_trace (false);
-       for (unsigned int i = 0; i < sid_ranges.length; i++)
-       {
-       	if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
- 	  return_trace (false);
--	fmt2->ranges[i].first.set (sid_ranges[i].code);
--	fmt2->ranges[i].nLeft.set (sid_ranges[i].glyph);
-+	fmt2->ranges[i].first = sid_ranges[i].code;
-+	fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
-       }
-     }
-     return_trace (true);
-   }
- 
-   /* parallel to above: calculate the size of a subset Charset */
-   static unsigned int calculate_serialized_size (
- 			uint8_t format,
-@@ -570,19 +571,19 @@ struct Charset {
- struct CFF1StringIndex : CFF1Index
- {
-   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
- 		  unsigned int offSize_, const remap_t &sidmap)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
-     {
--      if (!unlikely (c->extend_min (this->count)))
-+      if (unlikely (!c->extend_min (this->count)))
- 	return_trace (false);
--      count.set (0);
-+      count = 0;
-       return_trace (true);
-     }
- 
-     byte_str_array_t bytesArray;
-     bytesArray.init ();
-     if (!bytesArray.resize (sidmap.get_count ()))
-       return_trace (false);
-     for (unsigned int i = 0; i < strings.count; i++)
-@@ -593,29 +594,29 @@ struct CFF1StringIndex : CFF1Index
-     }
- 
-     bool result = CFF1Index::serialize (c, offSize_, bytesArray);
-     bytesArray.fini ();
-     return_trace (result);
-   }
- 
-   /* in parallel to above */
--  unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const remap_t &sidmap) const
-+  unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const remap_t &sidmap) const
-   {
--    offSize = 0;
-+    offSize_ = 0;
-     if ((count == 0) || (sidmap.get_count () == 0))
-       return count.static_size;
- 
-     unsigned int dataSize = 0;
-     for (unsigned int i = 0; i < count; i++)
-       if (sidmap[i] != CFF_UNDEF_CODE)
- 	dataSize += length_at (i);
- 
--    offSize = calcOffSize(dataSize);
--    return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize);
-+    offSize_ = calcOffSize(dataSize);
-+    return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_count (), dataSize);
-   }
- };
- 
- struct cff1_top_dict_interp_env_t : num_interp_env_t
- {
-   cff1_top_dict_interp_env_t ()
-     : num_interp_env_t(), prev_offset(0), last_offset(0) {}
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-cff2-table.cc b/gfx/harfbuzz/src/hb-ot-cff2-table.cc
---- a/gfx/harfbuzz/src/hb-ot-cff2-table.cc
-+++ b/gfx/harfbuzz/src/hb-ot-cff2-table.cc
-@@ -22,27 +22,29 @@
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Adobe Author(s): Michiharu Ariza
-  */
- 
- #include "hb-ot-cff2-table.hh"
- #include "hb-cff2-interp-cs.hh"
- 
-+#ifndef HB_NO_OT_FONT_CFF
-+
- using namespace CFF;
- 
- struct extents_param_t
- {
-   void init ()
-   {
-     path_open = false;
--    min_x.set_int (0x7FFFFFFF);
--    min_y.set_int (0x7FFFFFFF);
--    max_x.set_int (-0x80000000);
--    max_y.set_int (-0x80000000);
-+    min_x.set_int (INT_MAX);
-+    min_y.set_int (INT_MAX);
-+    max_x.set_int (INT_MIN);
-+    max_y.set_int (INT_MIN);
-   }
- 
-   void start_path ()         { path_open = true; }
-   void end_path ()           { path_open = false; }
-   bool is_path_open () const { return path_open; }
- 
-   void update_bounds (const point_t &pt)
-   {
-@@ -94,16 +96,21 @@ struct cff2_path_procs_extents_t : path_
- };
- 
- struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, extents_param_t, cff2_path_procs_extents_t> {};
- 
- bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
- 					   hb_codepoint_t glyph,
- 					   hb_glyph_extents_t *extents) const
- {
-+#ifdef HB_NO_OT_FONT_CFF
-+  /* XXX Remove check when this code moves to .hh file. */
-+  return true;
-+#endif
-+
-   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
- 
-   unsigned int num_coords;
-   const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
-   unsigned int fd = fdSelect->get_fd (glyph);
-   cff2_cs_interpreter_t<cff2_cs_opset_extents_t, extents_param_t> interp;
-   const byte_str_t str = (*charStrings)[glyph];
-   interp.env.init (str, *this, fd, coords, num_coords);
-@@ -129,8 +136,10 @@ bool OT::cff2::accelerator_t::get_extent
-   else
-   {
-     extents->y_bearing = (int32_t)param.max_y.ceil ();
-     extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
-   }
- 
-   return true;
- }
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-ot-cmap-table.hh b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
---- a/gfx/harfbuzz/src/hb-ot-cmap-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
-@@ -78,54 +78,54 @@ struct CmapSubtableFormat4
-   {
-     HBUINT16 start_code;
-     HBUINT16 end_code;
-     bool use_delta;
-   };
- 
-   bool serialize (hb_serialize_context_t *c,
- 		  const hb_subset_plan_t *plan,
--		  const hb_vector_t<segment_plan> &segments)
-+		  const hb_sorted_vector_t<segment_plan> &segments)
-   {
-     TRACE_SERIALIZE (this);
- 
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
- 
--    this->format.set (4);
--    this->length.set (get_sub_table_size (segments));
-+    this->format = 4;
-+    this->length = get_sub_table_size (segments);
- 
--    this->segCountX2.set (segments.length * 2);
--    this->entrySelector.set (MAX (1u, hb_bit_storage (segments.length)) - 1);
--    this->searchRange.set (2 * (1u << this->entrySelector));
--    this->rangeShift.set (segments.length * 2 > this->searchRange
--			  ? 2 * segments.length - this->searchRange
--			  : 0);
-+    this->segCountX2 = segments.length * 2;
-+    this->entrySelector = hb_max (1u, hb_bit_storage (segments.length)) - 1;
-+    this->searchRange = 2 * (1u << this->entrySelector);
-+    this->rangeShift = segments.length * 2 > this->searchRange
-+		       ? 2 * segments.length - this->searchRange
-+		       : 0;
- 
-     HBUINT16 *end_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
-     c->allocate_size<HBUINT16> (HBUINT16::static_size); // 2 bytes of padding.
-     HBUINT16 *start_count = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
-     HBINT16 *id_delta = c->allocate_size<HBINT16> (HBUINT16::static_size * segments.length);
-     HBUINT16 *id_range_offset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segments.length);
- 
-     if (id_range_offset == nullptr)
-       return_trace (false);
- 
-     for (unsigned int i = 0; i < segments.length; i++)
-     {
--      end_count[i].set (segments[i].end_code);
--      start_count[i].set (segments[i].start_code);
-+      end_count[i] = segments[i].end_code;
-+      start_count[i] = segments[i].start_code;
-       if (segments[i].use_delta)
-       {
- 	hb_codepoint_t cp = segments[i].start_code;
- 	hb_codepoint_t start_gid = 0;
- 	if (unlikely (!plan->new_gid_for_codepoint (cp, &start_gid) && cp != 0xFFFF))
- 	  return_trace (false);
--	id_delta[i].set (start_gid - segments[i].start_code);
-+	id_delta[i] = start_gid - segments[i].start_code;
-       } else {
--	id_delta[i].set (0);
-+	id_delta[i] = 0;
- 	unsigned int num_codepoints = segments[i].end_code - segments[i].start_code + 1;
- 	HBUINT16 *glyph_id_array = c->allocate_size<HBUINT16> (HBUINT16::static_size * num_codepoints);
- 	if (glyph_id_array == nullptr)
- 	  return_trace (false);
- 	// From the cmap spec:
- 	//
- 	// id_range_offset[i]/2
- 	// + (cp - segments[i].start_code)
-@@ -133,33 +133,32 @@ struct CmapSubtableFormat4
- 	// =
- 	// glyph_id_array + (cp - segments[i].start_code)
- 	//
- 	// So, solve for id_range_offset[i]:
- 	//
- 	// id_range_offset[i]
- 	// =
- 	// 2 * (glyph_id_array - id_range_offset - i)
--	id_range_offset[i].set (2 * (
--	    glyph_id_array - id_range_offset - i));
-+	id_range_offset[i] = 2 * (glyph_id_array - id_range_offset - i);
- 	for (unsigned int j = 0; j < num_codepoints; j++)
- 	{
- 	  hb_codepoint_t cp = segments[i].start_code + j;
--	  hb_codepoint_t new_gid;
-+	  hb_codepoint_t new_gid = 0;
- 	  if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
- 	    return_trace (false);
--	  glyph_id_array[j].set (new_gid);
-+	  glyph_id_array[j] = new_gid;
- 	}
-       }
-     }
- 
-     return_trace (true);
-   }
- 
--  static size_t get_sub_table_size (const hb_vector_t<segment_plan> &segments)
-+  static size_t get_sub_table_size (const hb_sorted_vector_t<segment_plan> &segments)
-   {
-     size_t segment_size = 0;
-     for (unsigned int i = 0; i < segments.length; i++)
-     {
-       // Parallel array entries
-       segment_size +=
- 	    2  // end count
- 	  + 2  // start count
-@@ -172,57 +171,57 @@ struct CmapSubtableFormat4
-     }
- 
-     return min_size
- 	+ 2 // Padding
- 	+ segment_size;
-   }
- 
-   static bool create_sub_table_plan (const hb_subset_plan_t *plan,
--				     hb_vector_t<segment_plan> *segments)
-+				     hb_sorted_vector_t<segment_plan> *segments)
-   {
-     segment_plan *segment = nullptr;
-     hb_codepoint_t last_gid = 0;
- 
-     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-     while (plan->unicodes->next (&cp)) {
--      hb_codepoint_t new_gid;
-+      hb_codepoint_t new_gid = 0;
-       if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
-       {
- 	DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
- 	return false;
-       }
- 
-       /* Stop adding to cmap if we are now outside of unicode BMP. */
-       if (cp > 0xFFFF) break;
- 
-       if (!segment ||
- 	  cp != segment->end_code + 1u)
-       {
- 	segment = segments->push ();
--	segment->start_code.set (cp);
--	segment->end_code.set (cp);
-+	segment->start_code = cp;
-+	segment->end_code = cp;
- 	segment->use_delta = true;
-       } else {
--	segment->end_code.set (cp);
-+	segment->end_code = cp;
- 	if (last_gid + 1u != new_gid)
- 	  // gid's are not consecutive in this segment so delta
- 	  // cannot be used.
- 	  segment->use_delta = false;
-       }
- 
-       last_gid = new_gid;
-     }
- 
-     // There must be a final entry with end_code == 0xFFFF. Check if we need to add one.
-     if (segment == nullptr || segment->end_code != 0xFFFF)
-     {
-       segment = segments->push ();
--      segment->start_code.set (0xFFFF);
--      segment->end_code.set (0xFFFF);
-+      segment->start_code = 0xFFFF;
-+      segment->end_code = 0xFFFF;
-       segment->use_delta = true;
-     }
- 
-     return true;
-   }
- 
-   struct accelerator_t
-   {
-@@ -281,17 +280,17 @@ struct CmapSubtableFormat4
- 	gid += this->idDelta[i];
-       }
-       gid &= 0xFFFFu;
-       if (!gid)
- 	return false;
-       *glyph = gid;
-       return true;
-     }
--    static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
-+    HB_INTERNAL static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
-     {
-       return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph);
-     }
-     void collect_unicodes (hb_set_t *out) const
-     {
-       unsigned int count = this->segCount;
-       if (count && this->startCount[count - 1] == 0xFFFFu)
- 	count--; /* Skip sentinel segment. */
-@@ -344,17 +343,17 @@ struct CmapSubtableFormat4
-     if (unlikely (!c->check_struct (this)))
-       return_trace (false);
- 
-     if (unlikely (!c->check_range (this, length)))
-     {
-       /* Some broken fonts have too long of a "length" value.
-        * If that is the case, just change the value to truncate
-        * the subtable at the end of the blob. */
--      uint16_t new_length = (uint16_t) MIN ((uintptr_t) 65535,
-+      uint16_t new_length = (uint16_t) hb_min ((uintptr_t) 65535,
- 					    (uintptr_t) (c->end -
- 							 (char *) this));
-       if (!c->try_set (&length, new_length))
- 	return_trace (false);
-     }
- 
-     return_trace (16 + 4 * (unsigned int) segCountX2 <= length);
-   }
-@@ -474,34 +473,34 @@ struct CmapSubtableLongSegmented
-     *glyph = gid;
-     return true;
-   }
- 
-   void collect_unicodes (hb_set_t *out) const
-   {
-     for (unsigned int i = 0; i < this->groups.len; i++) {
-       out->add_range (this->groups[i].startCharCode,
--		      MIN ((hb_codepoint_t) this->groups[i].endCharCode,
-+		      hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
- 			   (hb_codepoint_t) HB_UNICODE_MAX));
-     }
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) && groups.sanitize (c));
-   }
- 
-   bool serialize (hb_serialize_context_t *c,
--		  const hb_vector_t<CmapSubtableLongGroup> &group_data)
-+		  const hb_sorted_vector_t<CmapSubtableLongGroup> &group_data)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     if (unlikely (!groups.serialize (c, group_data.as_array ()))) return_trace (false);
--    return true;
-+    return_trace (true);
-   }
- 
-   protected:
-   HBUINT16	format;		/* Subtable format; set to 12. */
-   HBUINT16	reserved;	/* Reserved; set to 0. */
-   HBUINT32	length;		/* Byte length of this subtable. */
-   HBUINT32	language;	/* Ignore. */
-   SortedArrayOf<CmapSubtableLongGroup, HBUINT32>
-@@ -514,59 +513,60 @@ struct CmapSubtableFormat12 : CmapSubtab
- {
-   static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
- 					 hb_codepoint_t u)
-   { return likely (group.startCharCode <= group.endCharCode) ?
- 	   group.glyphID + (u - group.startCharCode) : 0; }
- 
- 
-   bool serialize (hb_serialize_context_t *c,
--		  const hb_vector_t<CmapSubtableLongGroup> &groups)
-+		  const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
-   {
--    if (unlikely (!c->extend_min (*this))) return false;
-+    TRACE_SERIALIZE (this);
-+    if (unlikely (!c->extend_min (*this))) return_trace (false);
- 
--    this->format.set (12);
--    this->reserved.set (0);
--    this->length.set (get_sub_table_size (groups));
-+    this->format = 12;
-+    this->reserved = 0;
-+    this->length = get_sub_table_size (groups_data);
- 
--    return CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups);
-+    return_trace (CmapSubtableLongSegmented<CmapSubtableFormat12>::serialize (c, groups_data));
-   }
- 
--  static size_t get_sub_table_size (const hb_vector_t<CmapSubtableLongGroup> &groups)
-+  static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
-   {
--    return 16 + 12 * groups.length;
-+    return 16 + 12 * groups_data.length;
-   }
- 
-   static bool create_sub_table_plan (const hb_subset_plan_t *plan,
--				     hb_vector_t<CmapSubtableLongGroup> *groups)
-+				     hb_sorted_vector_t<CmapSubtableLongGroup> *groups_out)
-   {
-     CmapSubtableLongGroup *group = nullptr;
- 
-     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-     while (plan->unicodes->next (&cp)) {
--      hb_codepoint_t new_gid;
-+      hb_codepoint_t new_gid = 0;
-       if (unlikely (!plan->new_gid_for_codepoint (cp, &new_gid)))
-       {
- 	DEBUG_MSG(SUBSET, nullptr, "Unable to find new gid for %04x", cp);
- 	return false;
-       }
- 
-       if (!group || !_is_gid_consecutive (group, cp, new_gid))
-       {
--	group = groups->push ();
--	group->startCharCode.set (cp);
--	group->endCharCode.set (cp);
--	group->glyphID.set (new_gid);
-+	group = groups_out->push ();
-+	group->startCharCode = cp;
-+	group->endCharCode = cp;
-+	group->glyphID = new_gid;
-       }
--      else group->endCharCode.set (cp);
-+      else group->endCharCode = cp;
-     }
- 
-     DEBUG_MSG(SUBSET, nullptr, "cmap");
--    for (unsigned int i = 0; i < groups->length; i++) {
--      CmapSubtableLongGroup& group = (*groups)[i];
-+    for (unsigned int i = 0; i < groups_out->length; i++) {
-+      CmapSubtableLongGroup& group = (*groups_out)[i];
-       DEBUG_MSG(SUBSET, nullptr, "  %d: U+%04X-U+%04X, gid %d-%d", i, (uint32_t) group.startCharCode, (uint32_t) group.endCharCode, (uint32_t) group.glyphID, (uint32_t) group.glyphID + ((uint32_t) group.endCharCode - (uint32_t) group.startCharCode));
-     }
- 
-     return true;
-   }
- 
-  private:
-   static bool _is_gid_consecutive (CmapSubtableLongGroup *group,
-@@ -618,17 +618,17 @@ struct UnicodeValueRange
- struct DefaultUVS : SortedArrayOf<UnicodeValueRange, HBUINT32>
- {
-   void collect_unicodes (hb_set_t *out) const
-   {
-     unsigned int count = len;
-     for (unsigned int i = 0; i < count; i++)
-     {
-       hb_codepoint_t first = arrayZ[i].startUnicodeValue;
--      hb_codepoint_t last = MIN ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
-+      hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
- 				 (hb_codepoint_t) HB_UNICODE_MAX);
-       out->add_range (first, last);
-     }
-   }
- 
-   public:
-   DEFINE_SIZE_ARRAY (4, *this);
- };
-@@ -848,79 +848,84 @@ struct cmap
-     size_t final_size () const
-     {
-       return 4 // header
- 	  +  8 * 3 // 3 EncodingRecord
- 	  +  CmapSubtableFormat4::get_sub_table_size (this->format4_segments)
- 	  +  CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
-     }
- 
--    hb_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
--    hb_vector_t<CmapSubtableLongGroup> format12_groups;
-+    hb_sorted_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
-+    hb_sorted_vector_t<CmapSubtableLongGroup> format12_groups;
-   };
- 
-   bool _create_plan (const hb_subset_plan_t *plan,
- 		     subset_plan *cmap_plan) const
-   {
-     if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
-       return false;
- 
-+    if (!find_subtable (12)) return true;
-     return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
-   }
- 
-   bool _subset (const hb_subset_plan_t *plan,
- 		const subset_plan &cmap_subset_plan,
- 		size_t dest_sz,
- 		void *dest) const
-   {
-     hb_serialize_context_t c (dest, dest_sz);
- 
-     cmap *table = c.start_serialize<cmap> ();
-     if (unlikely (!c.extend_min (*table)))
-     {
-       return false;
-     }
- 
--    table->version.set (0);
-+    table->version = 0;
- 
--    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ 3)))
--      return false;
-+    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ cmap_subset_plan.format12_groups ? 3 : 2))) return false;
- 
-     // TODO(grieger): Convert the below to a for loop
- 
-     // Format 4, Plat 0 Encoding Record
-     EncodingRecord &format4_plat0_rec = table->encodingRecord[0];
--    format4_plat0_rec.platformID.set (0); // Unicode
--    format4_plat0_rec.encodingID.set (3);
-+    format4_plat0_rec.platformID = 0; // Unicode
-+    format4_plat0_rec.encodingID = 3;
- 
-     // Format 4, Plat 3 Encoding Record
-     EncodingRecord &format4_plat3_rec = table->encodingRecord[1];
--    format4_plat3_rec.platformID.set (3); // Windows
--    format4_plat3_rec.encodingID.set (1); // Unicode BMP
-+    format4_plat3_rec.platformID = 3; // Windows
-+    format4_plat3_rec.encodingID = 1; // Unicode BMP
- 
-     // Format 12 Encoding Record
--    EncodingRecord &format12_rec = table->encodingRecord[2];
--    format12_rec.platformID.set (3); // Windows
--    format12_rec.encodingID.set (10); // Unicode UCS-4
-+    if (cmap_subset_plan.format12_groups)
-+    {
-+      EncodingRecord &format12_rec = table->encodingRecord[2];
-+      format12_rec.platformID = 3; // Windows
-+      format12_rec.encodingID = 10; // Unicode UCS-4
-+    }
- 
-     // Write out format 4 sub table
-     {
-       CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table);
--      format4_plat3_rec.subtable.set (format4_plat0_rec.subtable);
--      subtable.u.format.set (4);
-+      format4_plat3_rec.subtable = (unsigned int) format4_plat0_rec.subtable;
-+      subtable.u.format = 4;
- 
-       CmapSubtableFormat4 &format4 = subtable.u.format4;
-       if (unlikely (!format4.serialize (&c, plan, cmap_subset_plan.format4_segments)))
- 	return false;
-     }
- 
-     // Write out format 12 sub table.
-+    if (cmap_subset_plan.format12_groups)
-     {
-+      EncodingRecord &format12_rec = table->encodingRecord[2];
-       CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
--      subtable.u.format.set (12);
-+      subtable.u.format = 12;
- 
-       CmapSubtableFormat12 &format12 = subtable.u.format12;
-       if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
- 	return false;
-     }
- 
-     c.end_serialize ();
- 
-@@ -1091,28 +1096,28 @@ struct cmap
-     }
- 
-     protected:
-     typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
- 					      hb_codepoint_t codepoint,
- 					      hb_codepoint_t *glyph);
- 
-     template <typename Type>
--    static bool get_glyph_from (const void *obj,
--				hb_codepoint_t codepoint,
--				hb_codepoint_t *glyph)
-+    HB_INTERNAL static bool get_glyph_from (const void *obj,
-+					    hb_codepoint_t codepoint,
-+					    hb_codepoint_t *glyph)
-     {
-       const Type *typed_obj = (const Type *) obj;
-       return typed_obj->get_glyph (codepoint, glyph);
-     }
- 
-     template <typename Type>
--    static bool get_glyph_from_symbol (const void *obj,
--					      hb_codepoint_t codepoint,
--					      hb_codepoint_t *glyph)
-+    HB_INTERNAL static bool get_glyph_from_symbol (const void *obj,
-+						   hb_codepoint_t codepoint,
-+						   hb_codepoint_t *glyph)
-     {
-       const Type *typed_obj = (const Type *) obj;
-       if (likely (typed_obj->get_glyph (codepoint, glyph)))
- 	return true;
- 
-       if (codepoint <= 0x00FFu)
-       {
- 	/* For symbol-encoded OpenType fonts, we duplicate the
-@@ -1139,26 +1144,38 @@ struct cmap
-   };
- 
-   protected:
- 
-   const CmapSubtable *find_subtable (unsigned int platform_id,
- 				     unsigned int encoding_id) const
-   {
-     EncodingRecord key;
--    key.platformID.set (platform_id);
--    key.encodingID.set (encoding_id);
-+    key.platformID = platform_id;
-+    key.encodingID = encoding_id;
- 
-     const EncodingRecord &result = encodingRecord.bsearch (key);
-     if (!result.subtable)
-       return nullptr;
- 
-     return &(this+result.subtable);
-   }
- 
-+  bool find_subtable (unsigned format) const
-+  {
-+    auto it =
-+    + hb_iter (encodingRecord)
-+    | hb_map (&EncodingRecord::subtable)
-+    | hb_map (hb_add (this))
-+    | hb_filter ([&] (const CmapSubtable& _) { return _.u.format == format; })
-+    ;
-+
-+    return it.len ();
-+  }
-+
-   public:
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  likely (version == 0) &&
- 		  encodingRecord.sanitize (c, this));
-diff --git a/gfx/harfbuzz/src/hb-ot-color-cbdt-table.hh b/gfx/harfbuzz/src/hb-ot-color-cbdt-table.hh
---- a/gfx/harfbuzz/src/hb-ot-color-cbdt-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-color-cbdt-table.hh
-@@ -139,17 +139,17 @@ struct IndexSubtableFormat1Or3
-       return false;
- 
-     *offset = header.imageDataOffset + offsetArrayZ[idx];
-     *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx];
-     return true;
-   }
- 
-   IndexSubtableHeader	header;
--  UnsizedArrayOf<Offset<OffsetType> >
-+  UnsizedArrayOf<Offset<OffsetType>>
-  			offsetArrayZ;
-   public:
-   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
- };
- 
- struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<HBUINT32> {};
- struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<HBUINT16> {};
- 
-@@ -344,25 +344,25 @@ struct CBLC
- 
-   protected:
-   const BitmapSizeTable &choose_strike (hb_font_t *font) const
-   {
-     unsigned count = sizeTables.len;
-     if (unlikely (!count))
-       return Null(BitmapSizeTable);
- 
--    unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
-+    unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
-     if (!requested_ppem)
-       requested_ppem = 1<<30; /* Choose largest strike. */
-     unsigned int best_i = 0;
--    unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY);
-+    unsigned int best_ppem = hb_max (sizeTables[0].ppemX, sizeTables[0].ppemY);
- 
-     for (unsigned int i = 1; i < count; i++)
-     {
--      unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY);
-+      unsigned int ppem = hb_max (sizeTables[i].ppemX, sizeTables[i].ppemY);
-       if ((requested_ppem <= ppem && ppem < best_ppem) ||
- 	  (requested_ppem > best_ppem && ppem > best_ppem))
-       {
- 	best_i = i;
- 	best_ppem = ppem;
-       }
-     }
- 
-@@ -437,22 +437,22 @@ struct CBDT
- 	  }
- 	  default:
- 	    // TODO: Support other image formats.
- 	    return false;
- 	}
-       }
- 
-       /* Convert to font units. */
--      double x_scale = upem / (double) strike.ppemX;
--      double y_scale = upem / (double) strike.ppemY;
--      extents->x_bearing = round (extents->x_bearing * x_scale);
--      extents->y_bearing = round (extents->y_bearing * y_scale);
--      extents->width = round (extents->width * x_scale);
--      extents->height = round (extents->height * y_scale);
-+      float x_scale = upem / (float) strike.ppemX;
-+      float y_scale = upem / (float) strike.ppemY;
-+      extents->x_bearing = roundf (extents->x_bearing * x_scale);
-+      extents->y_bearing = roundf (extents->y_bearing * y_scale);
-+      extents->width = roundf (extents->width * x_scale);
-+      extents->height = roundf (extents->height * y_scale);
- 
-       return true;
-     }
- 
-     hb_blob_t* reference_png (hb_font_t      *font,
- 				     hb_codepoint_t  glyph) const
-     {
-       const void *base;
-diff --git a/gfx/harfbuzz/src/hb-ot-color-colr-table.hh b/gfx/harfbuzz/src/hb-ot-color-colr-table.hh
---- a/gfx/harfbuzz/src/hb-ot-color-colr-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-color-colr-table.hh
-@@ -120,19 +120,19 @@ struct COLR
-     return_trace (likely (c->check_struct (this) &&
- 			  (this+baseGlyphsZ).sanitize (c, numBaseGlyphs) &&
- 			  (this+layersZ).sanitize (c, numLayers)));
-   }
- 
-   protected:
-   HBUINT16	version;	/* Table version number (starts at 0). */
-   HBUINT16	numBaseGlyphs;	/* Number of Base Glyph Records. */
--  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord> >
-+  LNNOffsetTo<SortedUnsizedArrayOf<BaseGlyphRecord>>
- 		baseGlyphsZ;	/* Offset to Base Glyph records. */
--  LNNOffsetTo<UnsizedArrayOf<LayerRecord> >
-+  LNNOffsetTo<UnsizedArrayOf<LayerRecord>>
- 		layersZ;	/* Offset to Layer Records. */
-   HBUINT16	numLayers;	/* Number of Layer Records. */
-   public:
-   DEFINE_SIZE_STATIC (14);
- };
- 
- } /* namespace OT */
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-color-cpal-table.hh b/gfx/harfbuzz/src/hb-ot-color-cpal-table.hh
---- a/gfx/harfbuzz/src/hb-ot-color-cpal-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-color-cpal-table.hh
-@@ -82,25 +82,25 @@ struct CPALV1Tail
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  (!paletteFlagsZ  || (base+paletteFlagsZ).sanitize (c, palette_count)) &&
- 		  (!paletteLabelsZ || (base+paletteLabelsZ).sanitize (c, palette_count)) &&
- 		  (!colorLabelsZ   || (base+colorLabelsZ).sanitize (c, color_count)));
-   }
- 
-   protected:
--  LNNOffsetTo<UnsizedArrayOf<HBUINT32> >
-+  LNNOffsetTo<UnsizedArrayOf<HBUINT32>>
- 		paletteFlagsZ;		/* Offset from the beginning of CPAL table to
- 					 * the Palette Type Array. Set to 0 if no array
- 					 * is provided. */
--  LNNOffsetTo<UnsizedArrayOf<NameID> >
-+  LNNOffsetTo<UnsizedArrayOf<NameID>>
- 		paletteLabelsZ;		/* Offset from the beginning of CPAL table to
- 					 * the palette labels array. Set to 0 if no
- 					 * array is provided. */
--  LNNOffsetTo<UnsizedArrayOf<NameID> >
-+  LNNOffsetTo<UnsizedArrayOf<NameID>>
- 		colorLabelsZ;		/* Offset from the beginning of CPAL table to
- 					 * the color labels array. Set to 0
- 					 * if no array is provided. */
-   public:
-   DEFINE_SIZE_STATIC (12);
- };
- 
- typedef HBUINT32 BGRAColor;
-@@ -139,17 +139,17 @@ struct CPAL
-     unsigned int start_index = colorRecordIndicesZ[palette_index];
-     hb_array_t<const BGRAColor> all_colors ((this+colorRecordsZ).arrayZ, numColorRecords);
-     hb_array_t<const BGRAColor> palette_colors = all_colors.sub_array (start_index,
- 								       numColors);
-     if (color_count)
-     {
-       hb_array_t<const BGRAColor> segment_colors = palette_colors.sub_array (start_offset, *color_count);
-       /* Always return numColors colors per palette even if it has out-of-bounds start index. */
--      unsigned int count = MIN<unsigned int> (MAX<int> (numColors - start_offset, 0), *color_count);
-+      unsigned int count = hb_min ((unsigned) hb_max ((int) (numColors - start_offset), 0), *color_count);
-       *color_count = count;
-       for (unsigned int i = 0; i < count; i++)
-         colors[i] = segment_colors[i]; /* Bound-checked read. */
-     }
-     return numColors;
-   }
- 
-   private:
-@@ -171,17 +171,17 @@ struct CPAL
- 
-   protected:
-   HBUINT16	version;		/* Table version number */
-   /* Version 0 */
-   HBUINT16	numColors;		/* Number of colors in each palette. */
-   HBUINT16	numPalettes;		/* Number of palettes in the table. */
-   HBUINT16	numColorRecords;	/* Total number of color records, combined for
- 					 * all palettes. */
--  LNNOffsetTo<UnsizedArrayOf<BGRAColor> >
-+  LNNOffsetTo<UnsizedArrayOf<BGRAColor>>
- 		colorRecordsZ;		/* Offset from the beginning of CPAL table to
- 					 * the first ColorRecord. */
-   UnsizedArrayOf<HBUINT16>
- 		colorRecordIndicesZ;	/* Index of each palette’s first color record in
- 					 * the combined color record array. */
- /*CPALV1Tail	v1;*/
-   public:
-   DEFINE_SIZE_ARRAY (12, colorRecordIndicesZ);
-diff --git a/gfx/harfbuzz/src/hb-ot-color-sbix-table.hh b/gfx/harfbuzz/src/hb-ot-color-sbix-table.hh
---- a/gfx/harfbuzz/src/hb-ot-color-sbix-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-color-sbix-table.hh
-@@ -116,17 +116,17 @@ struct SBIXStrike
-     return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
-   }
- 
-   public:
-   HBUINT16	ppem;		/* The PPEM size for which this strike was designed. */
-   HBUINT16	resolution;	/* The device pixel density (in PPI) for which this
- 				 * strike was designed. (E.g., 96 PPI, 192 PPI.) */
-   protected:
--  UnsizedArrayOf<LOffsetTo<SBIXGlyph> >
-+  UnsizedArrayOf<LOffsetTo<SBIXGlyph>>
- 		imageOffsetsZ;	/* Offset from the beginning of the strike data header
- 				 * to bitmap data for an individual glyph ID. */
-   public:
-   DEFINE_SIZE_STATIC (8);
- };
- 
- struct sbix
- {
-@@ -170,17 +170,17 @@ struct sbix
-     private:
- 
-     const SBIXStrike &choose_strike (hb_font_t *font) const
-     {
-       unsigned count = table->strikes.len;
-       if (unlikely (!count))
-         return Null(SBIXStrike);
- 
--      unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
-+      unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
-       if (!requested_ppem)
-         requested_ppem = 1<<30; /* Choose largest strike. */
-       /* TODO Add DPI sensitivity as well? */
-       unsigned int best_i = 0;
-       unsigned int best_ppem = table->get_strike (0).ppem;
- 
-       for (unsigned int i = 1; i < count; i++)
-       {
-@@ -237,21 +237,21 @@ struct sbix
-       extents->x_bearing = x_offset;
-       extents->y_bearing = y_offset;
-       extents->width     = png.IHDR.width;
-       extents->height    = png.IHDR.height;
- 
-       /* Convert to font units. */
-       if (strike_ppem)
-       {
--	double scale = font->face->get_upem () / (double) strike_ppem;
--	extents->x_bearing = round (extents->x_bearing * scale);
--	extents->y_bearing = round (extents->y_bearing * scale);
--	extents->width = round (extents->width * scale);
--	extents->height = round (extents->height * scale);
-+	float scale = font->face->get_upem () / (float) strike_ppem;
-+	extents->x_bearing = roundf (extents->x_bearing * scale);
-+	extents->y_bearing = roundf (extents->y_bearing * scale);
-+	extents->width = roundf (extents->width * scale);
-+	extents->height = roundf (extents->height * scale);
-       }
- 
-       hb_blob_destroy (blob);
- 
-       return strike_ppem;
-     }
- 
-     private:
-diff --git a/gfx/harfbuzz/src/hb-ot-color-svg-table.hh b/gfx/harfbuzz/src/hb-ot-color-svg-table.hh
---- a/gfx/harfbuzz/src/hb-ot-color-svg-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-color-svg-table.hh
-@@ -57,17 +57,17 @@ struct SVGDocumentIndexEntry
- 		  svgDoc.sanitize (c, base, svgDocLength));
-   }
- 
-   protected:
-   HBUINT16	startGlyphID;	/* The first glyph ID in the range described by
- 				 * this index entry. */
-   HBUINT16	endGlyphID;	/* The last glyph ID in the range described by
- 				 * this index entry. Must be >= startGlyphID. */
--  LNNOffsetTo<UnsizedArrayOf<HBUINT8> >
-+  LNNOffsetTo<UnsizedArrayOf<HBUINT8>>
- 		svgDoc;		/* Offset from the beginning of the SVG Document Index
- 				 * to an SVG document. Must be non-zero. */
-   HBUINT32	svgDocLength;	/* Length of the SVG document.
- 				 * Must be non-zero. */
-   public:
-   DEFINE_SIZE_STATIC (12);
- };
- 
-@@ -102,17 +102,17 @@ struct SVG
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this) &&
- 			  (this+svgDocEntries).sanitize_shallow (c)));
-   }
- 
-   protected:
-   HBUINT16	version;	/* Table version (starting at 0). */
--  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry> >
-+  LOffsetTo<SortedArrayOf<SVGDocumentIndexEntry>>
- 		svgDocEntries;	/* Offset (relative to the start of the SVG table) to the
- 				 * SVG Documents Index. Must be non-zero. */
- 				/* Array of SVG Document Index Entries. */
-   HBUINT32	reserved;	/* Set to 0. */
-   public:
-   DEFINE_SIZE_STATIC (10);
- };
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-color.cc b/gfx/harfbuzz/src/hb-ot-color.cc
---- a/gfx/harfbuzz/src/hb-ot-color.cc
-+++ b/gfx/harfbuzz/src/hb-ot-color.cc
-@@ -42,256 +42,315 @@
- 
- /**
-  * SECTION:hb-ot-color
-  * @title: hb-ot-color
-  * @short_description: OpenType Color Fonts
-  * @include: hb-ot.h
-  *
-  * Functions for fetching color-font information from OpenType font faces.
-+ *
-+ * HarfBuzz supports `COLR`/`CPAL`, `sbix`, `CBDT`, and `SVG` color fonts.
-  **/
- 
- 
- /*
-  * CPAL
-  */
- 
- 
- /**
-  * hb_ot_color_has_palettes:
-- * @face: a font face.
-+ * @face: #hb_face_t to work upon
-  *
-- * Returns: whether CPAL table is available.
-+ * Tests whether a face includes a `CPAL` color-palette table.
-+ *
-+ * Return value: true if data found, false otherwise
-  *
-  * Since: 2.1.0
-  */
- hb_bool_t
- hb_ot_color_has_palettes (hb_face_t *face)
- {
-+#ifdef HB_NO_COLOR
-+  return false;
-+#endif
-   return face->table.CPAL->has_data ();
- }
- 
- /**
-  * hb_ot_color_palette_get_count:
-- * @face: a font face.
-+ * @face: #hb_face_t to work upon
-  *
-- * Returns: the number of color palettes in @face, or zero if @face has
-- * no colors.
-+ * Fetches the number of color palettes in a face.
-+ *
-+ * Return value: the number of palettes found
-  *
-  * Since: 2.1.0
-  */
- unsigned int
- hb_ot_color_palette_get_count (hb_face_t *face)
- {
-+#ifdef HB_NO_COLOR
-+  return 0;
-+#endif
-   return face->table.CPAL->get_palette_count ();
- }
- 
- /**
-  * hb_ot_color_palette_get_name_id:
-- * @face:    a font face.
-- * @palette_index: the index of the color palette whose name is being requested.
-+ * @face: #hb_face_t to work upon
-+ * @palette_index: The index of the color palette 
-  *
-- * Retrieves the name id of a color palette. For example, a color font can
-- * have themed palettes like "Spring", "Summer", "Fall", and "Winter".
-+ * Fetches the `name` table Name ID that provides display names for
-+ * a `CPAL` color palette. 
-  *
-- * Returns: an identifier within @face's `name` table.
-+ * Palette display names can be generic (e.g., "Default") or provide
-+ * specific, themed names (e.g., "Spring", "Summer", "Fall", and "Winter").
-+ *
-+ * Return value: the Named ID found for the palette. 
-  * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
-  *
-  * Since: 2.1.0
-  */
- hb_ot_name_id_t
- hb_ot_color_palette_get_name_id (hb_face_t *face,
- 				 unsigned int palette_index)
- {
-+#ifdef HB_NO_COLOR
-+  return HB_OT_NAME_ID_INVALID;
-+#endif
-   return face->table.CPAL->get_palette_name_id (palette_index);
- }
- 
- /**
-  * hb_ot_color_palette_color_get_name_id:
-- * @face:        a font face.
-- * @color_index: palette entry index.
-+ * @face: #hb_face_t to work upon
-+ * @color_index: The index of the color
-  *
-- * Returns: Name ID associated with a palette entry, e.g. eye color
-+ * Fetches the `name` table Name ID that provides display names for
-+ * the specificed color in a face's `CPAL` color palette. 
-+ *
-+ * Display names can be generic (e.g., "Background") or specific
-+ * (e.g., "Eye color").
-+ *
-+ * Return value: the Name ID found for the color.
-  *
-  * Since: 2.1.0
-  */
- hb_ot_name_id_t
- hb_ot_color_palette_color_get_name_id (hb_face_t *face,
- 				       unsigned int color_index)
- {
-+#ifdef HB_NO_COLOR
-+  return HB_OT_NAME_ID_INVALID;
-+#endif
-   return face->table.CPAL->get_color_name_id (color_index);
- }
- 
- /**
-  * hb_ot_color_palette_get_flags:
-- * @face:          a font face
-- * @palette_index: the index of the color palette whose flags are being requested
-+ * @face: #hb_face_t to work upon
-+ * @palette_index: The index of the color palette
-  *
-- * Returns: the flags for the requested color palette.
-+ * Fetches the flags defined for a color palette.
-+ *
-+ * Return value: the #hb_ot_color_palette_flags_t of the requested color palette
-  *
-  * Since: 2.1.0
-  */
- hb_ot_color_palette_flags_t
- hb_ot_color_palette_get_flags (hb_face_t *face,
- 			       unsigned int palette_index)
- {
-+#ifdef HB_NO_COLOR
-+  return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
-+#endif
-   return face->table.CPAL->get_palette_flags (palette_index);
- }
- 
- /**
-  * hb_ot_color_palette_get_colors:
-- * @face:         a font face.
-- * @palette_index:the index of the color palette whose colors
-- *                are being requested.
-- * @start_offset: the index of the first color being requested.
-- * @color_count:  (inout) (optional): on input, how many colors
-- *                can be maximally stored into the @colors array;
-- *                on output, how many colors were actually stored.
-- * @colors: (array length=color_count) (out) (optional):
-- *                an array of #hb_color_t records. After calling
-- *                this function, @colors will be filled with
-- *                the palette colors. If @colors is NULL, the function
-- *                will just return the number of total colors
-- *                without storing any actual colors; this can be used
-- *                for allocating a buffer of suitable size before calling
-- *                hb_ot_color_palette_get_colors() a second time.
-+ * @face: #hb_face_t to work upon
-+ * @palette_index: the index of the color palette to query
-+ * @start_offset: offset of the first color to retrieve
-+ * @color_count: (inout) (optional): Input = the maximum number of colors to return;
-+ *               Output = the actual number of colors returned (may be zero)
-+ * @colors: (out) (array length=color_count) (nullable): The array of #hb_color_t records found
-  *
-- * Retrieves the colors in a color palette.
-+ * Fetches a list of the colors in a color palette.
-  *
-- * Returns: the total number of colors in the palette.
-+ * After calling this function, @colors will be filled with the palette
-+ * colors. If @colors is NULL, the function will just return the number
-+ * of total colors without storing any actual colors; this can be used
-+ * for allocating a buffer of suitable size before calling
-+ * hb_ot_color_palette_get_colors() a second time.
-+ *
-+ * Return value: the total number of colors in the palette
-  *
-  * Since: 2.1.0
-  */
- unsigned int
- hb_ot_color_palette_get_colors (hb_face_t     *face,
- 				unsigned int   palette_index,
- 				unsigned int   start_offset,
- 				unsigned int  *colors_count  /* IN/OUT.  May be NULL. */,
- 				hb_color_t    *colors        /* OUT.     May be NULL. */)
- {
-+#ifdef HB_NO_COLOR
-+  if (colors_count)
-+    *colors_count = 0;
-+  return 0;
-+#endif
-   return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors);
- }
- 
- 
- /*
-  * COLR
-  */
- 
- /**
-  * hb_ot_color_has_layers:
-- * @face: a font face.
-+ * @face: #hb_face_t to work upon
-  *
-- * Returns: whether COLR table is available.
-+ * Tests whether a face includes any `COLR` color layers.
-+ *
-+ * Return value: true if data found, false otherwise
-  *
-  * Since: 2.1.0
-  */
- hb_bool_t
- hb_ot_color_has_layers (hb_face_t *face)
- {
-+#ifdef HB_NO_COLOR
-+  return false;
-+#endif
-   return face->table.COLR->has_data ();
- }
- 
- /**
-  * hb_ot_color_glyph_get_layers:
-- * @face:         a font face.
-- * @glyph:        a layered color glyph id.
-- * @start_offset: starting offset of layers.
-- * @count:  (inout) (optional): gets number of layers available to be written on buffer
-- * 				and returns number of written layers.
-- * @layers: (array length=count) (out) (optional): layers buffer to buffer.
-+ * @face: #hb_face_t to work upon
-+ * @glyph: The glyph index to query
-+ * @start_offset: offset of the first layer to retrieve
-+ * @layer_count: (inout) (optional): Input = the maximum number of layers to return;
-+ *         Output = the actual number of layers returned (may be zero)
-+ * @layers: (out) (array length=layer_count) (nullable): The array of layers found
-  *
-- * Returns: Total number of layers a layered color glyph have.
-+ * Fetches a list of all color layers for the specified glyph index in the specified
-+ * face. The list returned will begin at the offset provided.
-+ *
-+ * Return value: Total number of layers available for the glyph index queried
-  *
-  * Since: 2.1.0
-  */
- unsigned int
- hb_ot_color_glyph_get_layers (hb_face_t           *face,
- 			      hb_codepoint_t       glyph,
- 			      unsigned int         start_offset,
--			      unsigned int        *count, /* IN/OUT.  May be NULL. */
-+			      unsigned int        *layer_count, /* IN/OUT.  May be NULL. */
- 			      hb_ot_color_layer_t *layers /* OUT.     May be NULL. */)
- {
--  return face->table.COLR->get_glyph_layers (glyph, start_offset, count, layers);
-+#ifdef HB_NO_COLOR
-+  if (layer_count)
-+    *layer_count = 0;
-+  return 0;
-+#endif
-+  return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers);
- }
- 
- 
- /*
-  * SVG
-  */
- 
- /**
-  * hb_ot_color_has_svg:
-- * @face: a font face.
-+ * @face: #hb_face_t to work upon.
-  *
-- * Check whether @face has SVG glyph images.
-+ * Tests whether a face includes any `SVG` glyph images.
-  *
-- * Returns true if available, false otherwise.
-+ * Return value: true if data found, false otherwise.
-  *
-  * Since: 2.1.0
-  */
- hb_bool_t
- hb_ot_color_has_svg (hb_face_t *face)
- {
-+#ifdef HB_NO_COLOR
-+  return false;
-+#endif
-   return face->table.SVG->has_data ();
- }
- 
- /**
-  * hb_ot_color_glyph_reference_svg:
-- * @face:  a font face.
-- * @glyph: a svg glyph index.
-+ * @face: #hb_face_t to work upon
-+ * @glyph: a svg glyph index
-  *
-- * Get SVG document for a glyph. The blob may be either plain text or gzip-encoded.
-+ * Fetches the SVG document for a glyph. The blob may be either plain text or gzip-encoded.
-  *
-- * Returns: (transfer full): respective svg blob of the glyph, if available.
-+ * Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available
-  *
-  * Since: 2.1.0
-  */
- hb_blob_t *
- hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
- {
-+#ifdef HB_NO_COLOR
-+  return hb_blob_get_empty ();
-+#endif
-   return face->table.SVG->reference_blob_for_glyph (glyph);
- }
- 
- 
- /*
-  * PNG: CBDT or sbix
-  */
- 
- /**
-  * hb_ot_color_has_png:
-- * @face: a font face.
-+ * @face: #hb_face_t to work upon
-  *
-- * Check whether @face has PNG glyph images (either CBDT or sbix tables).
-+ * Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables).
-  *
-- * Returns true if available, false otherwise.
-+ * Return value: true if data found, false otherwise
-  *
-  * Since: 2.1.0
-  */
- hb_bool_t
- hb_ot_color_has_png (hb_face_t *face)
- {
-+#ifdef HB_NO_COLOR
-+  return false;
-+#endif
-   return face->table.CBDT->has_data () || face->table.sbix->has_data ();
- }
- 
- /**
-  * hb_ot_color_glyph_reference_png:
-- * @font:  a font object, not face. upem should be set on
-- * 	   that font object if one wants to get optimal png blob, otherwise
-- * 	   return the biggest one
-- * @glyph: a glyph index.
-+ * @font: #hb_font_t to work upon
-+ * @glyph: a glyph index
-  *
-- * Get PNG image for a glyph.
-+ * Fetches the PNG image for a glyph. This function takes a font object, not a face object,
-+ * as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font
-+ * object. If UPEM is unset, the blob returned will be the largest PNG available.
-  *
-- * Returns: (transfer full): respective PNG blob of the glyph, if available.
-+ * Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available
-  *
-  * Since: 2.1.0
-  */
- hb_blob_t *
- hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t  glyph)
- {
-+#ifdef HB_NO_COLOR
-+  return hb_blob_get_empty ();
-+#endif
-+
-   hb_blob_t *blob = hb_blob_get_empty ();
- 
-   if (font->face->table.sbix->has_data ())
-     blob = font->face->table.sbix->reference_png (font, glyph, nullptr, nullptr, nullptr);
- 
-   if (!blob->length && font->face->table.CBDT->has_data ())
-     blob = font->face->table.CBDT->reference_png (font, glyph);
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-color.h b/gfx/harfbuzz/src/hb-ot-color.h
---- a/gfx/harfbuzz/src/hb-ot-color.h
-+++ b/gfx/harfbuzz/src/hb-ot-color.h
-@@ -54,21 +54,21 @@ hb_ot_color_palette_get_name_id (hb_face
- 				 unsigned int palette_index);
- 
- HB_EXTERN hb_ot_name_id_t
- hb_ot_color_palette_color_get_name_id (hb_face_t *face,
- 				       unsigned int color_index);
- 
- /**
-  * hb_ot_color_palette_flags_t:
-- * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special
-+ * @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: Default indicating that there is nothing special
-  *   to note about a color palette.
-- * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: flag indicating that the color
-+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND: Flag indicating that the color
-  *   palette is appropriate to use when displaying the font on a light background such as white.
-- * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: flag indicating that the color
-+ * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: Flag indicating that the color
-  *   palette is appropriate to use when displaying the font on a dark background such as black.
-  *
-  * Since: 2.1.0
-  */
- typedef enum { /*< flags >*/
-   HB_OT_COLOR_PALETTE_FLAG_DEFAULT			= 0x00000000u,
-   HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND	= 0x00000001u,
-   HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND	= 0x00000002u
-@@ -105,17 +105,17 @@ typedef struct hb_ot_color_layer_t
-   hb_codepoint_t glyph;
-   unsigned int   color_index;
- } hb_ot_color_layer_t;
- 
- HB_EXTERN unsigned int
- hb_ot_color_glyph_get_layers (hb_face_t           *face,
- 			      hb_codepoint_t       glyph,
- 			      unsigned int         start_offset,
--			      unsigned int        *count, /* IN/OUT.  May be NULL. */
-+			      unsigned int        *layer_count, /* IN/OUT.  May be NULL. */
- 			      hb_ot_color_layer_t *layers /* OUT.     May be NULL. */);
- 
- /*
-  * SVG
-  */
- 
- HB_EXTERN hb_bool_t
- hb_ot_color_has_svg (hb_face_t *face);
-diff --git a/gfx/harfbuzz/src/hb-ot-deprecated.h b/gfx/harfbuzz/src/hb-ot-deprecated.h
---- a/gfx/harfbuzz/src/hb-ot-deprecated.h
-+++ b/gfx/harfbuzz/src/hb-ot-deprecated.h
-@@ -35,16 +35,20 @@
- #include "hb-ot-name.h"
- 
- 
- HB_BEGIN_DECLS
- 
- #ifndef HB_DISABLE_DEPRECATED
- 
- 
-+/* https://github.com/harfbuzz/harfbuzz/issues/1734 */
-+#define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER
-+
-+
- /* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
- HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
- hb_ot_layout_table_choose_script (hb_face_t      *face,
- 				  hb_tag_t        table_tag,
- 				  const hb_tag_t *script_tags,
- 				  unsigned int   *script_index,
- 				  hb_tag_t       *chosen_script);
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-font.cc b/gfx/harfbuzz/src/hb-ot-font.cc
---- a/gfx/harfbuzz/src/hb-ot-font.cc
-+++ b/gfx/harfbuzz/src/hb-ot-font.cc
-@@ -175,25 +175,30 @@ hb_ot_get_glyph_v_origin (hb_font_t *fon
- static hb_bool_t
- hb_ot_get_glyph_extents (hb_font_t *font,
- 			 void *font_data,
- 			 hb_codepoint_t glyph,
- 			 hb_glyph_extents_t *extents,
- 			 void *user_data HB_UNUSED)
- {
-   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
--  bool ret = ot_face->sbix->get_extents (font, glyph, extents);
--  if (!ret)
--    ret = ot_face->glyf->get_extents (glyph, extents);
--  if (!ret)
--    ret = ot_face->cff1->get_extents (glyph, extents);
--  if (!ret)
--    ret = ot_face->cff2->get_extents (font, glyph, extents);
--  if (!ret)
--    ret = ot_face->CBDT->get_extents (font, glyph, extents);
-+  bool ret = false;
-+
-+#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
-+  if (!ret) ret = ot_face->sbix->get_extents (font, glyph, extents);
-+#endif
-+  if (!ret) ret = ot_face->glyf->get_extents (glyph, extents);
-+#ifndef HB_NO_OT_FONT_CFF
-+  if (!ret) ret = ot_face->cff1->get_extents (glyph, extents);
-+  if (!ret) ret = ot_face->cff2->get_extents (font, glyph, extents);
-+#endif
-+#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
-+  if (!ret) ret = ot_face->CBDT->get_extents (font, glyph, extents);
-+#endif
-+
-   // TODO Hook up side-bearings variations.
-   extents->x_bearing = font->em_scale_x (extents->x_bearing);
-   extents->y_bearing = font->em_scale_y (extents->y_bearing);
-   extents->width     = font->em_scale_x (extents->width);
-   extents->height    = font->em_scale_y (extents->height);
-   return ret;
- }
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-glyf-table.hh b/gfx/harfbuzz/src/hb-ot-glyf-table.hh
---- a/gfx/harfbuzz/src/hb-ot-glyf-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-glyf-table.hh
-@@ -16,25 +16,24 @@
-  * DAMAGE.
-  *
-  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-- * Google Author(s): Behdad Esfahbod
-+ * Google Author(s): Behdad Esfahbod, Garret Rieger, Roderick Sheeter
-  */
- 
- #ifndef HB_OT_GLYF_TABLE_HH
- #define HB_OT_GLYF_TABLE_HH
- 
- #include "hb-open-type.hh"
- #include "hb-ot-head-table.hh"
--#include "hb-subset-glyf.hh"
- 
- namespace OT {
- 
- 
- /*
-  * loca -- Index to Location
-  * https://docs.microsoft.com/en-us/typography/opentype/spec/loca
-  */
-@@ -53,17 +52,17 @@ struct loca
-     return_trace (true);
-   }
- 
-   protected:
-   UnsizedArrayOf<HBUINT8>	dataZ;		/* Location data. */
-   public:
-   DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
- 			* check the size externally, allow Null() object of it by
--			* defining it MIN() instead. */
-+			* defining it _MIN instead. */
- };
- 
- 
- /*
-  * glyf -- TrueType Glyph Data
-  * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
-  */
- #define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
-@@ -76,48 +75,194 @@ struct glyf
-   bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
-   {
-     TRACE_SANITIZE (this);
-     /* We don't check for anything specific here.  The users of the
-      * struct do all the hard work... */
-     return_trace (true);
-   }
- 
--  bool subset (hb_subset_plan_t *plan) const
-+  template<typename Iterator,
-+	   hb_requires (hb_is_source_of (Iterator, unsigned int))>
-+  static bool
-+  _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets)
-+  {
-+    unsigned max_offset = + padded_offsets | hb_reduce(hb_add, 0);
-+    unsigned num_offsets = padded_offsets.len () + 1;
-+    bool use_short_loca = max_offset < 0x1FFFF;
-+    unsigned entry_size = use_short_loca ? 2 : 4;
-+    char *loca_prime_data = (char *) calloc (entry_size, num_offsets);
-+
-+    if (unlikely (!loca_prime_data)) return false;
-+
-+    DEBUG_MSG(SUBSET, nullptr, "loca entry_size %d num_offsets %d max_offset %d size %d", entry_size, num_offsets, max_offset, entry_size * num_offsets);
-+
-+    if (use_short_loca)
-+      _write_loca (padded_offsets, 1, hb_array ((HBUINT16*) loca_prime_data, num_offsets));
-+    else
-+      _write_loca (padded_offsets, 0, hb_array ((HBUINT32*) loca_prime_data, num_offsets));
-+
-+    hb_blob_t * loca_blob = hb_blob_create (loca_prime_data,
-+					    entry_size * num_offsets,
-+					    HB_MEMORY_MODE_WRITABLE,
-+					    loca_prime_data,
-+					    free);
-+
-+    bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
-+		  && _add_head_and_set_loca_version(plan, use_short_loca);
-+
-+    hb_blob_destroy (loca_blob);
-+    return result;
-+  }
-+
-+  template<typename IteratorIn, typename IteratorOut,
-+	   hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
-+	   hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
-+  static void
-+  _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest)
-   {
--    hb_blob_t *glyf_prime = nullptr;
--    hb_blob_t *loca_prime = nullptr;
-+    unsigned int offset = 0;
-+    dest << 0;
-+    + it
-+    | hb_map ([=, &offset] (unsigned int padded_size) {
-+      offset += padded_size;
-+      DEBUG_MSG(SUBSET, nullptr, "loca entry offset %d", offset);
-+      return offset >> right_shift;
-+    })
-+    | hb_sink (dest)
-+    ;
-+  }
-+
-+  // requires source of SubsetGlyph complains the identifier isn't declared
-+  template <typename Iterator>
-+  bool serialize(hb_serialize_context_t *c,
-+		 Iterator it,
-+		 const hb_subset_plan_t *plan)
-+  {
-+    TRACE_SERIALIZE (this);
-+
-+    + it
-+    | hb_apply ([=] (const SubsetGlyph& _) { _.serialize (c, plan); })
-+    ;
-+
-+    return_trace (true);
-+  }
-+
-+  bool subset (hb_subset_context_t *c) const
-+  {
-+    TRACE_SUBSET (this);
-+
-+    glyf *glyf_prime = c->serializer->start_embed <glyf> ();
-+    if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
-+
-+    // Byte region(s) per glyph to output
-+    // unpadded, hints removed if so requested
-+    // If we fail to process a glyph we produce an empty (0-length) glyph
-+    hb_vector_t<SubsetGlyph> glyphs;
-+    _populate_subset_glyphs (c->plan, &glyphs);
-+
-+    glyf_prime->serialize (c->serializer, hb_iter (glyphs), c->plan);
- 
--    bool success = true;
--    bool use_short_loca = false;
--    if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) {
--      success = success && plan->add_table (HB_OT_TAG_glyf, glyf_prime);
--      success = success && plan->add_table (HB_OT_TAG_loca, loca_prime);
--      success = success && _add_head_and_set_loca_version (plan, use_short_loca);
--    } else {
--      success = false;
-+    auto padded_offsets =
-+    + hb_iter (glyphs)
-+    | hb_map (&SubsetGlyph::padded_size)
-+    ;
-+
-+    if (c->serializer->in_error ()) return_trace (false);
-+    return_trace (c->serializer->check_success (_add_loca_and_head (c->plan, padded_offsets)));
-+  }
-+
-+  template <typename SubsetGlyph>
-+  void
-+  _populate_subset_glyphs (const hb_subset_plan_t * plan,
-+			   hb_vector_t<SubsetGlyph> * glyphs /* OUT */) const
-+  {
-+    OT::glyf::accelerator_t glyf;
-+    glyf.init (plan->source);
-+
-+    + hb_range (plan->num_output_glyphs ())
-+    | hb_map ([&] (hb_codepoint_t new_gid) {
-+      SubsetGlyph subset_glyph;
-+      subset_glyph.new_gid = new_gid;
-+
-+      // should never fail: all old gids should be mapped
-+      if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) return subset_glyph;
-+
-+      subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this, subset_glyph.old_gid);
-+      if (plan->drop_hints) subset_glyph.drop_hints (glyf);
-+      else subset_glyph.dest_start = subset_glyph.source_glyph;
-+
-+      return subset_glyph;
-+    })
-+    | hb_sink (glyphs)
-+    ;
-+
-+    glyf.fini();
-+  }
-+
-+  static void
-+  _fix_component_gids (const hb_subset_plan_t *plan,
-+		       hb_bytes_t glyph)
-+  {
-+    OT::glyf::CompositeGlyphHeader::Iterator iterator;
-+    if (OT::glyf::CompositeGlyphHeader::get_iterator (&glyph,
-+						      glyph.length,
-+						      &iterator))
-+    {
-+      do
-+      {
-+	hb_codepoint_t new_gid;
-+	if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
-+					&new_gid))
-+	  continue;
-+	((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex = new_gid;
-+      } while (iterator.move_to_next ());
-     }
--    hb_blob_destroy (loca_prime);
--    hb_blob_destroy (glyf_prime);
-+  }
-+
-+  static void
-+  _zero_instruction_length (hb_bytes_t glyph)
-+  {
-+    const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (&glyph, 0);
-+    int16_t num_contours = (int16_t) glyph_header.numberOfContours;
-+    if (num_contours <= 0) return;  // only for simple glyphs
-+
-+    const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (&glyph, GlyphHeader::static_size + 2 * num_contours);
-+    (HBUINT16 &) instruction_length = 0;
-+  }
- 
--    return success;
--  }
-+  static bool _remove_composite_instruction_flag (hb_bytes_t glyph)
-+  {
-+    const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (&glyph, 0);
-+    if (glyph_header.numberOfContours >= 0) return true;  // only for composites
-+
-+    /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
-+    OT::glyf::CompositeGlyphHeader::Iterator composite_it;
-+    if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false;
-+    const OT::glyf::CompositeGlyphHeader *composite_header;
-+    do {
-+      composite_header = composite_it.current;
-+      OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&composite_header->flags);
-+      *flags = (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS;
-+    } while (composite_it.move_to_next ());
-+    return true;
-+}
- 
-   static bool
-   _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
-   {
-     hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
-     hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
-     hb_blob_destroy (head_blob);
- 
-     if (unlikely (!head_prime_blob))
-       return false;
- 
-     head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
--    head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
-+    head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
-     bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
- 
-     hb_blob_destroy (head_prime_blob);
-     return success;
-   }
- 
-   struct GlyphHeader
-   {
-@@ -166,16 +311,17 @@ struct glyf
-       // Two x 16 bit (xscale, yscale)
-       else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
-       // Four x 16 bit (xscale, scale01, scale10, yscale)
-       else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
- 
-       return size;
-     }
- 
-+    // TODO rewrite using new iterator framework if possible
-     struct Iterator
-     {
-       const char *glyph_start;
-       const char *glyph_end;
-       const CompositeGlyphHeader *current;
- 
-       bool move_to_next ()
-       {
-@@ -236,17 +382,17 @@ struct glyf
-       if (head.indexToLocFormat > 1 || head.glyphDataFormat != 0)
- 	/* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
- 	return;
-       short_offset = 0 == head.indexToLocFormat;
- 
-       loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
-       glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
- 
--      num_glyphs = MAX (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
-+      num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
-     }
- 
-     void fini ()
-     {
-       loca_table.destroy ();
-       glyf_table.destroy ();
-     }
- 
-@@ -278,17 +424,17 @@ struct glyf
-       FLAG_X_SAME = 0x10,
-       FLAG_Y_SAME = 0x20,
-       FLAG_RESERVED1 = 0x40,
-       FLAG_RESERVED2 = 0x80
-     };
- 
-     /* based on FontTools _g_l_y_f.py::trim */
-     bool remove_padding (unsigned int start_offset,
--				unsigned int *end_offset) const
-+			 unsigned int *end_offset) const
-     {
-       if (*end_offset - start_offset < GlyphHeader::static_size) return true;
- 
-       const char *glyph = ((const char *) glyf_table) + start_offset;
-       const char * const glyph_end = glyph + (*end_offset - start_offset);
-       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyph, 0);
-       int16_t num_contours = (int16_t) glyph_header.numberOfContours;
- 
-@@ -376,107 +522,207 @@ struct glyf
-       }
- 
-       if (*start_offset > *end_offset || *end_offset > glyf_table.get_length ())
- 	return false;
- 
-       return true;
-     }
- 
--    bool get_instruction_offsets (unsigned int start_offset,
--				  unsigned int end_offset,
--				  unsigned int *instruction_start /* OUT */,
--				  unsigned int *instruction_end /* OUT */) const
-+    bool get_instruction_length (hb_bytes_t glyph,
-+				 unsigned int * length /* OUT */) const
-     {
--      if (end_offset - start_offset < GlyphHeader::static_size)
-+      /* Empty glyph; no instructions. */
-+      if (glyph.length < GlyphHeader::static_size)
-       {
--	*instruction_start = 0;
--	*instruction_end = 0;
--	return true; /* Empty glyph; no instructions. */
-+	*length = 0;
-+	// only 0 byte glyphs are healthy when missing GlyphHeader
-+	return glyph.length == 0;
-       }
--      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
-+      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (&glyph, 0);
-       int16_t num_contours = (int16_t) glyph_header.numberOfContours;
-       if (num_contours < 0)
-       {
-+	unsigned int start = glyph.length;
-+	unsigned int end = glyph.length;
-+	unsigned int glyph_offset = &glyph - glyf_table;
- 	CompositeGlyphHeader::Iterator composite_it;
--	if (unlikely (!CompositeGlyphHeader::get_iterator (
--	    (const char*) this->glyf_table + start_offset,
--	     end_offset - start_offset, &composite_it))) return false;
-+	if (unlikely (!CompositeGlyphHeader::get_iterator (&glyph, glyph.length, &composite_it))) return false;
- 	const CompositeGlyphHeader *last;
- 	do {
- 	  last = composite_it.current;
- 	} while (composite_it.move_to_next ());
- 
- 	if ((uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
--	  *instruction_start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size ();
--	else
--	  *instruction_start = end_offset;
--	*instruction_end = end_offset;
--	if (unlikely (*instruction_start > *instruction_end))
-+	  start = ((char *) last - (char *) glyf_table->dataZ.arrayZ) + last->get_size () - glyph_offset;
-+	if (unlikely (start > end))
- 	{
--	  DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset);
-+	  DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside %d byte buffer", start, glyph.length);
- 	  return false;
- 	}
-+	*length = end - start;
-       }
-       else
-       {
--	unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
--	if (unlikely (instruction_length_offset + 2 > end_offset))
-+	unsigned int instruction_length_offset = GlyphHeader::static_size + 2 * num_contours;
-+	if (unlikely (instruction_length_offset + 2 > glyph.length))
- 	{
- 	  DEBUG_MSG(SUBSET, nullptr, "Glyph size is too short, missing field instructionLength.");
- 	  return false;
- 	}
- 
--	const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
--	unsigned int start = instruction_length_offset + 2;
--	unsigned int end = start + (uint16_t) instruction_length;
--	if (unlikely (end > end_offset)) // Out of bounds of the current glyph
-+	const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (&glyph, instruction_length_offset);
-+	if (unlikely (instruction_length_offset + instruction_length > glyph.length)) // Out of bounds of the current glyph
- 	{
- 	  DEBUG_MSG(SUBSET, nullptr, "The instructions array overruns the glyph's boundaries.");
- 	  return false;
- 	}
--
--	*instruction_start = start;
--	*instruction_end = end;
-+	*length = (uint16_t) instruction_length;
-       }
-       return true;
-     }
- 
-     bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
-     {
-       unsigned int start_offset, end_offset;
-       if (!get_offsets (glyph, &start_offset, &end_offset))
- 	return false;
- 
-       if (end_offset - start_offset < GlyphHeader::static_size)
- 	return true; /* Empty glyph; zero extents. */
- 
-       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
- 
--      extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
--      extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
--      extents->width     = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
--      extents->height    = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
-+      extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax);
-+      extents->y_bearing = hb_max (glyph_header.yMin, glyph_header.yMax);
-+      extents->width     = hb_max (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
-+      extents->height    = hb_min (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
- 
-       return true;
-     }
- 
-+  hb_bytes_t bytes_for_glyph (const char * glyf, hb_codepoint_t gid)
-+  {
-+    unsigned int start_offset, end_offset;
-+    if (unlikely (!(get_offsets (gid, &start_offset, &end_offset) &&
-+      remove_padding (start_offset, &end_offset))))
-+    {
-+      DEBUG_MSG(SUBSET, nullptr, "Unable to get offset or remove padding for %d", gid);
-+      return hb_bytes_t ();
-+    }
-+    hb_bytes_t glyph = hb_bytes_t (glyf + start_offset, end_offset - start_offset);
-+    if (glyph.length == 0) return glyph;
-+    if (unlikely (glyph.length < GlyphHeader::static_size))
-+    {
-+      DEBUG_MSG(SUBSET, nullptr, "Glyph size smaller than minimum header %d", gid);
-+      return hb_bytes_t ();
-+    }
-+    return glyph;
-+  }
-+
-     private:
-     bool short_offset;
-     unsigned int num_glyphs;
-     hb_blob_ptr_t<loca> loca_table;
-     hb_blob_ptr_t<glyf> glyf_table;
-   };
- 
-+
-+  struct SubsetGlyph
-+  {
-+    hb_codepoint_t new_gid;
-+    hb_codepoint_t old_gid;
-+    hb_bytes_t source_glyph;
-+    hb_bytes_t dest_start;  // region of source_glyph to copy first
-+    hb_bytes_t dest_end;    // region of source_glyph to copy second
-+
-+
-+  bool serialize (hb_serialize_context_t *c,
-+		  const hb_subset_plan_t *plan) const
-+  {
-+    TRACE_SERIALIZE (this);
-+
-+    hb_bytes_t dest_glyph = dest_start.copy(c);
-+    dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy(c).length);
-+    unsigned int pad_length = padding ();
-+    DEBUG_MSG(SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length  + pad_length, pad_length);
-+
-+    HBUINT8 pad;
-+    pad = 0;
-+    while (pad_length > 0)
-+    {
-+      c->embed(pad);
-+      pad_length--;
-+    }
-+
-+    if (dest_glyph.length)
-+    {
-+      _fix_component_gids (plan, dest_glyph);
-+      if (plan->drop_hints)
-+      {
-+	_zero_instruction_length (dest_glyph);
-+	c->check_success (_remove_composite_instruction_flag (dest_glyph));
-+      }
-+    }
-+
-+    return_trace (true);
-+  }
-+
-+    void drop_hints (const OT::glyf::accelerator_t& glyf)
-+    {
-+      if (source_glyph.length == 0) return;
-+
-+      unsigned int instruction_length = 0;
-+      if (!glyf.get_instruction_length (source_glyph, &instruction_length))
-+      {
-+	 DEBUG_MSG(SUBSET, nullptr, "Unable to read instruction length for new_gid %d", new_gid);
-+	return ;
-+      }
-+
-+      const GlyphHeader& header = StructAtOffset<GlyphHeader> (&source_glyph, 0);
-+      int16_t num_contours = (int16_t) header.numberOfContours;
-+      DEBUG_MSG(SUBSET, nullptr, "new_gid %d (%d contours) drop %d instruction bytes from %d byte source glyph", new_gid, num_contours, instruction_length, source_glyph.length);
-+      if (num_contours < 0)
-+      {
-+	// composite, just chop instructions off the end
-+	dest_start = hb_bytes_t (&source_glyph, source_glyph.length - instruction_length);
-+      }
-+      else
-+      {
-+	// simple glyph
-+	dest_start = hb_bytes_t (&source_glyph, GlyphHeader::static_size + 2 * header.numberOfContours + 2);
-+	dest_end = hb_bytes_t (&source_glyph + dest_start.length + instruction_length,
-+			       source_glyph.length - dest_start.length - instruction_length);
-+DEBUG_MSG(SUBSET, nullptr, "source_len %d start len %d instruction_len %d end len %d", source_glyph.length, dest_start.length, instruction_length, dest_end.length);
-+      }
-+    }
-+
-+    unsigned int length () const
-+    {
-+      return dest_start.length + dest_end.length;
-+    }
-+
-+    // pad to 2 to ensure 2-byte loca will be ok
-+    unsigned int padding () const
-+    {
-+      return length () % 2;
-+    }
-+
-+    unsigned int padded_size () const
-+    {
-+      return length () + padding ();
-+    }
-+  };
-+
-   protected:
-   UnsizedArrayOf<HBUINT8>	dataZ;		/* Glyphs data. */
-   public:
-   DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
- 			* check the size externally, allow Null() object of it by
--			* defining it MIN() instead. */
-+			* defining it _MIN instead. */
- };
- 
- struct glyf_accelerator_t : glyf::accelerator_t {};
- 
- } /* namespace OT */
- 
- 
- #endif /* HB_OT_GLYF_TABLE_HH */
-diff --git a/gfx/harfbuzz/src/hb-ot-hdmx-table.hh b/gfx/harfbuzz/src/hb-ot-hdmx-table.hh
---- a/gfx/harfbuzz/src/hb-ot-hdmx-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-hdmx-table.hh
-@@ -36,81 +36,41 @@
- #define HB_OT_TAG_hdmx HB_TAG('h','d','m','x')
- 
- 
- namespace OT {
- 
- 
- struct DeviceRecord
- {
--  struct SubsetView
--  {
--    const DeviceRecord *source_device_record;
--    unsigned int sizeDeviceRecord;
--    hb_subset_plan_t *subset_plan;
--
--    void init (const DeviceRecord *source_device_record,
--	       unsigned int sizeDeviceRecord,
--	       hb_subset_plan_t   *subset_plan)
--    {
--      this->source_device_record = source_device_record;
--      this->sizeDeviceRecord = sizeDeviceRecord;
--      this->subset_plan = subset_plan;
--    }
--
--    unsigned int len () const
--    { return this->subset_plan->num_output_glyphs (); }
--
--    const HBUINT8* operator [] (unsigned int new_gid) const
--    {
--      if (unlikely (new_gid >= len ())) return nullptr;
--
--      hb_codepoint_t old_gid;
--      if (!this->subset_plan->old_gid_for_new_gid (new_gid, &old_gid))
--        return &Null(HBUINT8);
--
--      if (old_gid >= sizeDeviceRecord - DeviceRecord::min_size)
--        return nullptr;
--      return &(this->source_device_record->widthsZ[old_gid]);
--    }
--  };
--
--  static unsigned int get_size (unsigned int count)
-+  static unsigned int get_size (unsigned count)
-   { return hb_ceil_to_4 (min_size + count * HBUINT8::static_size); }
- 
--  bool serialize (hb_serialize_context_t *c, const SubsetView &subset_view)
-+  template<typename Iterator,
-+	   hb_requires (hb_is_iterator (Iterator))>
-+  bool serialize (hb_serialize_context_t *c, unsigned pixelSize, Iterator it)
-   {
-     TRACE_SERIALIZE (this);
- 
--    unsigned int size = get_size (subset_view.len ());
--    if (unlikely (!c->allocate_size<DeviceRecord> (size)))
--    {
--      DEBUG_MSG(SUBSET, nullptr, "Couldn't allocate enough space for DeviceRecord: %d.",
--		 size);
--      return_trace (false);
--    }
-+    unsigned length = it.len ();
- 
--    this->pixelSize.set (subset_view.source_device_record->pixelSize);
--    this->maxWidth.set (subset_view.source_device_record->maxWidth);
-+    if (unlikely (!c->extend (*this, length)))  return_trace (false);
- 
--    for (unsigned int i = 0; i < subset_view.len (); i++)
--    {
--      const HBUINT8 *width = subset_view[i];
--      if (!width)
--      {
--	DEBUG_MSG(SUBSET, nullptr, "HDMX width for new gid %d is missing.", i);
--	return_trace (false);
--      }
--      widthsZ[i].set (*width);
--    }
-+    this->pixelSize = pixelSize;
-+    this->maxWidth =
-+    + it
-+    | hb_reduce (hb_max, 0u);
-+
-+    + it
-+    | hb_sink (widthsZ.as_array (length));
- 
-     return_trace (true);
-   }
- 
--  bool sanitize (hb_sanitize_context_t *c, unsigned int sizeDeviceRecord) const
-+  bool sanitize (hb_sanitize_context_t *c, unsigned sizeDeviceRecord) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this) &&
- 			  c->check_range (this, sizeDeviceRecord)));
-   }
- 
-   HBUINT8			pixelSize;	/* Pixel size for following widths (as ppem). */
-   HBUINT8			maxWidth;	/* Maximum width. */
-@@ -130,72 +90,73 @@ struct hdmx
-   const DeviceRecord& operator [] (unsigned int i) const
-   {
-     /* XXX Null(DeviceRecord) is NOT safe as it's num-glyphs lengthed.
-      * https://github.com/harfbuzz/harfbuzz/issues/1300 */
-     if (unlikely (i >= numRecords)) return Null (DeviceRecord);
-     return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
-   }
- 
--  bool serialize (hb_serialize_context_t *c, const hdmx *source_hdmx, hb_subset_plan_t *plan)
-+  template<typename Iterator,
-+	   hb_requires (hb_is_iterator (Iterator))>
-+  bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
-   {
-     TRACE_SERIALIZE (this);
- 
-     if (unlikely (!c->extend_min ((*this))))  return_trace (false);
- 
--    this->version.set (source_hdmx->version);
--    this->numRecords.set (source_hdmx->numRecords);
--    this->sizeDeviceRecord.set (DeviceRecord::get_size (plan->num_output_glyphs ()));
-+    this->version = version;
-+    this->numRecords = it.len ();
-+    this->sizeDeviceRecord = DeviceRecord::get_size (it ? (*it).second.len () : 0);
-+
-+    + it
-+    | hb_apply ([c] (const hb_item_type<Iterator>& _) {
-+		  c->start_embed<DeviceRecord> ()->serialize (c, _.first, _.second);
-+		})
-+    ;
-+
-+    return_trace (c->successful);
-+  }
-+
-+
-+  bool subset (hb_subset_context_t *c) const
-+  {
-+    TRACE_SUBSET (this);
-+
-+    hdmx *hdmx_prime = c->serializer->start_embed <hdmx> ();
-+    if (unlikely (!hdmx_prime)) return_trace (false);
- 
--    for (unsigned int i = 0; i < source_hdmx->numRecords; i++)
--    {
--      DeviceRecord::SubsetView subset_view;
--      subset_view.init (&(*source_hdmx)[i], source_hdmx->sizeDeviceRecord, plan);
-+    auto it =
-+    + hb_range ((unsigned) numRecords)
-+    | hb_map ([c, this] (unsigned _)
-+	{
-+	  const DeviceRecord *device_record =
-+	    &StructAtOffset<DeviceRecord> (&firstDeviceRecord,
-+					   _ * sizeDeviceRecord);
-+	  auto row =
-+	    + hb_range (c->plan->num_output_glyphs ())
-+	    | hb_map (c->plan->reverse_glyph_map)
-+	    | hb_map ([=] (hb_codepoint_t _)
-+		      {
-+			if (c->plan->is_empty_glyph (_))
-+			  return Null(HBUINT8);
-+			return device_record->widthsZ.as_array (get_num_glyphs ()) [_];
-+		      })
-+	    ;
-+	  return hb_pair ((unsigned) device_record->pixelSize, +row);
-+	})
-+    ;
- 
--      if (!c->start_embed<DeviceRecord> ()->serialize (c, subset_view))
--	return_trace (false);
--    }
--
-+    hdmx_prime->serialize (c->serializer, version, it);
-     return_trace (true);
-   }
- 
--  static size_t get_subsetted_size (const hdmx *source_hdmx, hb_subset_plan_t *plan)
--  {
--    return min_size + source_hdmx->numRecords * DeviceRecord::get_size (plan->num_output_glyphs ());
--  }
--
--  bool subset (hb_subset_plan_t *plan) const
-+  unsigned get_num_glyphs () const
-   {
--    size_t dest_size = get_subsetted_size (this, plan);
--    hdmx *dest = (hdmx *) malloc (dest_size);
--    if (unlikely (!dest))
--    {
--      DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for hdmx subset output.", (unsigned long) dest_size);
--      return false;
--    }
--
--    hb_serialize_context_t c (dest, dest_size);
--    hdmx *hdmx_prime = c.start_serialize<hdmx> ();
--    if (!hdmx_prime || !hdmx_prime->serialize (&c, this, plan))
--    {
--      free (dest);
--      DEBUG_MSG(SUBSET, nullptr, "Failed to serialize write new hdmx.");
--      return false;
--    }
--    c.end_serialize ();
--
--    hb_blob_t *hdmx_prime_blob = hb_blob_create ((const char *) dest,
--						 dest_size,
--						 HB_MEMORY_MODE_READONLY,
--						 dest,
--						 free);
--    bool result = plan->add_table (HB_OT_TAG_hdmx, hdmx_prime_blob);
--    hb_blob_destroy (hdmx_prime_blob);
--
--    return result;
-+    return sizeDeviceRecord - DeviceRecord::min_size;
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  !hb_unsigned_mul_overflows (numRecords, sizeDeviceRecord) &&
- 		  sizeDeviceRecord >= DeviceRecord::min_size &&
-diff --git a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
---- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
-@@ -73,17 +73,17 @@ struct hmtxvmtx
-     hb_blob_destroy (src_blob);
- 
-     if (unlikely (!dest_blob)) {
-       return false;
-     }
- 
-     unsigned int length;
-     H *table = (H *) hb_blob_get_data (dest_blob, &length);
--    table->numberOfLongMetrics.set (num_hmetrics);
-+    table->numberOfLongMetrics = num_hmetrics;
- 
-     bool result = plan->add_table (H::tableTag, dest_blob);
-     hb_blob_destroy (dest_blob);
- 
-     return result;
-   }
- 
-   bool subset (hb_subset_plan_t *plan) const
-@@ -123,22 +123,22 @@ struct hmtxvmtx
-         // from the input font.
-         side_bearing = _mtx.get_side_bearing (old_gid);
-         advance = _mtx.get_advance (old_gid);
-       }
- 
-       bool has_advance = i < num_advances;
-       if (has_advance)
-       {
--        ((LongMetric *) dest_pos)->advance.set (advance);
--        ((LongMetric *) dest_pos)->sb.set (side_bearing);
-+        ((LongMetric *) dest_pos)->advance = advance;
-+        ((LongMetric *) dest_pos)->sb = side_bearing;
-       }
-       else
-       {
--        ((FWORD *) dest_pos)->set (side_bearing);
-+        *((FWORD *) dest_pos) = side_bearing;
-       }
-       dest_pos += (has_advance ? 4 : 2);
-     }
-     _mtx.fini ();
- 
-     // Amend header num hmetrics
-     if (failed || unlikely (!subset_update_header (plan, num_advances)))
-     {
-@@ -235,17 +235,17 @@ struct hmtxvmtx
- 	 * for this direction: return default advance.  Otherwise, it means that the
- 	 * glyph index is out of bound: return zero. */
- 	if (num_metrics)
- 	  return 0;
- 	else
- 	  return default_advance;
-       }
- 
--      return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance;
-+      return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance;
-     }
- 
-     unsigned int get_advance (hb_codepoint_t  glyph,
- 			      hb_font_t      *font) const
-     {
-       unsigned int advance = get_advance (glyph);
-       if (likely (glyph < num_metrics))
-       {
-diff --git a/gfx/harfbuzz/src/hb-ot-kern-table.hh b/gfx/harfbuzz/src/hb-ot-kern-table.hh
---- a/gfx/harfbuzz/src/hb-ot-kern-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-kern-table.hh
-@@ -42,19 +42,19 @@ namespace OT {
- 
- 
- template <typename KernSubTableHeader>
- struct KernSubTableFormat3
- {
-   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-   {
-     hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
--    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (kernValue).as_array (glyphCount);
--    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (leftClass).as_array (glyphCount);
--    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8> > (rightClass).as_array (leftClassCount * rightClassCount);
-+    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount);
-+    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount);
-+    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount);
- 
-     unsigned int leftC = leftClass[left];
-     unsigned int rightC = rightClass[right];
-     if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
-       return 0;
-     unsigned int i = leftC * rightClassCount + rightC;
-     return kernValue[kernIndex[i]];
-   }
-@@ -116,26 +116,30 @@ struct KernSubTable
-   {
-     switch (get_type ()) {
-     /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
-     case 0: return u.format0.get_kerning (left, right);
-     default:return 0;
-     }
-   }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     unsigned int subtable_type = get_type ();
-     TRACE_DISPATCH (this, subtable_type);
-     switch (subtable_type) {
-     case 0:	return_trace (c->dispatch (u.format0));
--    case 1:	return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ());
-+#ifndef HB_NO_SHAPE_AAT
-+    case 1:	return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward<Ts> (ds)...) : c->default_return_value ());
-+#endif
-     case 2:	return_trace (c->dispatch (u.format2));
--    case 3:	return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ());
-+#ifndef HB_NO_SHAPE_AAT
-+    case 3:	return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward<Ts> (ds)...) : c->default_return_value ());
-+#endif
-     default:	return_trace (c->default_return_value ());
-     }
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!u.header.sanitize (c) ||
-@@ -273,67 +277,77 @@ struct kern
- 
-   bool has_data () const { return u.version32; }
-   unsigned int get_type () const { return u.major; }
- 
-   bool has_state_machine () const
-   {
-     switch (get_type ()) {
-     case 0: return u.ot.has_state_machine ();
-+#ifndef HB_NO_SHAPE_AAT
-     case 1: return u.aat.has_state_machine ();
-+#endif
-     default:return false;
-     }
-   }
- 
-   bool has_cross_stream () const
-   {
-     switch (get_type ()) {
-     case 0: return u.ot.has_cross_stream ();
-+#ifndef HB_NO_SHAPE_AAT
-     case 1: return u.aat.has_cross_stream ();
-+#endif
-     default:return false;
-     }
-   }
- 
-   int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
-   {
-     switch (get_type ()) {
-     case 0: return u.ot.get_h_kerning (left, right);
-+#ifndef HB_NO_SHAPE_AAT
-     case 1: return u.aat.get_h_kerning (left, right);
-+#endif
-     default:return 0;
-     }
-   }
- 
-   bool apply (AAT::hb_aat_apply_context_t *c) const
-   { return dispatch (c); }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     unsigned int subtable_type = get_type ();
-     TRACE_DISPATCH (this, subtable_type);
-     switch (subtable_type) {
--    case 0:	return_trace (c->dispatch (u.ot));
--    case 1:	return_trace (c->dispatch (u.aat));
-+    case 0:	return_trace (c->dispatch (u.ot, hb_forward<Ts> (ds)...));
-+#ifndef HB_NO_SHAPE_AAT
-+    case 1:	return_trace (c->dispatch (u.aat, hb_forward<Ts> (ds)...));
-+#endif
-     default:	return_trace (c->default_return_value ());
-     }
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!u.version32.sanitize (c)) return_trace (false);
-     return_trace (dispatch (c));
-   }
- 
-   protected:
-   union {
-   HBUINT32		version32;
-   HBUINT16		major;
-   KernOT		ot;
-+#ifndef HB_NO_SHAPE_AAT
-   KernAAT		aat;
-+#endif
-   } u;
-   public:
-   DEFINE_SIZE_UNION (4, version32);
- };
- 
- } /* namespace OT */
- 
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-base-table.hh b/gfx/harfbuzz/src/hb-ot-layout-base-table.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-base-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-base-table.hh
-@@ -148,17 +148,17 @@ struct BaseCoord
-     BaseCoordFormat3	format3;
-   } u;
-   public:
-   DEFINE_SIZE_UNION (2, format);
- };
- 
- struct FeatMinMaxRecord
- {
--  static int cmp (const void *key_, const void *entry_)
-+  HB_INTERNAL static int cmp (const void *key_, const void *entry_)
-   {
-     hb_tag_t key = * (hb_tag_t *) key_;
-     const FeatMinMaxRecord &entry = * (const FeatMinMaxRecord *) entry_;
-     return key < (unsigned int) entry.tag ? -1 :
- 	   key > (unsigned int) entry.tag ? 1 :
- 	   0;
-   }
- 
-@@ -266,17 +266,17 @@ struct BaseValues
- 				 * BaseValues table — order matches baselineTags array in
- 				 * the BaseTagList */
-   public:
-   DEFINE_SIZE_ARRAY (4, baseCoords);
- };
- 
- struct BaseLangSysRecord
- {
--  static int cmp (const void *key_, const void *entry_)
-+  HB_INTERNAL static int cmp (const void *key_, const void *entry_)
-   {
-     hb_tag_t key = * (hb_tag_t *) key_;
-     const BaseLangSysRecord &entry = * (const BaseLangSysRecord *) entry_;
-     return key < (unsigned int) entry.baseLangSysTag ? -1 :
- 	   key > (unsigned int) entry.baseLangSysTag ? 1 :
- 	   0;
-   }
- 
-@@ -340,17 +340,17 @@ struct BaseScript
- 
-   public:
-   DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
- };
- 
- struct BaseScriptList;
- struct BaseScriptRecord
- {
--  static int cmp (const void *key_, const void *entry_)
-+  HB_INTERNAL static int cmp (const void *key_, const void *entry_)
-   {
-     hb_tag_t key = * (hb_tag_t *) key_;
-     const BaseScriptRecord &entry = * (const BaseScriptRecord *) entry_;
-     return key < (unsigned int) entry.baseScriptTag ? -1 :
- 	   key > (unsigned int) entry.baseScriptTag ? 1 :
- 	   0;
-   }
- 
-@@ -442,17 +442,17 @@ struct Axis
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this) &&
- 			  (this+baseTagList).sanitize (c) &&
- 			  (this+baseScriptList).sanitize (c)));
-   }
- 
-   protected:
--  OffsetTo<SortedArrayOf<Tag> >
-+  OffsetTo<SortedArrayOf<Tag>>
- 		baseTagList;	/* Offset to BaseTagList table, from beginning
- 				 * of Axis table (may be NULL)
- 				 * Array of 4-byte baseline identification tags — must
- 				 * be in alphabetical order */
-   OffsetTo<BaseScriptList>
- 		baseScriptList;	/* Offset to BaseScriptList table, from beginning
- 				 * of Axis table
- 				 * Array of BaseScriptRecords, in alphabetical order
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-common.hh b/gfx/harfbuzz/src/hb-ot-layout-common.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-common.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-common.hh
-@@ -61,17 +61,16 @@
- 
- 
- namespace OT {
- 
- 
- #define NOT_COVERED		((unsigned int) -1)
- 
- 
--
- /*
-  *
-  * OpenType Layout Common Table Formats
-  *
-  */
- 
- 
- /*
-@@ -99,17 +98,17 @@ struct Record
-   OffsetTo<Type>
- 		offset;		/* Offset from beginning of object holding
- 				 * the Record */
-   public:
-   DEFINE_SIZE_STATIC (6);
- };
- 
- template <typename Type>
--struct RecordArrayOf : SortedArrayOf<Record<Type> >
-+struct RecordArrayOf : SortedArrayOf<Record<Type>>
- {
-   const OffsetTo<Type>& get_offset (unsigned int i) const
-   { return (*this)[i].offset; }
-   OffsetTo<Type>& get_offset (unsigned int i)
-   { return (*this)[i].offset; }
-   const Tag& get_tag (unsigned int i) const
-   { return (*this)[i].tag; }
-   unsigned int get_tags (unsigned int start_offset,
-@@ -134,21 +133,21 @@ template <typename Type>
- struct RecordListOf : RecordArrayOf<Type>
- {
-   const Type& operator [] (unsigned int i) const
-   { return this+this->get_offset (i); }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
--    struct RecordListOf<Type> *out = c->serializer->embed (*this);
-+    auto *out = c->serializer->embed (*this);
-     if (unlikely (!out)) return_trace (false);
-     unsigned int count = this->len;
-     for (unsigned int i = 0; i < count; i++)
--      out->get_offset (i).serialize_subset (c, (*this)[i], out);
-+      out->get_offset (i).serialize_subset (c, this->get_offset (i), this, out);
-     return_trace (true);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (RecordArrayOf<Type>::sanitize (c, this));
-   }
-@@ -222,23 +221,23 @@ struct LangSys
-   void add_feature_indexes_to (hb_set_t *feature_indexes) const
-   { featureIndex.add_indexes_to (feature_indexes); }
- 
-   bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
-   unsigned int get_required_feature_index () const
-   {
-     if (reqFeatureIndex == 0xFFFFu)
-       return Index::NOT_FOUND_INDEX;
--   return reqFeatureIndex;;
-+   return reqFeatureIndex;
-   }
- 
--  bool subset (hb_subset_context_t *c) const
-+  LangSys* copy (hb_serialize_context_t *c) const
-   {
--    TRACE_SUBSET (this);
--    return_trace (c->serializer->embed (*this));
-+    TRACE_SERIALIZE (this);
-+    return_trace (c->embed (*this));
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c,
- 		 const Record_sanitize_closure_t * = nullptr) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) && featureIndex.sanitize (c));
-   }
-@@ -273,22 +272,22 @@ struct Script
-   { return langSys.find_index (tag, index); }
- 
-   bool has_default_lang_sys () const           { return defaultLangSys != 0; }
-   const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
--    struct Script *out = c->serializer->embed (*this);
-+    auto *out = c->serializer->embed (*this);
-     if (unlikely (!out)) return_trace (false);
--    out->defaultLangSys.serialize_subset (c, this+defaultLangSys, out);
-+    out->defaultLangSys.serialize_copy (c->serializer, defaultLangSys, this, out);
-     unsigned int count = langSys.len;
-     for (unsigned int i = 0; i < count; i++)
--      out->langSys.arrayZ[i].offset.serialize_subset (c, this+langSys[i].offset, out);
-+      out->langSys.arrayZ[i].offset.serialize_copy (c->serializer, langSys[i].offset, this, out);
-     return_trace (true);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c,
- 		 const Record_sanitize_closure_t * = nullptr) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
-@@ -555,19 +554,19 @@ struct Feature
-   { lookupIndex.add_indexes_to (lookup_indexes); }
- 
-   const FeatureParams &get_feature_params () const
-   { return this+featureParams; }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
--    struct Feature *out = c->serializer->embed (*this);
-+    auto *out = c->serializer->embed (*this);
-     if (unlikely (!out)) return_trace (false);
--    out->featureParams.set (0); /* TODO(subset) FeatureParams. */
-+    out->featureParams = 0; /* TODO(subset) FeatureParams. */
-     return_trace (true);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c,
- 		 const Record_sanitize_closure_t *closure = nullptr) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
-@@ -579,35 +578,35 @@ struct Feature
-      * If sanitizing "failed" for the FeatureParams subtable, try it with the
-      * alternative location.  We would know sanitize "failed" if old value
-      * of the offset was non-zero, but it's zeroed now.
-      *
-      * Only do this for the 'size' feature, since at the time of the faulty
-      * Adobe tools, only the 'size' feature had FeatureParams defined.
-      */
- 
--    OffsetTo<FeatureParams> orig_offset = featureParams;
-+    if (likely (featureParams.is_null ()))
-+      return_trace (true);
-+
-+    unsigned int orig_offset = featureParams;
-     if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
-       return_trace (false);
- 
--    if (likely (orig_offset.is_null ()))
--      return_trace (true);
--
-     if (featureParams == 0 && closure &&
- 	closure->tag == HB_TAG ('s','i','z','e') &&
- 	closure->list_base && closure->list_base < this)
-     {
--      unsigned int new_offset_int = (unsigned int) orig_offset -
-+      unsigned int new_offset_int = orig_offset -
- 				    (((char *) this) - ((char *) closure->list_base));
- 
-       OffsetTo<FeatureParams> new_offset;
--      /* Check that it did not overflow. */
--      new_offset.set (new_offset_int);
-+      /* Check that it would not overflow. */
-+      new_offset = new_offset_int;
-       if (new_offset == new_offset_int &&
--	  c->try_set (&featureParams, new_offset) &&
-+	  c->try_set (&featureParams, new_offset_int) &&
- 	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
- 	return_trace (false);
-     }
- 
-     return_trace (true);
-   }
- 
-   OffsetTo<FeatureParams>
-@@ -644,25 +643,28 @@ struct LookupFlag : HBUINT16
- HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
- namespace OT {
- 
- struct Lookup
- {
-   unsigned int get_subtable_count () const { return subTable.len; }
- 
-   template <typename TSubTable>
--  const TSubTable& get_subtable (unsigned int i) const
--  { return this+CastR<OffsetArrayOf<TSubTable> > (subTable)[i]; }
-+  const OffsetArrayOf<TSubTable>& get_subtables () const
-+  { return CastR<OffsetArrayOf<TSubTable>> (subTable); }
-+  template <typename TSubTable>
-+  OffsetArrayOf<TSubTable>& get_subtables ()
-+  { return CastR<OffsetArrayOf<TSubTable>> (subTable); }
- 
-   template <typename TSubTable>
--  const OffsetArrayOf<TSubTable>& get_subtables () const
--  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
-+  const TSubTable& get_subtable (unsigned int i) const
-+  { return this+get_subtables<TSubTable> ()[i]; }
-   template <typename TSubTable>
--  OffsetArrayOf<TSubTable>& get_subtables ()
--  { return CastR<OffsetArrayOf<TSubTable> > (subTable); }
-+  TSubTable& get_subtable (unsigned int i)
-+  { return this+get_subtables<TSubTable> ()[i]; }
- 
-   unsigned int get_size () const
-   {
-     const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
-     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-       return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
-     return (const char *) &markFilteringSet - (const char *) this;
-   }
-@@ -678,126 +680,101 @@ struct Lookup
-     if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
-     {
-       const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-       flag += (markFilteringSet << 16);
-     }
-     return flag;
-   }
- 
--  template <typename TSubTable, typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename TSubTable, typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     unsigned int lookup_type = get_type ();
-     TRACE_DISPATCH (this, lookup_type);
-     unsigned int count = get_subtable_count ();
-     for (unsigned int i = 0; i < count; i++) {
--      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type);
-+      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, hb_forward<Ts> (ds)...);
-       if (c->stop_sublookup_iteration (r))
- 	return_trace (r);
-     }
-     return_trace (c->default_return_value ());
-   }
- 
-   bool serialize (hb_serialize_context_t *c,
- 		  unsigned int lookup_type,
- 		  uint32_t lookup_props,
- 		  unsigned int num_subtables)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
--    lookupType.set (lookup_type);
--    lookupFlag.set (lookup_props & 0xFFFFu);
-+    lookupType = lookup_type;
-+    lookupFlag = lookup_props & 0xFFFFu;
-     if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
-     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-     {
-       if (unlikely (!c->extend (*this))) return_trace (false);
-       HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
--      markFilteringSet.set (lookup_props >> 16);
-+      markFilteringSet = lookup_props >> 16;
-     }
-     return_trace (true);
-   }
- 
--  /* Older compilers need this to NOT be locally defined in a function. */
--  template <typename TSubTable>
--  struct SubTableSubsetWrapper
--  {
--    SubTableSubsetWrapper (const TSubTable &subtable_,
--			   unsigned int lookup_type_) :
--			     subtable (subtable_),
--			     lookup_type (lookup_type_) {}
--
--    bool subset (hb_subset_context_t *c) const
--    { return subtable.dispatch (c, lookup_type); }
--
--    private:
--    const TSubTable &subtable;
--    unsigned int lookup_type;
--  };
--
-   template <typename TSubTable>
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
--    struct Lookup *out = c->serializer->embed (*this);
-+    auto *out = c->serializer->embed (*this);
-     if (unlikely (!out)) return_trace (false);
- 
-     /* Subset the actual subtables. */
-     /* TODO Drop empty ones, either by calling intersects() beforehand,
-      * or just dropping null offsets after. */
-     const OffsetArrayOf<TSubTable>& subtables = get_subtables<TSubTable> ();
-     OffsetArrayOf<TSubTable>& out_subtables = out->get_subtables<TSubTable> ();
-     unsigned int count = subTable.len;
-     for (unsigned int i = 0; i < count; i++)
--    {
--      SubTableSubsetWrapper<TSubTable> wrapper (this+subtables[i], get_type ());
--
--      out_subtables[i].serialize_subset (c, wrapper, out);
--    }
-+      out_subtables[i].serialize_subset (c, subtables[i], this, out, get_type ());
- 
-     return_trace (true);
-   }
- 
--  /* Older compilers need this to NOT be locally defined in a function. */
--  template <typename TSubTable>
--  struct SubTableSanitizeWrapper : TSubTable
--  {
--    bool sanitize (hb_sanitize_context_t *c, unsigned int lookup_type) const
--    { return this->dispatch (c, lookup_type); }
--  };
--
-   template <typename TSubTable>
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
-     if (lookupFlag & LookupFlag::UseMarkFilteringSet)
-     {
-       const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
-       if (!markFilteringSet.sanitize (c)) return_trace (false);
-     }
- 
--    if (unlikely (!CastR<OffsetArrayOf<SubTableSanitizeWrapper<TSubTable> > > (subTable)
--		   .sanitize (c, this, get_type ())))
-+    if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
-       return_trace (false);
- 
--    if (unlikely (get_type () == TSubTable::Extension))
-+    if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
-     {
-       /* The spec says all subtables of an Extension lookup should
-        * have the same type, which shall not be the Extension type
-        * itself (but we already checked for that).
--       * This is specially important if one has a reverse type! */
-+       * This is specially important if one has a reverse type!
-+       *
-+       * We only do this if sanitizer edit_count is zero.  Otherwise,
-+       * some of the subtables might have become insane after they
-+       * were sanity-checked by the edits of subsequent subtables.
-+       * https://bugs.chromium.org/p/chromium/issues/detail?id=960331
-+       */
-       unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
-       unsigned int count = get_subtable_count ();
-       for (unsigned int i = 1; i < count; i++)
- 	if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
- 	  return_trace (false);
-     }
-     return_trace (true);
--    return_trace (true);
-   }
- 
-   private:
-   HBUINT16	lookupType;		/* Different enumerations for GSUB and GPOS */
-   HBUINT16	lookupFlag;		/* Lookup qualifiers */
-   ArrayOf<Offset16>
- 		subTable;		/* Array of SubTables */
- /*HBUINT16	markFilteringSetX[VAR];*//* Index (base 0) into GDEF mark glyph sets
-@@ -821,18 +798,19 @@ struct CoverageFormat1
-   private:
-   unsigned int get_coverage (hb_codepoint_t glyph_id) const
-   {
-     unsigned int i;
-     glyphArray.bfind (glyph_id, &i, HB_BFIND_NOT_FOUND_STORE, NOT_COVERED);
-     return i;
-   }
- 
--  bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs)
-+  template <typename Iterator,
-+      hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
-+  bool serialize (hb_serialize_context_t *c, Iterator glyphs)
-   {
-     TRACE_SERIALIZE (this);
-     return_trace (glyphArray.serialize (c, glyphs));
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-@@ -848,29 +826,29 @@ struct CoverageFormat1
- 	return true;
-     return false;
-   }
-   bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
-   { return glyphs->has (glyphArray[index]); }
- 
-   template <typename set_t>
-   bool add_coverage (set_t *glyphs) const
--  {
--    return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len);
--  }
-+  { return glyphs->add_sorted_array (glyphArray.arrayZ, glyphArray.len); }
- 
-   public:
-   /* Older compilers need this to be public. */
--  struct Iter {
-+  struct iter_t
-+  {
-     void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
-     void fini () {}
--    bool more () { return i < c->glyphArray.len; }
-+    bool more () const { return i < c->glyphArray.len; }
-     void next () { i++; }
--    hb_codepoint_t get_glyph () { return c->glyphArray[i]; }
--    unsigned int get_coverage () { return i; }
-+    hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
-+    bool operator != (const iter_t& o) const
-+    { return i != o.i || c != o.c; }
- 
-     private:
-     const struct CoverageFormat1 *c;
-     unsigned int i;
-   };
-   private:
- 
-   protected:
-@@ -889,48 +867,58 @@ struct CoverageFormat2
-   unsigned int get_coverage (hb_codepoint_t glyph_id) const
-   {
-     const RangeRecord &range = rangeRecord.bsearch (glyph_id);
-     return likely (range.start <= range.end) ?
- 	   (unsigned int) range.value + (glyph_id - range.start) :
- 	   NOT_COVERED;
-   }
- 
--  bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs)
-+  template <typename Iterator,
-+      hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
-+  bool serialize (hb_serialize_context_t *c, Iterator glyphs)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
- 
--    if (unlikely (!glyphs.length))
-+    if (unlikely (!glyphs))
-     {
--      rangeRecord.len.set (0);
-+      rangeRecord.len = 0;
-       return_trace (true);
-     }
- 
--    unsigned int num_ranges = 1;
--    for (unsigned int i = 1; i < glyphs.length; i++)
--      if (glyphs[i - 1] + 1 != glyphs[i])
--	num_ranges++;
--    rangeRecord.len.set (num_ranges);
--    if (unlikely (!c->extend (rangeRecord))) return_trace (false);
-+    /* TODO(iter) Write more efficiently? */
-+
-+    unsigned num_ranges = 0;
-+    hb_codepoint_t last = (hb_codepoint_t) -2;
-+    for (auto g: glyphs)
-+    {
-+      if (last + 1 != g)
-+        num_ranges++;
-+      last = g;
-+    }
-+
-+    if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
- 
--    unsigned int range = 0;
--    rangeRecord[range].start = glyphs[0];
--    rangeRecord[range].value.set (0);
--    for (unsigned int i = 1; i < glyphs.length; i++)
-+    unsigned count = 0;
-+    unsigned range = (unsigned) -1;
-+    last = (hb_codepoint_t) -2;
-+    for (auto g: glyphs)
-     {
--      if (glyphs[i - 1] + 1 != glyphs[i])
-+      if (last + 1 != g)
-       {
--	range++;
--	rangeRecord[range].start = glyphs[i];
--	rangeRecord[range].value.set (i);
-+        range++;
-+	rangeRecord[range].start = g;
-+	rangeRecord[range].value = count;
-       }
--      rangeRecord[range].end = glyphs[i];
-+      rangeRecord[range].end = g;
-+      last = g;
-+      count++;
-     }
-+
-     return_trace (true);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (rangeRecord.sanitize (c));
-   }
-@@ -967,56 +955,60 @@ struct CoverageFormat2
-     for (unsigned int i = 0; i < count; i++)
-       if (unlikely (!rangeRecord[i].add_coverage (glyphs)))
- 	return false;
-     return true;
-   }
- 
-   public:
-   /* Older compilers need this to be public. */
--  struct Iter
-+  struct iter_t
-   {
-     void init (const CoverageFormat2 &c_)
-     {
-       c = &c_;
-       coverage = 0;
-       i = 0;
-       j = c->rangeRecord.len ? c->rangeRecord[0].start : 0;
-       if (unlikely (c->rangeRecord[0].start > c->rangeRecord[0].end))
-       {
- 	/* Broken table. Skip. */
- 	i = c->rangeRecord.len;
-       }
-     }
-     void fini () {}
--    bool more () { return i < c->rangeRecord.len; }
-+    bool more () const { return i < c->rangeRecord.len; }
-     void next ()
-     {
-       if (j >= c->rangeRecord[i].end)
-       {
- 	i++;
- 	if (more ())
- 	{
--	  hb_codepoint_t old = j;
-+	  unsigned int old = coverage;
- 	  j = c->rangeRecord[i].start;
--	  if (unlikely (j <= old))
-+	  coverage = c->rangeRecord[i].value;
-+	  if (unlikely (coverage != old + 1))
- 	  {
--	    /* Broken table. Skip. Important to avoid DoS. */
-+	    /* Broken table. Skip. Important to avoid DoS.
-+	     * Also, our callers depend on coverage being
-+	     * consecutive and monotonically increasing,
-+	     * ie. iota(). */
- 	   i = c->rangeRecord.len;
- 	   return;
- 	  }
--	  coverage = c->rangeRecord[i].value;
- 	}
- 	return;
-       }
-       coverage++;
-       j++;
-     }
--    hb_codepoint_t get_glyph () { return j; }
--    unsigned int get_coverage () { return coverage; }
-+    hb_codepoint_t get_glyph () const { return j; }
-+    bool operator != (const iter_t& o) const
-+    { return i != o.i || j != o.j || c != o.c; }
- 
-     private:
-     const struct CoverageFormat2 *c;
-     unsigned int i, coverage;
-     hb_codepoint_t j;
-   };
-   private:
- 
-@@ -1027,36 +1019,52 @@ struct CoverageFormat2
- 				 * Start GlyphID. rangeCount entries
- 				 * long */
-   public:
-   DEFINE_SIZE_ARRAY (4, rangeRecord);
- };
- 
- struct Coverage
- {
-+  /* Has interface. */
-+  static constexpr unsigned SENTINEL = NOT_COVERED;
-+  typedef unsigned int value_t;
-+  value_t operator [] (hb_codepoint_t k) const { return get (k); }
-+  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
-+  /* Predicate. */
-+  bool operator () (hb_codepoint_t k) const { return has (k); }
-+
-+  unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
-   unsigned int get_coverage (hb_codepoint_t glyph_id) const
-   {
-     switch (u.format) {
-     case 1: return u.format1.get_coverage (glyph_id);
-     case 2: return u.format2.get_coverage (glyph_id);
-     default:return NOT_COVERED;
-     }
-   }
- 
--  bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs)
-+  template <typename Iterator,
-+      hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
-+  bool serialize (hb_serialize_context_t *c, Iterator glyphs)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
- 
--    unsigned int num_ranges = 1;
--    for (unsigned int i = 1; i < glyphs.length; i++)
--      if (glyphs[i - 1] + 1 != glyphs[i])
--	num_ranges++;
--    u.format.set (glyphs.length * 2 < num_ranges * 3 ? 1 : 2);
-+    unsigned count = 0;
-+    unsigned num_ranges = 0;
-+    hb_codepoint_t last = (hb_codepoint_t) -2;
-+    for (auto g: glyphs)
-+    {
-+      if (last + 1 != g)
-+        num_ranges++;
-+      last = g;
-+      count++;
-+    }
-+    u.format = count * 2 < num_ranges * 3 ? 1 : 2;
- 
-     switch (u.format)
-     {
-     case 1: return_trace (u.format1.serialize (c, glyphs));
-     case 2: return_trace (u.format2.serialize (c, glyphs));
-     default:return_trace (false);
-     }
-   }
-@@ -1100,73 +1108,79 @@ struct Coverage
-     switch (u.format)
-     {
-     case 1: return u.format1.add_coverage (glyphs);
-     case 2: return u.format2.add_coverage (glyphs);
-     default:return false;
-     }
-   }
- 
--  struct Iter
-+  struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
-   {
--    Iter (const Coverage &c_)
-+    static constexpr bool is_sorted_iterator = true;
-+    iter_t (const Coverage &c_ = Null(Coverage))
-     {
-       memset (this, 0, sizeof (*this));
-       format = c_.u.format;
-       switch (format)
-       {
-       case 1: u.format1.init (c_.u.format1); return;
-       case 2: u.format2.init (c_.u.format2); return;
-       default:				     return;
-       }
-     }
--    bool more ()
-+    bool __more__ () const
-     {
-       switch (format)
-       {
-       case 1: return u.format1.more ();
-       case 2: return u.format2.more ();
-       default:return false;
-       }
-     }
--    void next ()
-+    void __next__ ()
-     {
-       switch (format)
-       {
-       case 1: u.format1.next (); break;
-       case 2: u.format2.next (); break;
-       default:			 break;
-       }
-     }
--    hb_codepoint_t get_glyph ()
-+    typedef hb_codepoint_t __item_t__;
-+    __item_t__ __item__ () const { return get_glyph (); }
-+
-+    hb_codepoint_t get_glyph () const
-     {
-       switch (format)
-       {
-       case 1: return u.format1.get_glyph ();
-       case 2: return u.format2.get_glyph ();
-       default:return 0;
-       }
-     }
--    unsigned int get_coverage ()
-+    bool operator != (const iter_t& o) const
-     {
-+      if (format != o.format) return true;
-       switch (format)
-       {
--      case 1: return u.format1.get_coverage ();
--      case 2: return u.format2.get_coverage ();
--      default:return -1;
-+      case 1: return u.format1 != o.u.format1;
-+      case 2: return u.format2 != o.u.format2;
-+      default:return false;
-       }
-     }
- 
-     private:
-     unsigned int format;
-     union {
--    CoverageFormat2::Iter	format2; /* Put this one first since it's larger; helps shut up compiler. */
--    CoverageFormat1::Iter	format1;
-+    CoverageFormat2::iter_t	format2; /* Put this one first since it's larger; helps shut up compiler. */
-+    CoverageFormat1::iter_t	format1;
-     } u;
-   };
-+  iter_t iter () const { return iter_t (*this); }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   CoverageFormat1	format1;
-   CoverageFormat2	format2;
-   } u;
-   public:
-@@ -1188,63 +1202,63 @@ struct ClassDefFormat1
- 
-   private:
-   unsigned int get_class (hb_codepoint_t glyph_id) const
-   {
-     return classValue[(unsigned int) (glyph_id - startGlyph)];
-   }
- 
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const HBUINT16> glyphs,
-+		  hb_array_t<const GlyphID> glyphs,
- 		  hb_array_t<const HBUINT16> klasses)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
- 
--    if (unlikely (!glyphs.length))
-+    if (unlikely (!glyphs))
-     {
--      startGlyph.set (0);
--      classValue.len.set (0);
-+      startGlyph = 0;
-+      classValue.len = 0;
-       return_trace (true);
-     }
- 
--    hb_codepoint_t glyph_min = glyphs[0];
--    hb_codepoint_t glyph_max = glyphs[glyphs.length - 1];
-+    hb_codepoint_t glyph_min = +glyphs | hb_reduce (hb_min, 0xFFFFu);
-+    hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u);
- 
--    startGlyph.set (glyph_min);
--    classValue.len.set (glyph_max - glyph_min + 1);
-+    startGlyph = glyph_min;
-+    c->check_assign (classValue.len, glyph_max - glyph_min + 1);
-     if (unlikely (!c->extend (classValue))) return_trace (false);
- 
-     for (unsigned int i = 0; i < glyphs.length; i++)
-       classValue[glyphs[i] - glyph_min] = klasses[i];
- 
-     return_trace (true);
-   }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
-     const hb_set_t &glyphset = *c->plan->glyphset ();
-     const hb_map_t &glyph_map = *c->plan->glyph_map;
--    hb_vector_t<GlyphID> glyphs;
-+    hb_sorted_vector_t<GlyphID> glyphs;
-     hb_vector_t<HBUINT16> klasses;
- 
-     hb_codepoint_t start = startGlyph;
-     hb_codepoint_t end   = start + classValue.len;
-     for (hb_codepoint_t g = start; g < end; g++)
-     {
-+      if (!glyphset.has (g)) continue;
-       unsigned int value = classValue[g - start];
-       if (!value) continue;
--      if (!glyphset.has (g)) continue;
--      glyphs.push()->set (glyph_map[g]);
--      klasses.push()->set (value);
-+      glyphs.push(glyph_map[g]);
-+      klasses.push(value);
-     }
-     c->serializer->propagate_error (glyphs, klasses);
-     ClassDef_serialize (c->serializer, glyphs, klasses);
--    return_trace (glyphs.length);
-+    return_trace ((bool) glyphs);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) && classValue.sanitize (c));
-   }
- 
-@@ -1324,50 +1338,52 @@ struct ClassDefFormat2
- 
-   private:
-   unsigned int get_class (hb_codepoint_t glyph_id) const
-   {
-     return rangeRecord.bsearch (glyph_id).value;
-   }
- 
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const HBUINT16> glyphs,
-+		  hb_array_t<const GlyphID> glyphs,
- 		  hb_array_t<const HBUINT16> klasses)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
- 
--    if (unlikely (!glyphs.length))
-+    if (unlikely (!glyphs))
-     {
--      rangeRecord.len.set (0);
-+      rangeRecord.len = 0;
-       return_trace (true);
-     }
- 
-+    unsigned int count = glyphs.len ();
-     unsigned int num_ranges = 1;
--    for (unsigned int i = 1; i < glyphs.length; i++)
-+    for (unsigned int i = 1; i < count; i++)
-       if (glyphs[i - 1] + 1 != glyphs[i] ||
- 	  klasses[i - 1] != klasses[i])
- 	num_ranges++;
--    rangeRecord.len.set (num_ranges);
-+    rangeRecord.len = num_ranges;
-     if (unlikely (!c->extend (rangeRecord))) return_trace (false);
- 
-     unsigned int range = 0;
-     rangeRecord[range].start = glyphs[0];
--    rangeRecord[range].value.set (klasses[0]);
--    for (unsigned int i = 1; i < glyphs.length; i++)
-+    rangeRecord[range].value = klasses[0];
-+    for (unsigned int i = 1; i < count; i++)
-     {
-       if (glyphs[i - 1] + 1 != glyphs[i] ||
- 	  klasses[i - 1] != klasses[i])
-       {
-+	rangeRecord[range].end = glyphs[i - 1];
- 	range++;
- 	rangeRecord[range].start = glyphs[i];
- 	rangeRecord[range].value = klasses[i];
-       }
--      rangeRecord[range].end = glyphs[i];
-     }
-+    rangeRecord[range].end = glyphs[count - 1];
-     return_trace (true);
-   }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
-     const hb_set_t &glyphset = *c->plan->glyphset ();
-     const hb_map_t &glyph_map = *c->plan->glyph_map;
-@@ -1379,23 +1395,23 @@ struct ClassDefFormat2
-     {
-       unsigned int value = rangeRecord[i].value;
-       if (!value) continue;
-       hb_codepoint_t start = rangeRecord[i].start;
-       hb_codepoint_t end   = rangeRecord[i].end + 1;
-       for (hb_codepoint_t g = start; g < end; g++)
-       {
- 	if (!glyphset.has (g)) continue;
--	glyphs.push ()->set (glyph_map[g]);
--	klasses.push ()->set (value);
-+	glyphs.push (glyph_map[g]);
-+	klasses.push (value);
-       }
-     }
-     c->serializer->propagate_error (glyphs, klasses);
-     ClassDef_serialize (c->serializer, glyphs, klasses);
--    return_trace (glyphs.length);
-+    return_trace ((bool) glyphs);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (rangeRecord.sanitize (c));
-   }
- 
-@@ -1463,16 +1479,25 @@ struct ClassDefFormat2
- 		rangeRecord;	/* Array of glyph ranges--ordered by
- 				 * Start GlyphID */
-   public:
-   DEFINE_SIZE_ARRAY (4, rangeRecord);
- };
- 
- struct ClassDef
- {
-+  /* Has interface. */
-+  static constexpr unsigned SENTINEL = 0;
-+  typedef unsigned int value_t;
-+  value_t operator [] (hb_codepoint_t k) const { return get (k); }
-+  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
-+  /* Projection. */
-+  hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
-+
-+  unsigned int get (hb_codepoint_t k) const { return get_class (k); }
-   unsigned int get_class (hb_codepoint_t glyph_id) const
-   {
-     switch (u.format) {
-     case 1: return u.format1.get_class (glyph_id);
-     case 2: return u.format2.get_class (glyph_id);
-     default:return 0;
-     }
-   }
-@@ -1480,31 +1505,32 @@ struct ClassDef
-   bool serialize (hb_serialize_context_t *c,
- 		  hb_array_t<const GlyphID> glyphs,
- 		  hb_array_t<const HBUINT16> klasses)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
- 
-     unsigned int format = 2;
--    if (glyphs.length)
-+    if (likely (glyphs))
-     {
--      hb_codepoint_t glyph_min = glyphs[0];
--      hb_codepoint_t glyph_max = glyphs[glyphs.length - 1];
-+      hb_codepoint_t glyph_min = +glyphs | hb_reduce (hb_min, 0xFFFFu);
-+      hb_codepoint_t glyph_max = +glyphs | hb_reduce (hb_max, 0u);
- 
-+      unsigned int count = glyphs.len ();
-       unsigned int num_ranges = 1;
--      for (unsigned int i = 1; i < glyphs.length; i++)
-+      for (unsigned int i = 1; i < count; i++)
- 	if (glyphs[i - 1] + 1 != glyphs[i] ||
- 	    klasses[i - 1] != klasses[i])
- 	  num_ranges++;
- 
-       if (1 + (glyph_max - glyph_min + 1) < num_ranges * 3)
-         format = 1;
-     }
--    u.format.set (format);
-+    u.format = format;
- 
-     switch (u.format)
-     {
-     case 1: return_trace (u.format1.serialize (c, glyphs, klasses));
-     case 2: return_trace (u.format2.serialize (c, glyphs, klasses));
-     default:return_trace (false);
-     }
-   }
-@@ -1970,20 +1996,20 @@ struct FeatureVariations
- 
-   const Feature *find_substitute (unsigned int variations_index,
- 				  unsigned int feature_index) const
-   {
-     const FeatureVariationRecord &record = varRecords[variations_index];
-     return (this+record.substitutions).find_substitute (feature_index);
-   }
- 
--  bool subset (hb_subset_context_t *c) const
-+  FeatureVariations* copy (hb_serialize_context_t *c) const
-   {
--    TRACE_SUBSET (this);
--    return_trace (c->serializer->embed (*this));
-+    TRACE_SERIALIZE (this);
-+    return_trace (c->embed (*this));
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (version.sanitize (c) &&
- 		  likely (version.major == 1) &&
- 		  varRecords.sanitize (c, this));
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-gdef-table.hh
-@@ -215,17 +215,17 @@ struct LigGlyph
- 			       hb_codepoint_t glyph_id,
- 			       const VariationStore &var_store,
- 			       unsigned int start_offset,
- 			       unsigned int *caret_count /* IN/OUT */,
- 			       hb_position_t *caret_array /* OUT */) const
-   {
-     if (caret_count)
-     {
--      hb_array_t <const OffsetTo<CaretValue> > array = carets.sub_array (start_offset, caret_count);
-+      hb_array_t <const OffsetTo<CaretValue>> array = carets.sub_array (start_offset, caret_count);
-       unsigned int count = array.length;
-       for (unsigned int i = 0; i < count; i++)
- 	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id, var_store);
-     }
- 
-     return carets.len;
-   }
- 
-@@ -291,17 +291,17 @@ struct MarkGlyphSetsFormat1
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (coverage.sanitize (c, this));
-   }
- 
-   protected:
-   HBUINT16	format;			/* Format identifier--format = 1 */
--  ArrayOf<LOffsetTo<Coverage> >
-+  ArrayOf<LOffsetTo<Coverage>>
- 		coverage;		/* Array of long offsets to mark set
- 					 * coverage tables */
-   public:
-   DEFINE_SIZE_ARRAY (4, coverage);
- };
- 
- struct MarkGlyphSets
- {
-@@ -434,29 +434,29 @@ struct GDEF
-     return min_size +
- 	   (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
- 	   (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
-   }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
--    struct GDEF *out = c->serializer->embed (*this);
-+    auto *out = c->serializer->embed (*this);
-     if (unlikely (!out)) return_trace (false);
- 
--    out->glyphClassDef.serialize_subset (c, this+glyphClassDef, out);
--    out->attachList.set (0);//TODO(subset) serialize_subset (c, this+attachList, out);
--    out->ligCaretList.set (0);//TODO(subset) serialize_subset (c, this+ligCaretList, out);
--    out->markAttachClassDef.serialize_subset (c, this+markAttachClassDef, out);
-+    out->glyphClassDef.serialize_subset (c, glyphClassDef, this, out);
-+    out->attachList = 0;//TODO(subset) serialize_subset (c, attachList, this, out);
-+    out->ligCaretList = 0;//TODO(subset) serialize_subset (c, ligCaretList, this, out);
-+    out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, out);
- 
-     if (version.to_int () >= 0x00010002u)
--      out->markGlyphSetsDef.set (0);// TODO(subset) serialize_subset (c, this+markGlyphSetsDef, out);
-+      out->markGlyphSetsDef = 0;// TODO(subset) serialize_subset (c, markGlyphSetsDef, this, out);
- 
-     if (version.to_int () >= 0x00010003u)
--      out->varStore.set (0);// TODO(subset) serialize_subset (c, this+varStore, out);
-+      out->varStore = 0;// TODO(subset) serialize_subset (c, varStore, this, out);
- 
-     return_trace (true);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (version.sanitize (c) &&
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
-@@ -168,25 +168,25 @@ struct ValueFormat : HBUINT16
-     if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
-     if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
-     if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
-     if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
- 
-     return true;
-   }
- 
--  static OffsetTo<Device>& get_device (Value* value)
--  { return *CastP<OffsetTo<Device> > (value); }
--  static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
-+  HB_INTERNAL static OffsetTo<Device>& get_device (Value* value)
-+  { return *CastP<OffsetTo<Device>> (value); }
-+  HB_INTERNAL static const OffsetTo<Device>& get_device (const Value* value, bool *worked=nullptr)
-   {
-     if (worked) *worked |= bool (*value);
--    return *CastP<OffsetTo<Device> > (value);
-+    return *CastP<OffsetTo<Device>> (value);
-   }
- 
--  static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
-+  HB_INTERNAL static const HBINT16& get_short (const Value* value, bool *worked=nullptr)
-   {
-     if (worked) *worked |= bool (*value);
-     return *CastP<HBINT16> (value);
-   }
- 
-   public:
- 
-   bool has_device () const
-@@ -388,17 +388,17 @@ struct AnchorMatrix
-     if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
-     for (unsigned int i = 0; i < count; i++)
-       if (!matrixZ[i].sanitize (c, this)) return_trace (false);
-     return_trace (true);
-   }
- 
-   HBUINT16	rows;			/* Number of rows */
-   protected:
--  UnsizedArrayOf<OffsetTo<Anchor> >
-+  UnsizedArrayOf<OffsetTo<Anchor>>
- 		matrixZ;		/* Matrix of offsets to Anchor tables--
- 					 * from beginning of AnchorMatrix table */
-   public:
-   DEFINE_SIZE_ARRAY (2, matrixZ);
- };
- 
- 
- struct MarkRecord
-@@ -441,18 +441,18 @@ struct MarkArray : ArrayOf<MarkRecord>	/
- 
-     float mark_x, mark_y, base_x, base_y;
- 
-     buffer->unsafe_to_break (glyph_pos, buffer->idx);
-     mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
-     glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
- 
-     hb_glyph_position_t &o = buffer->cur_pos();
--    o.x_offset = round (base_x - mark_x);
--    o.y_offset = round (base_y - mark_y);
-+    o.x_offset = roundf (base_x - mark_x);
-+    o.y_offset = roundf (base_y - mark_y);
-     o.attach_type() = ATTACH_TYPE_MARK;
-     o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
-     buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
- 
-     buffer->idx++;
-     return_trace (true);
-   }
- 
-@@ -571,24 +571,24 @@ struct SinglePosFormat2
-   ValueRecord	values;			/* Array of ValueRecords--positioning
- 					 * values applied to glyphs */
-   public:
-   DEFINE_SIZE_ARRAY (8, values);
- };
- 
- struct SinglePos
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
--    case 2: return_trace (c->dispatch (u.format2));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   SinglePosFormat1	format1;
-@@ -611,17 +611,17 @@ struct PairValueRecord
-   DEFINE_SIZE_ARRAY (2, values);
- };
- 
- struct PairSet
- {
-   friend struct PairPosFormat1;
- 
-   bool intersects (const hb_set_t *glyphs,
--			  const ValueFormat *valueFormats) const
-+		   const ValueFormat *valueFormats) const
-   {
-     unsigned int len1 = valueFormats[0].get_len ();
-     unsigned int len2 = valueFormats[1].get_len ();
-     unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
- 
-     const PairValueRecord *record = &firstPairValueRecord;
-     unsigned int count = len;
-     for (unsigned int i = 0; i < count; i++)
-@@ -717,26 +717,24 @@ struct PairSet
-   public:
-   DEFINE_SIZE_MIN (2);
- };
- 
- struct PairPosFormat1
- {
-   bool intersects (const hb_set_t *glyphs) const
-   {
--    unsigned int count = pairSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (glyphs->has (iter.get_glyph ()) &&
--	  (this+pairSet[iter.get_coverage ()]).intersects (glyphs, valueFormat))
--	return true;
--    }
--    return false;
-+    return
-+    + hb_zip (this+coverage, pairSet)
-+    | hb_filter (*glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_map ([=] (const OffsetTo<PairSet> &_)
-+	      { return (this+_).intersects (glyphs, valueFormat); })
-+    | hb_any
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
-     unsigned int count = pairSet.len;
-     for (unsigned int i = 0; i < count; i++)
-       (this+pairSet[i]).collect_glyphs (c, valueFormat);
-@@ -904,24 +902,24 @@ struct PairPosFormat2
- 					 * class1-major, class2-minor,
- 					 * Each entry has value1 and value2 */
-   public:
-   DEFINE_SIZE_ARRAY (16, values);
- };
- 
- struct PairPos
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
--    case 2: return_trace (c->dispatch (u.format2));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   PairPosFormat1	format1;
-@@ -990,42 +988,42 @@ struct CursivePosFormat1
-     (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
- 
-     hb_glyph_position_t *pos = buffer->pos;
- 
-     hb_position_t d;
-     /* Main-direction adjustment */
-     switch (c->direction) {
-       case HB_DIRECTION_LTR:
--	pos[i].x_advance  = round (exit_x) + pos[i].x_offset;
-+	pos[i].x_advance  = roundf (exit_x) + pos[i].x_offset;
- 
--	d = round (entry_x) + pos[j].x_offset;
-+	d = roundf (entry_x) + pos[j].x_offset;
- 	pos[j].x_advance -= d;
- 	pos[j].x_offset  -= d;
- 	break;
-       case HB_DIRECTION_RTL:
--	d = round (exit_x) + pos[i].x_offset;
-+	d = roundf (exit_x) + pos[i].x_offset;
- 	pos[i].x_advance -= d;
- 	pos[i].x_offset  -= d;
- 
--	pos[j].x_advance  = round (entry_x) + pos[j].x_offset;
-+	pos[j].x_advance  = roundf (entry_x) + pos[j].x_offset;
- 	break;
-       case HB_DIRECTION_TTB:
--	pos[i].y_advance  = round (exit_y) + pos[i].y_offset;
-+	pos[i].y_advance  = roundf (exit_y) + pos[i].y_offset;
- 
--	d = round (entry_y) + pos[j].y_offset;
-+	d = roundf (entry_y) + pos[j].y_offset;
- 	pos[j].y_advance -= d;
- 	pos[j].y_offset  -= d;
- 	break;
-       case HB_DIRECTION_BTT:
--	d = round (exit_y) + pos[i].y_offset;
-+	d = roundf (exit_y) + pos[i].y_offset;
- 	pos[i].y_advance -= d;
- 	pos[i].y_offset  -= d;
- 
--	pos[j].y_advance  = round (entry_y);
-+	pos[j].y_advance  = roundf (entry_y);
- 	break;
-       case HB_DIRECTION_INVALID:
-       default:
- 	break;
-     }
- 
-     /* Cross-direction adjustment */
- 
-@@ -1089,23 +1087,23 @@ struct CursivePosFormat1
- 		entryExitRecord;	/* Array of EntryExit records--in
- 					 * Coverage Index order */
-   public:
-   DEFINE_SIZE_ARRAY (6, entryExitRecord);
- };
- 
- struct CursivePos
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   CursivePosFormat1	format1;
-@@ -1205,23 +1203,23 @@ struct MarkBasePosFormat1
- 		baseArray;		/* Offset to BaseArray table--from
- 					 * beginning of MarkBasePos subtable */
-   public:
-   DEFINE_SIZE_STATIC (12);
- };
- 
- struct MarkBasePos
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   MarkBasePosFormat1	format1;
-@@ -1284,17 +1282,17 @@ struct MarkLigPosFormat1
-      * is identical to the ligature ID of the found ligature.  If yes, we
-      * can directly use the component index.  If not, we attach the mark
-      * glyph to the last component of the ligature. */
-     unsigned int comp_index;
-     unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
-     unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-     unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
-     if (lig_id && lig_id == mark_id && mark_comp > 0)
--      comp_index = MIN (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
-+      comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
-     else
-       comp_index = comp_count - 1;
- 
-     return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
-   }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-@@ -1330,23 +1328,23 @@ struct MarkLigPosFormat1
- 		ligatureArray;		/* Offset to LigatureArray table--from
- 					 * beginning of MarkLigPos subtable */
-   public:
-   DEFINE_SIZE_STATIC (12);
- };
- 
- struct MarkLigPos
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   MarkLigPosFormat1	format1;
-@@ -1452,23 +1450,23 @@ struct MarkMarkPosFormat1
- 		mark2Array;		/* Offset to Mark2Array table--from
- 					 * beginning of MarkMarkPos subtable */
-   public:
-   DEFINE_SIZE_STATIC (12);
- };
- 
- struct MarkMarkPos
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   MarkMarkPosFormat1	format1;
-@@ -1504,30 +1502,30 @@ struct PosLookupSubTable
-     MarkBase		= 4,
-     MarkLig		= 5,
-     MarkMark		= 6,
-     Context		= 7,
-     ChainContext	= 8,
-     Extension		= 9
-   };
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, lookup_type);
-     switch (lookup_type) {
--    case Single:		return_trace (u.single.dispatch (c));
--    case Pair:			return_trace (u.pair.dispatch (c));
--    case Cursive:		return_trace (u.cursive.dispatch (c));
--    case MarkBase:		return_trace (u.markBase.dispatch (c));
--    case MarkLig:		return_trace (u.markLig.dispatch (c));
--    case MarkMark:		return_trace (u.markMark.dispatch (c));
--    case Context:		return_trace (u.context.dispatch (c));
--    case ChainContext:		return_trace (u.chainContext.dispatch (c));
--    case Extension:		return_trace (u.extension.dispatch (c));
-+    case Single:		return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Pair:			return_trace (u.pair.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Cursive:		return_trace (u.cursive.dispatch (c, hb_forward<Ts> (ds)...));
-+    case MarkBase:		return_trace (u.markBase.dispatch (c, hb_forward<Ts> (ds)...));
-+    case MarkLig:		return_trace (u.markLig.dispatch (c, hb_forward<Ts> (ds)...));
-+    case MarkMark:		return_trace (u.markMark.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Context:		return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
-+    case ChainContext:		return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Extension:		return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
-     default:			return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   SinglePos		single;
-   PairPos		pair;
-@@ -1573,24 +1571,24 @@ struct PosLookup : Lookup
- 
-   template <typename set_t>
-   void add_coverage (set_t *glyphs) const
-   {
-     hb_add_coverage_context_t<set_t> c (glyphs);
-     dispatch (&c);
-   }
- 
--  static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-+  HB_INTERNAL static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
- 
-   template <typename context_t>
-   static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
--  { return Lookup::dispatch<SubTable> (c); }
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-+  { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
- 
-   bool subset (hb_subset_context_t *c) const
-   { return Lookup::subset<SubTable> (c); }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   { return Lookup::sanitize<SubTable> (c); }
- };
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-gsub-table.hh
-@@ -29,197 +29,197 @@
- #ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
- #define HB_OT_LAYOUT_GSUB_TABLE_HH
- 
- #include "hb-ot-layout-gsubgpos.hh"
- 
- 
- namespace OT {
- 
-+typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
- 
-+template<typename Iterator>
- static inline void SingleSubst_serialize (hb_serialize_context_t *c,
--					  hb_array_t<const GlyphID> glyphs,
--					  hb_array_t<const GlyphID> substitutes);
-+					  Iterator it);
-+
- 
- struct SingleSubstFormat1
- {
-   bool intersects (const hb_set_t *glyphs) const
-   { return (this+coverage).intersects (glyphs); }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      /* TODO Switch to range-based API to work around malicious fonts.
--       * https://github.com/harfbuzz/harfbuzz/issues/363 */
--      hb_codepoint_t glyph_id = iter.get_glyph ();
--      if (c->glyphs->has (glyph_id))
--	c->out->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
--    }
-+    unsigned d = deltaGlyphID;
-+    + hb_iter (this+coverage)
-+    | hb_filter (*c->glyphs)
-+    | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
-+    | hb_sink (c->output)
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      /* TODO Switch to range-based API to work around malicious fonts.
--       * https://github.com/harfbuzz/harfbuzz/issues/363 */
--      hb_codepoint_t glyph_id = iter.get_glyph ();
--      c->output->add ((glyph_id + deltaGlyphID) & 0xFFFFu);
--    }
-+    unsigned d = deltaGlyphID;
-+    + hb_iter (this+coverage)
-+    | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
-+    | hb_sink (c->output)
-+    ;
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
--  {
--    TRACE_WOULD_APPLY (this);
--    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
--  }
-+  { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
-     unsigned int index = (this+coverage).get_coverage (glyph_id);
-     if (likely (index == NOT_COVERED)) return_trace (false);
- 
-     /* According to the Adobe Annotated OpenType Suite, result is always
-      * limited to 16bit. */
-     glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
-     c->replace_glyph (glyph_id);
- 
-     return_trace (true);
-   }
- 
-+  template<typename Iterator,
-+	   hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs,
--		  int delta)
-+		  Iterator glyphs,
-+		  unsigned delta)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
--    deltaGlyphID.set (delta); /* TODO(serialize) overflow? */
-+    c->check_assign (deltaGlyphID, delta);
-     return_trace (true);
-   }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
--    const hb_set_t &glyphset = *c->plan->glyphset ();
-+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-     const hb_map_t &glyph_map = *c->plan->glyph_map;
--    hb_vector_t<GlyphID> from;
--    hb_vector_t<GlyphID> to;
-+
-     hb_codepoint_t delta = deltaGlyphID;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (!glyphset.has (iter.get_glyph ())) continue;
--      from.push ()->set (glyph_map[iter.get_glyph ()]);
--      to.push ()->set (glyph_map[(iter.get_glyph () + delta) & 0xFFFF]);
--    }
--    c->serializer->propagate_error (from, to);
--    SingleSubst_serialize (c->serializer, from, to);
--    return_trace (from.length);
-+
-+    auto it =
-+    + hb_iter (this+coverage)
-+    | hb_filter (glyphset)
-+    | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
-+				return hb_codepoint_pair_t (glyph_map[g],
-+							    glyph_map[(g + delta) & 0xFFFF]); })
-+    ;
-+
-+    bool ret = bool (it);
-+    SingleSubst_serialize (c->serializer, it);
-+    return_trace (ret);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
-   }
- 
-   protected:
-   HBUINT16	format;			/* Format identifier--format = 1 */
-   OffsetTo<Coverage>
- 		coverage;		/* Offset to Coverage table--from
- 					 * beginning of Substitution table */
--  HBINT16	deltaGlyphID;		/* Add to original GlyphID to get
--					 * substitute GlyphID */
-+  HBUINT16	deltaGlyphID;		/* Add to original GlyphID to get
-+					 * substitute GlyphID, modulo 0x10000 */
-   public:
-   DEFINE_SIZE_STATIC (6);
- };
- 
- struct SingleSubstFormat2
- {
-   bool intersects (const hb_set_t *glyphs) const
-   { return (this+coverage).intersects (glyphs); }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    unsigned int count = substitute.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (c->glyphs->has (iter.get_glyph ()))
--	c->out->add (substitute[iter.get_coverage ()]);
--    }
-+    + hb_zip (this+coverage, substitute)
-+    | hb_filter (*c->glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_sink (c->output)
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
--    unsigned int count = substitute.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      c->output->add (substitute[iter.get_coverage ()]);
--    }
-+    + hb_zip (this+coverage, substitute)
-+    | hb_map (hb_second)
-+    | hb_sink (c->output)
-+    ;
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
--  {
--    TRACE_WOULD_APPLY (this);
--    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
--  }
-+  { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-     if (likely (index == NOT_COVERED)) return_trace (false);
- 
-     if (unlikely (index >= substitute.len)) return_trace (false);
- 
-     c->replace_glyph (substitute[index]);
- 
-     return_trace (true);
-   }
- 
-+  template<typename Iterator,
-+	   hb_requires (hb_is_sorted_source_of (Iterator,
-+						hb_codepoint_pair_t))>
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs,
--		  hb_array_t<const GlyphID> substitutes)
-+		  Iterator it)
-   {
-     TRACE_SERIALIZE (this);
-+    auto substitutes =
-+      + it
-+      | hb_map (hb_second)
-+      ;
-+    auto glyphs =
-+      + it
-+      | hb_map_retains_sorting (hb_first)
-+      ;
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
-     if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
-     return_trace (true);
-   }
- 
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
--    const hb_set_t &glyphset = *c->plan->glyphset ();
-+    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-     const hb_map_t &glyph_map = *c->plan->glyph_map;
--    hb_vector_t<GlyphID> from;
--    hb_vector_t<GlyphID> to;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (!glyphset.has (iter.get_glyph ())) continue;
--      from.push ()->set (glyph_map[iter.get_glyph ()]);
--      to.push ()->set (glyph_map[substitute[iter.get_coverage ()]]);
--    }
--    c->serializer->propagate_error (from, to);
--    SingleSubst_serialize (c->serializer, from, to);
--    return_trace (from.length);
-+
-+    auto it =
-+    + hb_zip (this+coverage, substitute)
-+    | hb_filter (glyphset, hb_first)
-+    | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const GlyphID &> p) -> hb_codepoint_pair_t
-+			      { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
-+    ;
-+
-+    bool ret = bool (it);
-+    SingleSubst_serialize (c->serializer, it);
-+    return_trace (ret);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
-   }
- 
-@@ -232,76 +232,80 @@ struct SingleSubstFormat2
- 		substitute;		/* Array of substitute
- 					 * GlyphIDs--ordered by Coverage Index */
-   public:
-   DEFINE_SIZE_ARRAY (6, substitute);
- };
- 
- struct SingleSubst
- {
-+
-+  template<typename Iterator,
-+	   hb_requires (hb_is_sorted_source_of (Iterator,
-+						const hb_codepoint_pair_t))>
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs,
--		  hb_array_t<const GlyphID> substitutes)
-+		  Iterator glyphs)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (u.format))) return_trace (false);
--    unsigned int format = 2;
--    int delta = 0;
--    if (glyphs.length)
-+    unsigned format = 2;
-+    unsigned delta = 0;
-+    if (glyphs.len ())
-     {
-       format = 1;
--      /* TODO(serialize) check for wrap-around */
--      delta = substitutes[0] - glyphs[0];
--      for (unsigned int i = 1; i < glyphs.length; i++)
--	if (delta != (int) (substitutes[i] - glyphs[i])) {
--	  format = 2;
--	  break;
--	}
-+      auto get_delta = [=] (hb_codepoint_pair_t _) {
-+			 return (unsigned) (_.second - _.first) & 0xFFFF;
-+		       };
-+      delta = get_delta (*glyphs);
-+      if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
-     }
--    u.format.set (format);
-+    u.format = format;
-     switch (u.format) {
--    case 1: return_trace (u.format1.serialize (c, glyphs, delta));
--    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes));
-+    case 1: return_trace (u.format1.serialize (c,
-+					       + glyphs
-+					       | hb_map_retains_sorting (hb_first),
-+					       delta));
-+    case 2: return_trace (u.format2.serialize (c, glyphs));
-     default:return_trace (false);
-     }
-   }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
--    case 2: return_trace (c->dispatch (u.format2));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   SingleSubstFormat1	format1;
-   SingleSubstFormat2	format2;
-   } u;
- };
- 
-+template<typename Iterator>
- static inline void
- SingleSubst_serialize (hb_serialize_context_t *c,
--		       hb_array_t<const GlyphID> glyphs,
--		       hb_array_t<const GlyphID> substitutes)
--{ c->start_embed<SingleSubst> ()->serialize (c, glyphs, substitutes); }
-+		       Iterator it)
-+{ c->start_embed<SingleSubst> ()->serialize (c, it); }
- 
- struct Sequence
- {
-   void closure (hb_closure_context_t *c) const
-   {
-     unsigned int count = substitute.len;
-     for (unsigned int i = 0; i < count; i++)
--      c->out->add (substitute[i]);
-+      c->output->add (substitute[i]);
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   { c->output->add_array (substitute.arrayZ, substitute.len); }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-@@ -329,21 +333,23 @@ struct Sequence
-       _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
-       c->output_glyph_for_component (substitute.arrayZ[i], klass);
-     }
-     c->buffer->skip_glyph ();
- 
-     return_trace (true);
-   }
- 
-+  template <typename Iterator,
-+	    hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs)
-+		  Iterator subst)
-   {
-     TRACE_SERIALIZE (this);
--    return_trace (substitute.serialize (c, glyphs));
-+    return_trace (substitute.serialize (c, subst));
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (substitute.sanitize (c));
-   }
- 
-@@ -356,54 +362,51 @@ struct Sequence
- 
- struct MultipleSubstFormat1
- {
-   bool intersects (const hb_set_t *glyphs) const
-   { return (this+coverage).intersects (glyphs); }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    unsigned int count = sequence.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (c->glyphs->has (iter.get_glyph ()))
--	(this+sequence[iter.get_coverage ()]).closure (c);
--    }
-+    + hb_zip (this+coverage, sequence)
-+    | hb_filter (*c->glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([c] (const Sequence &_) { _.closure (c); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
--    unsigned int count = sequence.len;
--    for (unsigned int i = 0; i < count; i++)
--      (this+sequence[i]).collect_glyphs (c);
-+    + hb_zip (this+coverage, sequence)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
-+    ;
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
--  {
--    TRACE_WOULD_APPLY (this);
--    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
--  }
-+  { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
- 
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-     if (likely (index == NOT_COVERED)) return_trace (false);
- 
-     return_trace ((this+sequence[index]).apply (c));
-   }
- 
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs,
-+		  hb_sorted_array_t<const GlyphID> glyphs,
- 		  hb_array_t<const unsigned int> substitute_len_list,
- 		  hb_array_t<const GlyphID> substitute_glyphs_list)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
-     for (unsigned int i = 0; i < glyphs.length; i++)
-     {
-@@ -439,37 +442,37 @@ struct MultipleSubstFormat1
- 					 * ordered by Coverage Index */
-   public:
-   DEFINE_SIZE_ARRAY (6, sequence);
- };
- 
- struct MultipleSubst
- {
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs,
-+		  hb_sorted_array_t<const GlyphID> glyphs,
- 		  hb_array_t<const unsigned int> substitute_len_list,
- 		  hb_array_t<const GlyphID> substitute_glyphs_list)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (u.format))) return_trace (false);
-     unsigned int format = 1;
--    u.format.set (format);
-+    u.format = format;
-     switch (u.format) {
-     case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
-     default:return_trace (false);
-     }
-   }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   MultipleSubstFormat1	format1;
-@@ -477,17 +480,17 @@ struct MultipleSubst
- };
- 
- struct AlternateSet
- {
-   void closure (hb_closure_context_t *c) const
-   {
-     unsigned int count = alternates.len;
-     for (unsigned int i = 0; i < count; i++)
--      c->out->add (alternates[i]);
-+      c->output->add (alternates[i]);
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   { c->output->add_array (alternates.arrayZ, alternates.len); }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-@@ -497,32 +500,34 @@ struct AlternateSet
- 
-     hb_mask_t glyph_mask = c->buffer->cur().mask;
-     hb_mask_t lookup_mask = c->lookup_mask;
- 
-     /* Note: This breaks badly if two features enabled this lookup together. */
-     unsigned int shift = hb_ctz (lookup_mask);
-     unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
- 
--    /* If alt_index is MAX, randomize feature if it is the rand feature. */
-+    /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
-     if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
-       alt_index = c->random_number () % count + 1;
- 
-     if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
- 
-     c->replace_glyph (alternates[alt_index - 1]);
- 
-     return_trace (true);
-   }
- 
-+  template <typename Iterator,
-+	    hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs)
-+		  Iterator alts)
-   {
-     TRACE_SERIALIZE (this);
--    return_trace (alternates.serialize (c, glyphs));
-+    return_trace (alternates.serialize (c, alts));
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (alternates.sanitize (c));
-   }
- 
-@@ -536,58 +541,50 @@ struct AlternateSet
- 
- struct AlternateSubstFormat1
- {
-   bool intersects (const hb_set_t *glyphs) const
-   { return (this+coverage).intersects (glyphs); }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    unsigned int count = alternateSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (c->glyphs->has (iter.get_glyph ()))
--	(this+alternateSet[iter.get_coverage ()]).closure (c);
--    }
-+    + hb_zip (this+coverage, alternateSet)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
--    unsigned int count = alternateSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      (this+alternateSet[iter.get_coverage ()]).collect_glyphs (c);
--    }
-+    + hb_zip (this+coverage, alternateSet)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
-+    ;
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
--  {
--    TRACE_WOULD_APPLY (this);
--    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
--  }
-+  { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
- 
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-     if (likely (index == NOT_COVERED)) return_trace (false);
- 
-     return_trace ((this+alternateSet[index]).apply (c));
-   }
- 
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs,
-+		  hb_sorted_array_t<const GlyphID> glyphs,
- 		  hb_array_t<const unsigned int> alternate_len_list,
- 		  hb_array_t<const GlyphID> alternate_glyphs_list)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
-     for (unsigned int i = 0; i < glyphs.length; i++)
-     {
-@@ -623,37 +620,37 @@ struct AlternateSubstFormat1
- 					 * ordered by Coverage Index */
-   public:
-   DEFINE_SIZE_ARRAY (6, alternateSet);
- };
- 
- struct AlternateSubst
- {
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> glyphs,
-+		  hb_sorted_array_t<const GlyphID> glyphs,
- 		  hb_array_t<const unsigned int> alternate_len_list,
- 		  hb_array_t<const GlyphID> alternate_glyphs_list)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (u.format))) return_trace (false);
-     unsigned int format = 1;
--    u.format.set (format);
-+    u.format = format;
-     switch (u.format) {
-     case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
-     default:return_trace (false);
-     }
-   }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   AlternateSubstFormat1	format1;
-@@ -663,46 +660,42 @@ struct AlternateSubst
- 
- struct Ligature
- {
-   bool intersects (const hb_set_t *glyphs) const
-   {
-     unsigned int count = component.lenP1;
-     for (unsigned int i = 1; i < count; i++)
-       if (!glyphs->has (component[i]))
--        return false;
-+	return false;
-     return true;
-   }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    unsigned int count = component.lenP1;
--    for (unsigned int i = 1; i < count; i++)
--      if (!c->glyphs->has (component[i]))
--        return;
--    c->out->add (ligGlyph);
-+    if (!intersects (c->glyphs)) return;
-+    c->output->add (ligGlyph);
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     c->input->add_array (component.arrayZ, component.lenP1 ? component.lenP1 - 1 : 0);
-     c->output->add (ligGlyph);
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
-     if (c->len != component.lenP1)
--      return_trace (false);
-+      return false;
- 
-     for (unsigned int i = 1; i < c->len; i++)
-       if (likely (c->glyphs[i] != component[i]))
--	return_trace (false);
-+	return false;
- 
--    return_trace (true);
-+    return true;
-   }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     unsigned int count = component.lenP1;
- 
-     if (unlikely (!count)) return_trace (false);
-@@ -734,19 +727,21 @@ struct Ligature
- 		  match_positions,
- 		  match_length,
- 		  ligGlyph,
- 		  total_component_count);
- 
-     return_trace (true);
-   }
- 
-+  template <typename Iterator,
-+	    hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
-   bool serialize (hb_serialize_context_t *c,
- 		  GlyphID ligature,
--		  hb_array_t<const GlyphID> components /* Starting from second */)
-+		  Iterator components /* Starting from second */)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     ligGlyph = ligature;
-     if (unlikely (!component.serialize (c, components))) return_trace (false);
-     return_trace (true);
-   }
- 
-@@ -766,48 +761,48 @@ struct Ligature
-   public:
-   DEFINE_SIZE_ARRAY (4, component);
- };
- 
- struct LigatureSet
- {
-   bool intersects (const hb_set_t *glyphs) const
-   {
--    unsigned int num_ligs = ligature.len;
--    for (unsigned int i = 0; i < num_ligs; i++)
--      if ((this+ligature[i]).intersects (glyphs))
--        return true;
--    return false;
-+    return
-+    + hb_iter (ligature)
-+    | hb_map (hb_add (this))
-+    | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
-+    | hb_any
-+    ;
-   }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    unsigned int num_ligs = ligature.len;
--    for (unsigned int i = 0; i < num_ligs; i++)
--      (this+ligature[i]).closure (c);
-+    + hb_iter (ligature)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([c] (const Ligature &_) { _.closure (c); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
--    unsigned int num_ligs = ligature.len;
--    for (unsigned int i = 0; i < num_ligs; i++)
--      (this+ligature[i]).collect_glyphs (c);
-+    + hb_iter (ligature)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
-+    ;
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
--    unsigned int num_ligs = ligature.len;
--    for (unsigned int i = 0; i < num_ligs; i++)
--    {
--      const Ligature &lig = this+ligature[i];
--      if (lig.would_apply (c))
--        return_trace (true);
--    }
--    return_trace (false);
-+    return
-+    + hb_iter (ligature)
-+    | hb_map (hb_add (this))
-+    | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
-+    | hb_any
-+    ;
-   }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     unsigned int num_ligs = ligature.len;
-     for (unsigned int i = 0; i < num_ligs; i++)
-     {
-@@ -823,17 +818,17 @@ struct LigatureSet
- 		  hb_array_t<const unsigned int> component_count_list,
- 		  hb_array_t<const GlyphID> &component_list /* Starting from second for each ligature */)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
-     for (unsigned int i = 0; i < ligatures.length; i++)
-     {
--      unsigned int component_count = MAX<int> (component_count_list[i] - 1, 0);
-+      unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
-       if (unlikely (!ligature[i].serialize (c, this)
- 				.serialize (c,
- 					    ligatures[i],
- 					    component_list.sub_array (0, component_count))))
- 	return_trace (false);
-       component_list += component_count;
-     }
-     return_trace (true);
-@@ -852,77 +847,71 @@ struct LigatureSet
-   public:
-   DEFINE_SIZE_ARRAY (2, ligature);
- };
- 
- struct LigatureSubstFormat1
- {
-   bool intersects (const hb_set_t *glyphs) const
-   {
--    unsigned int count = ligatureSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (glyphs->has (iter.get_glyph ()) &&
--	  (this+ligatureSet[iter.get_coverage ()]).intersects (glyphs))
--        return true;
--    }
--    return false;
-+    return
-+    + hb_zip (this+coverage, ligatureSet)
-+    | hb_filter (*glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_map ([this, glyphs] (const OffsetTo<LigatureSet> &_)
-+	      { return (this+_).intersects (glyphs); })
-+    | hb_any
-+    ;
-   }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    unsigned int count = ligatureSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (c->glyphs->has (iter.get_glyph ()))
--	(this+ligatureSet[iter.get_coverage ()]).closure (c);
--    }
-+    + hb_zip (this+coverage, ligatureSet)
-+    | hb_filter (*c->glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
--    unsigned int count = ligatureSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      (this+ligatureSet[iter.get_coverage ()]).collect_glyphs (c);
--    }
-+
-+    + hb_zip (this+coverage, ligatureSet)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
-+    ;
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
-     unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
--    if (likely (index == NOT_COVERED)) return_trace (false);
-+    if (likely (index == NOT_COVERED)) return false;
- 
-     const LigatureSet &lig_set = this+ligatureSet[index];
--    return_trace (lig_set.would_apply (c));
-+    return lig_set.would_apply (c);
-   }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
- 
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-     if (likely (index == NOT_COVERED)) return_trace (false);
- 
-     const LigatureSet &lig_set = this+ligatureSet[index];
-     return_trace (lig_set.apply (c));
-   }
- 
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> first_glyphs,
-+		  hb_sorted_array_t<const GlyphID> first_glyphs,
- 		  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- 		  hb_array_t<const GlyphID> ligatures_list,
- 		  hb_array_t<const unsigned int> component_count_list,
- 		  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
-@@ -963,44 +952,44 @@ struct LigatureSubstFormat1
- 					 * ordered by Coverage Index */
-   public:
-   DEFINE_SIZE_ARRAY (6, ligatureSet);
- };
- 
- struct LigatureSubst
- {
-   bool serialize (hb_serialize_context_t *c,
--		  hb_array_t<const GlyphID> first_glyphs,
-+		  hb_sorted_array_t<const GlyphID> first_glyphs,
- 		  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- 		  hb_array_t<const GlyphID> ligatures_list,
- 		  hb_array_t<const unsigned int> component_count_list,
- 		  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (u.format))) return_trace (false);
-     unsigned int format = 1;
--    u.format.set (format);
-+    u.format = format;
-     switch (u.format) {
-     case 1: return_trace (u.format1.serialize (c,
- 					       first_glyphs,
- 					       ligature_per_first_glyph_count_list,
- 					       ligatures_list,
- 					       component_count_list,
- 					       component_list));
-     default:return_trace (false);
-     }
-   }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   LigatureSubstFormat1	format1;
-@@ -1022,106 +1011,90 @@ struct ExtensionSubst : Extension<Extens
- 
- struct ReverseChainSingleSubstFormat1
- {
-   bool intersects (const hb_set_t *glyphs) const
-   {
-     if (!(this+coverage).intersects (glyphs))
-       return false;
- 
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
- 
-     unsigned int count;
- 
-     count = backtrack.len;
-     for (unsigned int i = 0; i < count; i++)
-       if (!(this+backtrack[i]).intersects (glyphs))
--        return false;
-+	return false;
- 
-     count = lookahead.len;
-     for (unsigned int i = 0; i < count; i++)
-       if (!(this+lookahead[i]).intersects (glyphs))
--        return false;
-+	return false;
- 
-     return true;
-   }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
--
--    unsigned int count;
-+    if (!intersects (c->glyphs)) return;
- 
--    count = backtrack.len;
--    for (unsigned int i = 0; i < count; i++)
--      if (!(this+backtrack[i]).intersects (c->glyphs))
--        return;
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID>> (lookahead);
- 
--    count = lookahead.len;
--    for (unsigned int i = 0; i < count; i++)
--      if (!(this+lookahead[i]).intersects (c->glyphs))
--        return;
--
--    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
--    count = substitute.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--        break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (c->glyphs->has (iter.get_glyph ()))
--	c->out->add (substitute[iter.get_coverage ()]);
--    }
-+    + hb_zip (this+coverage, substitute)
-+    | hb_filter (*c->glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_sink (c->output)
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     if (unlikely (!(this+coverage).add_coverage (c->input))) return;
- 
-     unsigned int count;
- 
-     count = backtrack.len;
-     for (unsigned int i = 0; i < count; i++)
-       if (unlikely (!(this+backtrack[i]).add_coverage (c->before))) return;
- 
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-     count = lookahead.len;
-     for (unsigned int i = 0; i < count; i++)
-       if (unlikely (!(this+lookahead[i]).add_coverage (c->after))) return;
- 
--    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID>> (lookahead);
-     count = substitute.len;
-     c->output->add_array (substitute.arrayZ, substitute.len);
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
--  {
--    TRACE_WOULD_APPLY (this);
--    return_trace (c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED);
--  }
-+  { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
-       return_trace (false); /* No chaining to this type */
- 
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-     if (likely (index == NOT_COVERED)) return_trace (false);
- 
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
--    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID>> (lookahead);
- 
-   unsigned int start_index = 0, end_index = 0;
-     if (match_backtrack (c,
- 			 backtrack.len, (HBUINT16 *) backtrack.arrayZ,
- 			 match_coverage, this,
- 			 &start_index) &&
--        match_lookahead (c,
-+	match_lookahead (c,
- 			 lookahead.len, (HBUINT16 *) lookahead.arrayZ,
- 			 match_coverage, this,
- 			 1, &end_index))
-     {
-       c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
-       c->replace_glyph_inplace (substitute[index]);
-       /* Note: We DON'T decrease buffer->idx.  The main loop does it
-        * for us.  This is useful for preventing surprises if someone
-@@ -1139,20 +1112,20 @@ struct ReverseChainSingleSubstFormat1
-     return_trace (false);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
-       return_trace (false);
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-     if (!lookahead.sanitize (c, this))
-       return_trace (false);
--    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
-+    const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID>> (lookahead);
-     return_trace (substitute.sanitize (c));
-   }
- 
-   protected:
-   HBUINT16	format;			/* Format identifier--format = 1 */
-   OffsetTo<Coverage>
- 		coverage;		/* Offset to Coverage table--from
- 					 * beginning of table */
-@@ -1168,23 +1141,23 @@ struct ReverseChainSingleSubstFormat1
- 		substituteX;		/* Array of substitute
- 					 * GlyphIDs--ordered by Coverage Index */
-   public:
-   DEFINE_SIZE_MIN (10);
- };
- 
- struct ReverseChainSingleSubst
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16				format;		/* Format identifier */
-   ReverseChainSingleSubstFormat1	format1;
-@@ -1208,29 +1181,29 @@ struct SubstLookupSubTable
-     Alternate		= 3,
-     Ligature		= 4,
-     Context		= 5,
-     ChainContext	= 6,
-     Extension		= 7,
-     ReverseChainSingle	= 8
-   };
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, lookup_type);
-     switch (lookup_type) {
--    case Single:		return_trace (u.single.dispatch (c));
--    case Multiple:		return_trace (u.multiple.dispatch (c));
--    case Alternate:		return_trace (u.alternate.dispatch (c));
--    case Ligature:		return_trace (u.ligature.dispatch (c));
--    case Context:		return_trace (u.context.dispatch (c));
--    case ChainContext:		return_trace (u.chainContext.dispatch (c));
--    case Extension:		return_trace (u.extension.dispatch (c));
--    case ReverseChainSingle:	return_trace (u.reverseChainContextSingle.dispatch (c));
-+    case Single:		return_trace (u.single.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Multiple:		return_trace (u.multiple.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Alternate:		return_trace (u.alternate.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Ligature:		return_trace (u.ligature.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Context:		return_trace (u.context.dispatch (c, hb_forward<Ts> (ds)...));
-+    case ChainContext:		return_trace (u.chainContext.dispatch (c, hb_forward<Ts> (ds)...));
-+    case Extension:		return_trace (u.extension.dispatch (c, hb_forward<Ts> (ds)...));
-+    case ReverseChainSingle:	return_trace (u.reverseChainContextSingle.dispatch (c, hb_forward<Ts> (ds)...));
-     default:			return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   SingleSubst			single;
-   MultipleSubst			multiple;
-@@ -1248,17 +1221,17 @@ struct SubstLookupSubTable
- 
- struct SubstLookup : Lookup
- {
-   typedef SubstLookupSubTable SubTable;
- 
-   const SubTable& get_subtable (unsigned int i) const
-   { return Lookup::get_subtable<SubTable> (i); }
- 
--  static bool lookup_type_is_reverse (unsigned int lookup_type)
-+  HB_INTERNAL static bool lookup_type_is_reverse (unsigned int lookup_type)
-   { return lookup_type == SubTable::ReverseChainSingle; }
- 
-   bool is_reverse () const
-   {
-     unsigned int type = get_type ();
-     if (unlikely (type == SubTable::Extension))
-       return CastR<ExtensionSubst> (get_subtable(0)).is_reverse ();
-     return lookup_type_is_reverse (type);
-@@ -1301,105 +1274,108 @@ struct SubstLookup : Lookup
-   {
-     hb_add_coverage_context_t<set_t> c (glyphs);
-     dispatch (&c);
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c,
- 		    const hb_ot_layout_lookup_accelerator_t *accel) const
-   {
--    TRACE_WOULD_APPLY (this);
--    if (unlikely (!c->len))  return_trace (false);
--    if (!accel->may_have (c->glyphs[0]))  return_trace (false);
--      return_trace (dispatch (c));
-+    if (unlikely (!c->len)) return false;
-+    if (!accel->may_have (c->glyphs[0])) return false;
-+      return dispatch (c);
-   }
- 
--  static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-+  HB_INTERNAL static bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
- 
-   SubTable& serialize_subtable (hb_serialize_context_t *c,
--				       unsigned int i)
-+				unsigned int i)
-   { return get_subtables<SubTable> ()[i].serialize (c, this); }
- 
-   bool serialize_single (hb_serialize_context_t *c,
- 			 uint32_t lookup_props,
--		         hb_array_t<const GlyphID> glyphs,
--		         hb_array_t<const GlyphID> substitutes)
-+			 hb_sorted_array_t<const GlyphID> glyphs,
-+			 hb_array_t<const GlyphID> substitutes)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
--    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes));
-+    return_trace (serialize_subtable (c, 0).u.single.
-+		  serialize (c, hb_zip (glyphs, substitutes)));
-   }
- 
-   bool serialize_multiple (hb_serialize_context_t *c,
- 			   uint32_t lookup_props,
--			   hb_array_t<const GlyphID> glyphs,
-+			   hb_sorted_array_t<const GlyphID> glyphs,
- 			   hb_array_t<const unsigned int> substitute_len_list,
- 			   hb_array_t<const GlyphID> substitute_glyphs_list)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
--    return_trace (serialize_subtable (c, 0).u.multiple.serialize (c,
--								  glyphs,
--								  substitute_len_list,
--								  substitute_glyphs_list));
-+    return_trace (serialize_subtable (c, 0).u.multiple.
-+		  serialize (c,
-+			     glyphs,
-+			     substitute_len_list,
-+			     substitute_glyphs_list));
-   }
- 
-   bool serialize_alternate (hb_serialize_context_t *c,
- 			    uint32_t lookup_props,
--			    hb_array_t<const GlyphID> glyphs,
-+			    hb_sorted_array_t<const GlyphID> glyphs,
- 			    hb_array_t<const unsigned int> alternate_len_list,
- 			    hb_array_t<const GlyphID> alternate_glyphs_list)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
--    return_trace (serialize_subtable (c, 0).u.alternate.serialize (c,
--								   glyphs,
--								   alternate_len_list,
--								   alternate_glyphs_list));
-+    return_trace (serialize_subtable (c, 0).u.alternate.
-+		  serialize (c,
-+			     glyphs,
-+			     alternate_len_list,
-+			     alternate_glyphs_list));
-   }
- 
-   bool serialize_ligature (hb_serialize_context_t *c,
- 			   uint32_t lookup_props,
--			   hb_array_t<const GlyphID> first_glyphs,
-+			   hb_sorted_array_t<const GlyphID> first_glyphs,
- 			   hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- 			   hb_array_t<const GlyphID> ligatures_list,
- 			   hb_array_t<const unsigned int> component_count_list,
- 			   hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
--    return_trace (serialize_subtable (c, 0).u.ligature.serialize (c,
--								  first_glyphs,
--								  ligature_per_first_glyph_count_list,
--								  ligatures_list,
--								  component_count_list,
--								  component_list));
-+    return_trace (serialize_subtable (c, 0).u.ligature.
-+		  serialize (c,
-+			     first_glyphs,
-+			     ligature_per_first_glyph_count_list,
-+			     ligatures_list,
-+			     component_count_list,
-+			     component_list));
-   }
- 
-   template <typename context_t>
--  static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-+  HB_INTERNAL static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
- 
--  static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
-+  HB_INTERNAL static hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned int lookup_index)
-   {
-     if (!c->should_visit_lookup (lookup_index))
--      return HB_VOID;
-+      return hb_empty_t ();
- 
-     hb_closure_context_t::return_t ret = dispatch_recurse_func (c, lookup_index);
- 
-     /* While in theory we should flush here, it will cause timeouts because a recursive
-      * lookup can keep growing the glyph set.  Skip, and outer loop will retry up to
-      * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
-     //c->flush ();
- 
-     return ret;
-   }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
--  { return Lookup::dispatch<SubTable> (c); }
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-+  { return Lookup::dispatch<SubTable> (c, hb_forward<Ts> (ds)...); }
- 
-   bool subset (hb_subset_context_t *c) const
-   { return Lookup::subset<SubTable> (c); }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   { return Lookup::sanitize<SubTable> (c); }
- };
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
-@@ -54,23 +54,23 @@ struct hb_intersects_context_t :
-   unsigned int debug_depth;
- 
-   hb_intersects_context_t (const hb_set_t *glyphs_) :
- 			     glyphs (glyphs_),
- 			     debug_depth (0) {}
- };
- 
- struct hb_closure_context_t :
--       hb_dispatch_context_t<hb_closure_context_t, hb_void_t, 0>
-+       hb_dispatch_context_t<hb_closure_context_t, hb_empty_t, 0>
- {
-   const char *get_name () { return "CLOSURE"; }
-   typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
-   template <typename T>
--  return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
--  static return_t default_return_value () { return HB_VOID; }
-+  return_t dispatch (const T &obj) { obj.closure (this); return hb_empty_t (); }
-+  static return_t default_return_value () { return hb_empty_t (); }
-   void recurse (unsigned int lookup_index)
-   {
-     if (unlikely (nesting_level_left == 0 || !recurse_func))
-       return;
- 
-     nesting_level_left--;
-     recurse_func (this, lookup_index);
-     nesting_level_left++;
-@@ -87,17 +87,17 @@ struct hb_closure_context_t :
-   bool is_lookup_done (unsigned int lookup_index)
-   {
-     /* Have we visited this lookup with the current set of glyphs? */
-     return done_lookups->get (lookup_index) == glyphs->get_population ();
-   }
- 
-   hb_face_t *face;
-   hb_set_t *glyphs;
--  hb_set_t out[1];
-+  hb_set_t output[1];
-   recurse_func_t recurse_func;
-   unsigned int nesting_level_left;
-   unsigned int debug_depth;
- 
-   hb_closure_context_t (hb_face_t *face_,
- 			hb_set_t *glyphs_,
- 			hb_map_t *done_lookups_,
- 			unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
-@@ -109,27 +109,27 @@ struct hb_closure_context_t :
- 			  done_lookups (done_lookups_) {}
- 
-   ~hb_closure_context_t () { flush (); }
- 
-   void set_recurse_func (recurse_func_t func) { recurse_func = func; }
- 
-   void flush ()
-   {
--    hb_set_union (glyphs, out);
--    hb_set_clear (out);
-+    hb_set_union (glyphs, output);
-+    hb_set_clear (output);
-   }
- 
-   private:
-   hb_map_t *done_lookups;
- };
- 
- 
- struct hb_would_apply_context_t :
--       hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
-+       hb_dispatch_context_t<hb_would_apply_context_t, bool, 0>
- {
-   const char *get_name () { return "WOULD_APPLY"; }
-   template <typename T>
-   return_t dispatch (const T &obj) { return obj.would_apply (this); }
-   static return_t default_return_value () { return false; }
-   bool stop_sublookup_iteration (return_t r) const { return r; }
- 
-   hb_face_t *face;
-@@ -146,23 +146,23 @@ struct hb_would_apply_context_t :
- 			      glyphs (glyphs_),
- 			      len (len_),
- 			      zero_context (zero_context_),
- 			      debug_depth (0) {}
- };
- 
- 
- struct hb_collect_glyphs_context_t :
--       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, 0>
-+       hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_empty_t, 0>
- {
-   const char *get_name () { return "COLLECT_GLYPHS"; }
-   typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
-   template <typename T>
--  return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
--  static return_t default_return_value () { return HB_VOID; }
-+  return_t dispatch (const T &obj) { obj.collect_glyphs (this); return hb_empty_t (); }
-+  static return_t default_return_value () { return hb_empty_t (); }
-   void recurse (unsigned int lookup_index)
-   {
-     if (unlikely (nesting_level_left == 0 || !recurse_func))
-       return;
- 
-     /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
-      * past the previous check.  For GSUB, we only want to collect the output
-      * glyphs in the recursion.  If output is not requested, we can go home now.
-@@ -281,17 +281,17 @@ struct hb_ot_apply_context_t :
- 
-     enum may_match_t {
-       MATCH_NO,
-       MATCH_YES,
-       MATCH_MAYBE
-     };
- 
-     may_match_t may_match (const hb_glyph_info_t &info,
--				  const HBUINT16        *glyph_data) const
-+			   const HBUINT16        *glyph_data) const
-     {
-       if (!(info.mask & mask) ||
- 	  (syllable && syllable != info.syllable ()))
- 	return MATCH_NO;
- 
-       if (match_func)
- 	return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
- 
-@@ -605,20 +605,20 @@ struct hb_ot_apply_context_t :
-   {
-     _set_glyph_props (glyph_index, class_guess, false, true);
-     buffer->output_glyph (glyph_index);
-   }
- };
- 
- 
- struct hb_get_subtables_context_t :
--       hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
-+       hb_dispatch_context_t<hb_get_subtables_context_t, hb_empty_t, HB_DEBUG_APPLY>
- {
-   template <typename Type>
--  static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
-+  HB_INTERNAL static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
-   {
-     const Type *typed_obj = (const Type *) obj;
-     return typed_obj->apply (c);
-   }
- 
-   typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
- 
-   struct hb_applicable_t
-@@ -647,19 +647,19 @@ struct hb_get_subtables_context_t :
- 
-   /* Dispatch interface. */
-   const char *get_name () { return "GET_SUBTABLES"; }
-   template <typename T>
-   return_t dispatch (const T &obj)
-   {
-     hb_applicable_t *entry = array.push();
-     entry->init (obj, apply_to<T>);
--    return HB_VOID;
-+    return hb_empty_t ();
-   }
--  static return_t default_return_value () { return HB_VOID; }
-+  static return_t default_return_value () { return hb_empty_t (); }
- 
-   hb_get_subtables_context_t (array_t &array_) :
- 			      array (array_),
- 			      debug_depth (0) {}
- 
-   array_t &array;
-   unsigned int debug_depth;
- };
-@@ -701,20 +701,21 @@ static inline bool intersects_coverage (
- }
- 
- static inline bool intersects_array (const hb_set_t *glyphs,
- 				     unsigned int count,
- 				     const HBUINT16 values[],
- 				     intersects_func_t intersects_func,
- 				     const void *intersects_data)
- {
--  for (unsigned int i = 0; i < count; i++)
--    if (likely (!intersects_func (glyphs, values[i], intersects_data)))
--      return false;
--  return true;
-+  return
-+  + hb_iter (values, count)
-+  | hb_map ([&] (const HBUINT16 &_) { return intersects_func (glyphs, _, intersects_data); })
-+  | hb_any
-+  ;
- }
- 
- 
- static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
- {
-   glyphs->add (value);
- }
- static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
-@@ -729,18 +730,20 @@ static inline void collect_coverage (hb_
- }
- static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
- 				  hb_set_t *glyphs,
- 				  unsigned int count,
- 				  const HBUINT16 values[],
- 				  collect_glyphs_func_t collect_func,
- 				  const void *collect_data)
- {
--  for (unsigned int i = 0; i < count; i++)
--    collect_func (glyphs, values[i], collect_data);
-+  return
-+  + hb_iter (values, count)
-+  | hb_apply ([&] (const HBUINT16 &_) { collect_func (glyphs, _, collect_data); })
-+  ;
- }
- 
- 
- static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
- {
-   return glyph_id == value;
- }
- static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
-@@ -841,17 +844,17 @@ static inline bool match_input (hb_ot_ap
-        * component, otherwise we shouldn't ligate them... */
-       if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
-       {
- 	/* ...unless, we are attached to a base ligature and that base
- 	 * ligature is ignorable. */
- 	if (ligbase == LIGBASE_NOT_CHECKED)
- 	{
- 	  bool found = false;
--	  const hb_glyph_info_t *out = buffer->out_info;
-+	  const auto *out = buffer->out_info;
- 	  unsigned int j = buffer->out_len;
- 	  while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
- 	  {
- 	    if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
- 	    {
- 	      j--;
- 	      found = true;
- 	      break;
-@@ -965,17 +968,17 @@ static inline bool ligate_input (hb_ot_a
-     while (buffer->idx < match_positions[i] && buffer->successful)
-     {
-       if (is_ligature)
-       {
- 	unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
- 	if (this_comp == 0)
- 	  this_comp = last_num_components;
- 	unsigned int new_lig_comp = components_so_far - last_num_components +
--				    MIN (this_comp, last_num_components);
-+				    hb_min (this_comp, last_num_components);
- 	  _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
-       }
-       buffer->next_glyph ();
-     }
- 
-     last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
-     last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
-     components_so_far += last_num_components;
-@@ -987,17 +990,17 @@ static inline bool ligate_input (hb_ot_a
-   if (!is_mark_ligature && last_lig_id) {
-     /* Re-adjust components for any marks following. */
-     for (unsigned int i = buffer->idx; i < buffer->len; i++) {
-       if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
- 	unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
- 	if (!this_comp)
- 	  break;
- 	unsigned int new_lig_comp = components_so_far - last_num_components +
--				    MIN (this_comp, last_num_components);
-+				    hb_min (this_comp, last_num_components);
- 	_hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
-       } else
- 	break;
-     }
-   }
-   return_trace (true);
- }
- 
-@@ -1165,17 +1168,17 @@ static inline bool apply_lookup (hb_ot_a
-     if (delta > 0)
-     {
-       if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
- 	break;
-     }
-     else
-     {
-       /* NOTE: delta is negative. */
--      delta = MAX (delta, (int) next - (int) count);
-+      delta = hb_max (delta, (int) next - (int) count);
-       next -= delta;
-     }
- 
-     /* Shift! */
-     memmove (match_positions + next + delta, match_positions + next,
- 	     (count - next) * sizeof (match_positions[0]));
-     next += delta;
-     count += delta;
-@@ -1291,49 +1294,51 @@ struct Rule
-   {
-     return context_intersects (glyphs,
- 			       inputCount, inputZ.arrayZ,
- 			       lookup_context);
-   }
- 
-   void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
-   {
--    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
-+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- 						       (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
-     context_closure_lookup (c,
- 			    inputCount, inputZ.arrayZ,
- 			    lookupCount, lookupRecord.arrayZ,
- 			    lookup_context);
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c,
- 		       ContextCollectGlyphsLookupContext &lookup_context) const
-   {
--    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
-+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
-     context_collect_glyphs_lookup (c,
- 				   inputCount, inputZ.arrayZ,
- 				   lookupCount, lookupRecord.arrayZ,
- 				   lookup_context);
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c,
- 		    ContextApplyLookupContext &lookup_context) const
-   {
--    TRACE_WOULD_APPLY (this);
--    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
-+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
--    return_trace (context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
-+    return context_would_apply_lookup (c,
-+				       inputCount, inputZ.arrayZ,
-+				       lookupCount, lookupRecord.arrayZ,
-+				       lookup_context);
-   }
- 
-   bool apply (hb_ot_apply_context_t *c,
- 	      ContextApplyLookupContext &lookup_context) const
-   {
-     TRACE_APPLY (this);
--    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
-+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- 						       (inputZ.as_array (inputCount ? inputCount - 1 : 0));
-     return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
-   }
- 
-   public:
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-@@ -1359,63 +1364,66 @@ struct Rule
-   DEFINE_SIZE_ARRAY (4, inputZ);
- };
- 
- struct RuleSet
- {
-   bool intersects (const hb_set_t *glyphs,
- 		   ContextClosureLookupContext &lookup_context) const
-   {
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--      if ((this+rule[i]).intersects (glyphs, lookup_context))
--	return true;
--    return false;
-+    return
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_map ([&] (const Rule &_) { return _.intersects (glyphs, lookup_context); })
-+    | hb_any
-+    ;
-   }
- 
-   void closure (hb_closure_context_t *c,
- 		ContextClosureLookupContext &lookup_context) const
-   {
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--      (this+rule[i]).closure (c, lookup_context);
-+    return
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const Rule &_) { _.closure (c, lookup_context); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c,
- 		       ContextCollectGlyphsLookupContext &lookup_context) const
-   {
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--      (this+rule[i]).collect_glyphs (c, lookup_context);
-+    return
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const Rule &_) { _.collect_glyphs (c, lookup_context); })
-+    ;
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c,
- 		    ContextApplyLookupContext &lookup_context) const
-   {
--    TRACE_WOULD_APPLY (this);
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--    {
--      if ((this+rule[i]).would_apply (c, lookup_context))
--	return_trace (true);
--    }
--    return_trace (false);
-+    return
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_map ([&] (const Rule &_) { return _.would_apply (c, lookup_context); })
-+    | hb_any
-+    ;
-   }
- 
-   bool apply (hb_ot_apply_context_t *c,
- 	      ContextApplyLookupContext &lookup_context) const
-   {
-     TRACE_APPLY (this);
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--    {
--      if ((this+rule[i]).apply (c, lookup_context))
--	return_trace (true);
--    }
--    return_trace (false);
-+    return_trace (
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
-+    | hb_any
-+    )
-+    ;
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (rule.sanitize (c, this));
-   }
- 
-@@ -1432,69 +1440,64 @@ struct ContextFormat1
- {
-   bool intersects (const hb_set_t *glyphs) const
-   {
-     struct ContextClosureLookupContext lookup_context = {
-       {intersects_glyph},
-       nullptr
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (glyphs->has (iter.get_glyph ()) &&
--	  (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
--	return true;
--    }
--    return false;
-+    return
-+    + hb_zip (this+coverage, ruleSet)
-+    | hb_filter (*glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_map ([&] (const RuleSet &_) { return _.intersects (glyphs, lookup_context); })
-+    | hb_any
-+    ;
-   }
- 
-   void closure (hb_closure_context_t *c) const
-   {
-     struct ContextClosureLookupContext lookup_context = {
-       {intersects_glyph},
-       nullptr
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (c->glyphs->has (iter.get_glyph ()))
--	(this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
--    }
-+    + hb_zip (this+coverage, ruleSet)
-+    | hb_filter (*c->glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     (this+coverage).add_coverage (c->input);
- 
-     struct ContextCollectGlyphsLookupContext lookup_context = {
-       {collect_glyph},
-       nullptr
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (unsigned int i = 0; i < count; i++)
--      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-+    + hb_iter (ruleSet)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); })
-+    ;
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
--
-     const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-     struct ContextApplyLookupContext lookup_context = {
-       {match_glyph},
-       nullptr
-     };
--    return_trace (rule_set.would_apply (c, lookup_context));
-+    return rule_set.would_apply (c, lookup_context);
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-@@ -1544,72 +1547,74 @@ struct ContextFormat2
- 
-     const ClassDef &class_def = this+classDef;
- 
-     struct ContextClosureLookupContext lookup_context = {
-       {intersects_class},
-       &class_def
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (unsigned int i = 0; i < count; i++)
--      if (class_def.intersects_class (glyphs, i) &&
--	  (this+ruleSet[i]).intersects (glyphs, lookup_context))
--	return true;
--
--    return false;
-+    return
-+    + hb_enumerate (ruleSet)
-+    | hb_map ([&] (const hb_pair_t<unsigned, const OffsetTo<RuleSet> &> p)
-+	      { return class_def.intersects_class (glyphs, p.first) &&
-+		       (this+p.second).intersects (glyphs, lookup_context); })
-+    | hb_any
-+    ;
-   }
- 
-   void closure (hb_closure_context_t *c) const
-   {
-     if (!(this+coverage).intersects (c->glyphs))
-       return;
- 
-     const ClassDef &class_def = this+classDef;
- 
-     struct ContextClosureLookupContext lookup_context = {
-       {intersects_class},
-       &class_def
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (unsigned int i = 0; i < count; i++)
--      if (class_def.intersects_class (c->glyphs, i)) {
--	const RuleSet &rule_set = this+ruleSet[i];
--	rule_set.closure (c, lookup_context);
--      }
-+    return
-+    + hb_enumerate (ruleSet)
-+    | hb_filter ([&] (unsigned _)
-+		 { return class_def.intersects_class (c->glyphs, _); },
-+		 hb_first)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const RuleSet &_) { _.closure (c, lookup_context); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     (this+coverage).add_coverage (c->input);
- 
-     const ClassDef &class_def = this+classDef;
-     struct ContextCollectGlyphsLookupContext lookup_context = {
-       {collect_class},
-       &class_def
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (unsigned int i = 0; i < count; i++)
--      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-+    + hb_iter (ruleSet)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); })
-+    ;
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
--
-     const ClassDef &class_def = this+classDef;
-     unsigned int index = class_def.get_class (c->glyphs[0]);
-     const RuleSet &rule_set = this+ruleSet[index];
-     struct ContextApplyLookupContext lookup_context = {
-       {match_class},
-       &class_def
-     };
--    return_trace (rule_set.would_apply (c, lookup_context));
-+    return rule_set.would_apply (c, lookup_context);
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-@@ -1699,24 +1704,25 @@ struct ContextFormat3
-     context_collect_glyphs_lookup (c,
- 				   glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
- 				   lookupCount, lookupRecord,
- 				   lookup_context);
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
--
-     const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
-     struct ContextApplyLookupContext lookup_context = {
-       {match_coverage},
-       this
-     };
--    return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
-+    return context_would_apply_lookup (c,
-+				       glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
-+				       lookupCount, lookupRecord,
-+				       lookup_context);
-   }
- 
-   const Coverage &get_coverage () const { return this+coverageZ[0]; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
-@@ -1750,37 +1756,37 @@ struct ContextFormat3
-     return_trace (c->check_array (lookupRecord, lookupCount));
-   }
- 
-   protected:
-   HBUINT16	format;			/* Format identifier--format = 3 */
-   HBUINT16	glyphCount;		/* Number of glyphs in the input glyph
- 					 * sequence */
-   HBUINT16	lookupCount;		/* Number of LookupRecords */
--  UnsizedArrayOf<OffsetTo<Coverage> >
-+  UnsizedArrayOf<OffsetTo<Coverage>>
- 		coverageZ;		/* Array of offsets to Coverage
- 					 * table in glyph sequence order */
- /*UnsizedArrayOf<LookupRecord>
- 		lookupRecordX;*/	/* Array of LookupRecords--in
- 					 * design order */
-   public:
-   DEFINE_SIZE_ARRAY (6, coverageZ);
- };
- 
- struct Context
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
--    case 2: return_trace (c->dispatch (u.format2));
--    case 3: return_trace (c->dispatch (u.format3));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
-+    case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   ContextFormat1	format1;
-@@ -1922,89 +1928,88 @@ static inline bool chain_context_apply_l
- 			lookupCount, lookupRecord,
- 			match_length));
- }
- 
- struct ChainRule
- {
-   bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
-   {
--    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
--    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-     return chain_context_intersects (glyphs,
- 				     backtrack.len, backtrack.arrayZ,
- 				     input.lenP1, input.arrayZ,
- 				     lookahead.len, lookahead.arrayZ,
- 				     lookup_context);
-   }
- 
-   void closure (hb_closure_context_t *c,
- 		ChainContextClosureLookupContext &lookup_context) const
-   {
--    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
--    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     chain_context_closure_lookup (c,
- 				  backtrack.len, backtrack.arrayZ,
- 				  input.lenP1, input.arrayZ,
- 				  lookahead.len, lookahead.arrayZ,
- 				  lookup.len, lookup.arrayZ,
- 				  lookup_context);
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c,
- 		       ChainContextCollectGlyphsLookupContext &lookup_context) const
-   {
--    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
--    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     chain_context_collect_glyphs_lookup (c,
- 					 backtrack.len, backtrack.arrayZ,
- 					 input.lenP1, input.arrayZ,
- 					 lookahead.len, lookahead.arrayZ,
- 					 lookup.len, lookup.arrayZ,
- 					 lookup_context);
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c,
- 		    ChainContextApplyLookupContext &lookup_context) const
-   {
--    TRACE_WOULD_APPLY (this);
--    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
--    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
--    return_trace (chain_context_would_apply_lookup (c,
--						    backtrack.len, backtrack.arrayZ,
--						    input.lenP1, input.arrayZ,
--						    lookahead.len, lookahead.arrayZ, lookup.len,
--						    lookup.arrayZ, lookup_context));
-+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-+    return chain_context_would_apply_lookup (c,
-+					     backtrack.len, backtrack.arrayZ,
-+					     input.lenP1, input.arrayZ,
-+					     lookahead.len, lookahead.arrayZ, lookup.len,
-+					     lookup.arrayZ, lookup_context);
-   }
- 
-   bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-   {
-     TRACE_APPLY (this);
--    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
--    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     return_trace (chain_context_apply_lookup (c,
- 					      backtrack.len, backtrack.arrayZ,
- 					      input.lenP1, input.arrayZ,
- 					      lookahead.len, lookahead.arrayZ, lookup.len,
- 					      lookup.arrayZ, lookup_context));
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!backtrack.sanitize (c)) return_trace (false);
--    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
-+    const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
-     if (!input.sanitize (c)) return_trace (false);
--    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
-+    const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input);
-     if (!lookahead.sanitize (c)) return_trace (false);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     return_trace (lookup.sanitize (c));
-   }
- 
-   protected:
-   ArrayOf<HBUINT16>
- 		backtrack;		/* Array of backtracking values
- 					 * (to be matched before the input
- 					 * sequence) */
-@@ -2020,56 +2025,61 @@ struct ChainRule
-   public:
-   DEFINE_SIZE_MIN (8);
- };
- 
- struct ChainRuleSet
- {
-   bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
-   {
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--      if ((this+rule[i]).intersects (glyphs, lookup_context))
--	return true;
--    return false;
-+    return
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_map ([&] (const ChainRule &_) { return _.intersects (glyphs, lookup_context); })
-+    | hb_any
-+    ;
-   }
-   void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
-   {
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--      (this+rule[i]).closure (c, lookup_context);
-+    return
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const ChainRule &_) { _.closure (c, lookup_context); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
-   {
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--      (this+rule[i]).collect_glyphs (c, lookup_context);
-+    return
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const ChainRule &_) { _.collect_glyphs (c, lookup_context); })
-+    ;
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-   {
--    TRACE_WOULD_APPLY (this);
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--      if ((this+rule[i]).would_apply (c, lookup_context))
--	return_trace (true);
--
--    return_trace (false);
-+    return
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_map ([&] (const ChainRule &_) { return _.would_apply (c, lookup_context); })
-+    | hb_any
-+    ;
-   }
- 
-   bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
-   {
-     TRACE_APPLY (this);
--    unsigned int num_rules = rule.len;
--    for (unsigned int i = 0; i < num_rules; i++)
--      if ((this+rule[i]).apply (c, lookup_context))
--	return_trace (true);
--
--    return_trace (false);
-+    return_trace (
-+    + hb_iter (rule)
-+    | hb_map (hb_add (this))
-+    | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
-+    | hb_any
-+    )
-+    ;
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (rule.sanitize (c, this));
-   }
- 
-@@ -2085,69 +2095,64 @@ struct ChainContextFormat1
- {
-   bool intersects (const hb_set_t *glyphs) const
-   {
-     struct ChainContextClosureLookupContext lookup_context = {
-       {intersects_glyph},
-       {nullptr, nullptr, nullptr}
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (glyphs->has (iter.get_glyph ()) &&
--	  (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
--	return true;
--    }
--    return false;
-+    return
-+    + hb_zip (this+coverage, ruleSet)
-+    | hb_filter (*glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_map ([&] (const ChainRuleSet &_) { return _.intersects (glyphs, lookup_context); })
-+    | hb_any
-+    ;
-   }
- 
-   void closure (hb_closure_context_t *c) const
-   {
-     struct ChainContextClosureLookupContext lookup_context = {
-       {intersects_glyph},
-       {nullptr, nullptr, nullptr}
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
--    {
--      if (unlikely (iter.get_coverage () >= count))
--	break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
--      if (c->glyphs->has (iter.get_glyph ()))
--	(this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
--    }
-+    + hb_zip (this+coverage, ruleSet)
-+    | hb_filter (*c->glyphs, hb_first)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     (this+coverage).add_coverage (c->input);
- 
-     struct ChainContextCollectGlyphsLookupContext lookup_context = {
-       {collect_glyph},
-       {nullptr, nullptr, nullptr}
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (unsigned int i = 0; i < count; i++)
--      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-+    + hb_iter (ruleSet)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); })
-+    ;
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
--
-     const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
-     struct ChainContextApplyLookupContext lookup_context = {
-       {match_glyph},
-       {nullptr, nullptr, nullptr}
-     };
--    return_trace (rule_set.would_apply (c, lookup_context));
-+    return rule_set.would_apply (c, lookup_context);
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-@@ -2199,23 +2204,23 @@ struct ChainContextFormat2
- 
-     struct ChainContextClosureLookupContext lookup_context = {
-       {intersects_class},
-       {&backtrack_class_def,
-        &input_class_def,
-        &lookahead_class_def}
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (unsigned int i = 0; i < count; i++)
--      if (input_class_def.intersects_class (glyphs, i) &&
--	  (this+ruleSet[i]).intersects (glyphs, lookup_context))
--	return true;
--
--    return false;
-+    return
-+    + hb_enumerate (ruleSet)
-+    | hb_map ([&] (const hb_pair_t<unsigned, const OffsetTo<ChainRuleSet> &> p)
-+	      { return input_class_def.intersects_class (glyphs, p.first) &&
-+		       (this+p.second).intersects (glyphs, lookup_context); })
-+    | hb_any
-+    ;
-   }
-   void closure (hb_closure_context_t *c) const
-   {
-     if (!(this+coverage).intersects (c->glyphs))
-       return;
- 
-     const ClassDef &backtrack_class_def = this+backtrackClassDef;
-     const ClassDef &input_class_def = this+inputClassDef;
-@@ -2223,22 +2228,25 @@ struct ChainContextFormat2
- 
-     struct ChainContextClosureLookupContext lookup_context = {
-       {intersects_class},
-       {&backtrack_class_def,
-        &input_class_def,
-        &lookahead_class_def}
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (unsigned int i = 0; i < count; i++)
--      if (input_class_def.intersects_class (c->glyphs, i)) {
--	const ChainRuleSet &rule_set = this+ruleSet[i];
--	rule_set.closure (c, lookup_context);
--      }
-+    return
-+    + hb_enumerate (ruleSet)
-+    | hb_filter ([&] (unsigned _)
-+		 { return input_class_def.intersects_class (c->glyphs, _); },
-+		 hb_first)
-+    | hb_map (hb_second)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const ChainRuleSet &_) { _.closure (c, lookup_context); })
-+    ;
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
-     (this+coverage).add_coverage (c->input);
- 
-     const ClassDef &backtrack_class_def = this+backtrackClassDef;
-     const ClassDef &input_class_def = this+inputClassDef;
-@@ -2246,38 +2254,37 @@ struct ChainContextFormat2
- 
-     struct ChainContextCollectGlyphsLookupContext lookup_context = {
-       {collect_class},
-       {&backtrack_class_def,
-        &input_class_def,
-        &lookahead_class_def}
-     };
- 
--    unsigned int count = ruleSet.len;
--    for (unsigned int i = 0; i < count; i++)
--      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
-+    + hb_iter (ruleSet)
-+    | hb_map (hb_add (this))
-+    | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); })
-+    ;
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
--
-     const ClassDef &backtrack_class_def = this+backtrackClassDef;
-     const ClassDef &input_class_def = this+inputClassDef;
-     const ClassDef &lookahead_class_def = this+lookaheadClassDef;
- 
-     unsigned int index = input_class_def.get_class (c->glyphs[0]);
-     const ChainRuleSet &rule_set = this+ruleSet[index];
-     struct ChainContextApplyLookupContext lookup_context = {
-       {match_class},
-       {&backtrack_class_def,
-        &input_class_def,
-        &lookahead_class_def}
-     };
--    return_trace (rule_set.would_apply (c, lookup_context));
-+    return rule_set.would_apply (c, lookup_context);
-   }
- 
-   const Coverage &get_coverage () const { return this+coverage; }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
-     unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
-@@ -2338,108 +2345,106 @@ struct ChainContextFormat2
-   public:
-   DEFINE_SIZE_ARRAY (12, ruleSet);
- };
- 
- struct ChainContextFormat3
- {
-   bool intersects (const hb_set_t *glyphs) const
-   {
--    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
- 
-     if (!(this+input[0]).intersects (glyphs))
-       return false;
- 
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-     struct ChainContextClosureLookupContext lookup_context = {
-       {intersects_coverage},
-       {this, this, this}
-     };
-     return chain_context_intersects (glyphs,
- 				     backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
- 				     input.len, (const HBUINT16 *) input.arrayZ + 1,
- 				     lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
- 				     lookup_context);
-   }
- 
-   void closure (hb_closure_context_t *c) const
-   {
--    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
- 
-     if (!(this+input[0]).intersects (c->glyphs))
-       return;
- 
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     struct ChainContextClosureLookupContext lookup_context = {
-       {intersects_coverage},
-       {this, this, this}
-     };
-     chain_context_closure_lookup (c,
- 				  backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
- 				  input.len, (const HBUINT16 *) input.arrayZ + 1,
- 				  lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
- 				  lookup.len, lookup.arrayZ,
- 				  lookup_context);
-   }
- 
-   void collect_glyphs (hb_collect_glyphs_context_t *c) const
-   {
--    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
- 
-     (this+input[0]).add_coverage (c->input);
- 
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     struct ChainContextCollectGlyphsLookupContext lookup_context = {
-       {collect_coverage},
-       {this, this, this}
-     };
-     chain_context_collect_glyphs_lookup (c,
- 					 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
- 					 input.len, (const HBUINT16 *) input.arrayZ + 1,
- 					 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
- 					 lookup.len, lookup.arrayZ,
- 					 lookup_context);
-   }
- 
-   bool would_apply (hb_would_apply_context_t *c) const
-   {
--    TRACE_WOULD_APPLY (this);
--
--    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     struct ChainContextApplyLookupContext lookup_context = {
-       {match_coverage},
-       {this, this, this}
-     };
--    return_trace (chain_context_would_apply_lookup (c,
--						    backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
--						    input.len, (const HBUINT16 *) input.arrayZ + 1,
--						    lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
--						    lookup.len, lookup.arrayZ, lookup_context));
-+    return chain_context_would_apply_lookup (c,
-+					     backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
-+					     input.len, (const HBUINT16 *) input.arrayZ + 1,
-+					     lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-+					     lookup.len, lookup.arrayZ, lookup_context);
-   }
- 
-   const Coverage &get_coverage () const
-   {
--    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-     return this+input[0];
-   }
- 
-   bool apply (hb_ot_apply_context_t *c) const
-   {
-     TRACE_APPLY (this);
--    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
- 
-     unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
-     if (likely (index == NOT_COVERED)) return_trace (false);
- 
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     struct ChainContextApplyLookupContext lookup_context = {
-       {match_coverage},
-       {this, this, this}
-     };
-     return_trace (chain_context_apply_lookup (c,
- 					      backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
- 					      input.len, (const HBUINT16 *) input.arrayZ + 1,
- 					      lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
-@@ -2452,22 +2457,22 @@ struct ChainContextFormat3
-     // TODO(subset)
-     return_trace (false);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!backtrack.sanitize (c, this)) return_trace (false);
--    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
-+    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack);
-     if (!input.sanitize (c, this)) return_trace (false);
-     if (!input.len) return_trace (false); /* To be consistent with Context. */
--    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
-+    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input);
-     if (!lookahead.sanitize (c, this)) return_trace (false);
--    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
-+    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-     return_trace (lookup.sanitize (c));
-   }
- 
-   protected:
-   HBUINT16	format;			/* Format identifier--format = 3 */
-   OffsetArrayOf<Coverage>
- 		backtrack;		/* Array of coverage tables
- 					 * in backtracking sequence, in  glyph
-@@ -2484,25 +2489,25 @@ struct ChainContextFormat3
- 		lookupX;		/* Array of LookupRecords--in
- 					 * design order) */
-   public:
-   DEFINE_SIZE_MIN (10);
- };
- 
- struct ChainContext
- {
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (c->dispatch (u.format1));
--    case 2: return_trace (c->dispatch (u.format2));
--    case 3: return_trace (c->dispatch (u.format3));
-+    case 1: return_trace (c->dispatch (u.format1, hb_forward<Ts> (ds)...));
-+    case 2: return_trace (c->dispatch (u.format2, hb_forward<Ts> (ds)...));
-+    case 3: return_trace (c->dispatch (u.format3, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;	/* Format identifier */
-   ChainContextFormat1	format1;
-@@ -2514,45 +2519,40 @@ struct ChainContext
- 
- template <typename T>
- struct ExtensionFormat1
- {
-   unsigned int get_type () const { return extensionLookupType; }
- 
-   template <typename X>
-   const X& get_subtable () const
--  {
--    unsigned int offset = extensionOffset;
--    if (unlikely (!offset)) return Null(typename T::SubTable);
--    return StructAtOffset<typename T::SubTable> (this, offset);
--  }
--
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  { return this + CastR<LOffsetTo<typename T::SubTable>> (extensionOffset); }
-+
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, format);
-     if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
--    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type ()));
-+    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), hb_forward<Ts> (ds)...));
-   }
- 
-   /* This is called from may_dispatch() above with hb_sanitize_context_t. */
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
--		  extensionOffset != 0 &&
- 		  extensionLookupType != T::SubTable::Extension);
-   }
- 
-   protected:
-   HBUINT16	format;			/* Format identifier. Set to 1. */
-   HBUINT16	extensionLookupType;	/* Lookup type of subtable referenced
- 					 * by ExtensionOffset (i.e. the
- 					 * extension subtable). */
--  HBUINT32	extensionOffset;	/* Offset to the extension subtable,
-+  Offset32	extensionOffset;	/* Offset to the extension subtable,
- 					 * of lookup type subtable. */
-   public:
-   DEFINE_SIZE_STATIC (8);
- };
- 
- template <typename T>
- struct Extension
- {
-@@ -2567,23 +2567,23 @@ struct Extension
-   const X& get_subtable () const
-   {
-     switch (u.format) {
-     case 1: return u.format1.template get_subtable<typename T::SubTable> ();
-     default:return Null(typename T::SubTable);
-     }
-   }
- 
--  template <typename context_t>
--  typename context_t::return_t dispatch (context_t *c) const
-+  template <typename context_t, typename ...Ts>
-+  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
-   {
-     TRACE_DISPATCH (this, u.format);
-     if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
-     switch (u.format) {
--    case 1: return_trace (u.format1.dispatch (c));
-+    case 1: return_trace (u.format1.dispatch (c, hb_forward<Ts> (ds)...));
-     default:return_trace (c->default_return_value ());
-     }
-   }
- 
-   protected:
-   union {
-   HBUINT16		format;		/* Format identifier */
-   ExtensionFormat1<T>	format1;
-@@ -2676,31 +2676,32 @@ struct GSUBGPOS
-     }
-     return get_feature (feature_index);
-   }
- 
-   template <typename TLookup>
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
--    struct GSUBGPOS *out = c->serializer->embed (*this);
-+    auto *out = c->serializer->embed (*this);
-     if (unlikely (!out)) return_trace (false);
- 
--    out->scriptList.serialize_subset (c, this+scriptList, out);
--    out->featureList.serialize_subset (c, this+featureList, out);
-+    out->scriptList.serialize_subset (c, scriptList, this, out);
-+    out->featureList.serialize_subset (c, featureList, this, out);
- 
-     typedef OffsetListOf<TLookup> TLookupList;
-     /* TODO Use intersects() to count how many subtables survive? */
--    CastR<OffsetTo<TLookupList> > (out->lookupList)
-+    CastR<OffsetTo<TLookupList>> (out->lookupList)
-       .serialize_subset (c,
--			 this+CastR<const OffsetTo<TLookupList> > (lookupList),
-+			 CastR<OffsetTo<TLookupList>> (lookupList),
-+			 this,
- 			 out);
- 
-     if (version.to_int () >= 0x00010001u)
--     out->featureVars.serialize_subset (c, this+featureVars, out);
-+     out->featureVars.serialize_copy (c->serializer, featureVars, this, out);
- 
-     return_trace (true);
-   }
- 
-   unsigned int get_size () const
-   {
-     return min_size +
- 	   (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
-@@ -2710,17 +2711,17 @@ struct GSUBGPOS
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     typedef OffsetListOf<TLookup> TLookupList;
-     return_trace (version.sanitize (c) &&
- 		  likely (version.major == 1) &&
- 		  scriptList.sanitize (c, this) &&
- 		  featureList.sanitize (c, this) &&
--		  CastR<OffsetTo<TLookupList> > (lookupList).sanitize (c, this) &&
-+		  CastR<OffsetTo<TLookupList>> (lookupList).sanitize (c, this) &&
- 		  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
-   }
- 
-   template <typename T>
-   struct accelerator_t
-   {
-     void init (hb_face_t *face)
-     {
-diff --git a/gfx/harfbuzz/src/hb-ot-layout.cc b/gfx/harfbuzz/src/hb-ot-layout.cc
---- a/gfx/harfbuzz/src/hb-ot-layout.cc
-+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
-@@ -57,28 +57,64 @@
-  * Functions for querying OpenType Layout features in the font face.
-  **/
- 
- 
- /*
-  * kern
-  */
- 
-+/**
-+ * hb_ot_layout_has_kerning:
-+ * @face: The #hb_face_t to work on
-+ *
-+ * Tests whether a face includes any kerning data in the 'kern' table.
-+ * Does NOT test for kerning lookups in the GPOS table.
-+ *
-+ * Return value: true if data found, false otherwise
-+ *
-+ **/
- bool
- hb_ot_layout_has_kerning (hb_face_t *face)
- {
-   return face->table.kern->has_data ();
- }
- 
-+
-+/**
-+ * hb_ot_layout_has_machine_kerning:
-+ * @face: The #hb_face_t to work on
-+ *
-+ * Tests whether a face includes any state-machine kerning in the 'kern' table.
-+ * Does NOT examine the GPOS table.
-+ *
-+ * Return value: true if data found, false otherwise
-+ *
-+ **/
- bool
- hb_ot_layout_has_machine_kerning (hb_face_t *face)
- {
-   return face->table.kern->has_state_machine ();
- }
- 
-+
-+/**
-+ * hb_ot_layout_has_cross_kerning:
-+ * @face: The #hb_face_t to work on
-+ *
-+ * Tests whether a face has any cross-stream kerning (i.e., kerns
-+ * that make adjustments perpendicular to the direction of the text
-+ * flow: Y adjustments in horizontal text or X adjustments in 
-+ * vertical text) in the 'kern' table.
-+ *
-+ * Does NOT examine the GPOS table.
-+ *
-+ * Return value: true is data found, false otherwise
-+ *
-+ **/
- bool
- hb_ot_layout_has_cross_kerning (hb_face_t *face)
- {
-   return face->table.kern->has_cross_stream ();
- }
- 
- void
- hb_ot_layout_kern (const hb_ot_shape_plan_t *plan,
-@@ -97,16 +133,19 @@ hb_ot_layout_kern (const hb_ot_shape_pla
- /*
-  * GDEF
-  */
- 
- bool
- OT::GDEF::is_blacklisted (hb_blob_t *blob,
- 			  hb_face_t *face) const
- {
-+#ifdef HB_NO_OT_LAYOUT_BLACKLIST
-+  return false;
-+#endif
-   /* The ugly business of blacklisting individual fonts' tables happen here!
-    * See this thread for why we finally had to bend in and do this:
-    * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html
-    *
-    * In certain versions of Times New Roman Italic and Bold Italic,
-    * ASCII double quotation mark U+0022 has wrong glyph class 3 (mark)
-    * in GDEF.  Many versions of Tahoma have bad GDEF tables that
-    * incorrectly classify some spacing marks such as certain IPA
-@@ -114,94 +153,92 @@ OT::GDEF::is_blacklisted (hb_blob_t *blo
-    * Himalaya, and the version of Cantarell shipped by Ubuntu 16.04.
-    *
-    * Nuke the GDEF tables of to avoid unwanted width-zeroing.
-    *
-    * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925
-    *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279693
-    *     https://bugzilla.mozilla.org/show_bug.cgi?id=1279875
-    */
--#define ENCODE(x,y,z) (((uint64_t) (x) << 48) | ((uint64_t) (y) << 24) | (uint64_t) (z))
--  switch ENCODE(blob->length,
--		face->table.GSUB->table.get_length (),
--		face->table.GPOS->table.get_length ())
-+  switch HB_CODEPOINT_ENCODE3(blob->length,
-+			      face->table.GSUB->table.get_length (),
-+			      face->table.GPOS->table.get_length ())
-   {
-     /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */
--    case ENCODE (442, 2874, 42038):
-+    case HB_CODEPOINT_ENCODE3 (442, 2874, 42038):
-     /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */
--    case ENCODE (430, 2874, 40662):
-+    case HB_CODEPOINT_ENCODE3 (430, 2874, 40662):
-     /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */
--    case ENCODE (442, 2874, 39116):
-+    case HB_CODEPOINT_ENCODE3 (442, 2874, 39116):
-     /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */
--    case ENCODE (430, 2874, 39374):
-+    case HB_CODEPOINT_ENCODE3 (430, 2874, 39374):
-     /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */
--    case ENCODE (490, 3046, 41638):
-+    case HB_CODEPOINT_ENCODE3 (490, 3046, 41638):
-     /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */
--    case ENCODE (478, 3046, 41902):
-+    case HB_CODEPOINT_ENCODE3 (478, 3046, 41902):
-     /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c  tahoma.ttf from Windows 8 */
--    case ENCODE (898, 12554, 46470):
-+    case HB_CODEPOINT_ENCODE3 (898, 12554, 46470):
-     /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc  tahomabd.ttf from Windows 8 */
--    case ENCODE (910, 12566, 47732):
-+    case HB_CODEPOINT_ENCODE3 (910, 12566, 47732):
-     /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e  tahoma.ttf from Windows 8.1 */
--    case ENCODE (928, 23298, 59332):
-+    case HB_CODEPOINT_ENCODE3 (928, 23298, 59332):
-     /* sha1sum:6d400781948517c3c0441ba42acb309584b73033  tahomabd.ttf from Windows 8.1 */
--    case ENCODE (940, 23310, 60732):
-+    case HB_CODEPOINT_ENCODE3 (940, 23310, 60732):
-     /* tahoma.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
--    case ENCODE (964, 23836, 60072):
-+    case HB_CODEPOINT_ENCODE3 (964, 23836, 60072):
-     /* tahomabd.ttf v6.04 from Windows 8.1 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
--    case ENCODE (976, 23832, 61456):
-+    case HB_CODEPOINT_ENCODE3 (976, 23832, 61456):
-     /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846  tahoma.ttf from Windows 10 */
--    case ENCODE (994, 24474, 60336):
-+    case HB_CODEPOINT_ENCODE3 (994, 24474, 60336):
-     /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343  tahomabd.ttf from Windows 10 */
--    case ENCODE (1006, 24470, 61740):
-+    case HB_CODEPOINT_ENCODE3 (1006, 24470, 61740):
-     /* tahoma.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
--    case ENCODE (1006, 24576, 61346):
-+    case HB_CODEPOINT_ENCODE3 (1006, 24576, 61346):
-     /* tahomabd.ttf v6.91 from Windows 10 x64, see https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 */
--    case ENCODE (1018, 24572, 62828):
-+    case HB_CODEPOINT_ENCODE3 (1018, 24572, 62828):
-     /* sha1sum:b9c84d820c49850d3d27ec498be93955b82772b5  tahoma.ttf from Windows 10 AU */
--    case ENCODE (1006, 24576, 61352):
-+    case HB_CODEPOINT_ENCODE3 (1006, 24576, 61352):
-     /* sha1sum:2bdfaab28174bdadd2f3d4200a30a7ae31db79d2  tahomabd.ttf from Windows 10 AU */
--    case ENCODE (1018, 24572, 62834):
-+    case HB_CODEPOINT_ENCODE3 (1018, 24572, 62834):
-     /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7  Tahoma.ttf from Mac OS X 10.9 */
--    case ENCODE (832, 7324, 47162):
-+    case HB_CODEPOINT_ENCODE3 (832, 7324, 47162):
-     /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba  Tahoma Bold.ttf from Mac OS X 10.9 */
--    case ENCODE (844, 7302, 45474):
-+    case HB_CODEPOINT_ENCODE3 (844, 7302, 45474):
-     /* sha1sum:eb8afadd28e9cf963e886b23a30b44ab4fd83acc  himalaya.ttf from Windows 7 */
--    case ENCODE (180, 13054, 7254):
-+    case HB_CODEPOINT_ENCODE3 (180, 13054, 7254):
-     /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0  himalaya.ttf from Windows 8 */
--    case ENCODE (192, 12638, 7254):
-+    case HB_CODEPOINT_ENCODE3 (192, 12638, 7254):
-     /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427  himalaya.ttf from Windows 8.1 */
--    case ENCODE (192, 12690, 7254):
-+    case HB_CODEPOINT_ENCODE3 (192, 12690, 7254):
-     /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44  cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */
-     /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371  cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */
--    case ENCODE (188, 248, 3852):
-+    case HB_CODEPOINT_ENCODE3 (188, 248, 3852):
-     /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f  cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */
-     /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b  cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */
--    case ENCODE (188, 264, 3426):
-+    case HB_CODEPOINT_ENCODE3 (188, 264, 3426):
-     /* d125afa82a77a6475ac0e74e7c207914af84b37a padauk-2.80/Padauk.ttf RHEL 7.2 */
--    case ENCODE (1058, 47032, 11818):
-+    case HB_CODEPOINT_ENCODE3 (1058, 47032, 11818):
-     /* 0f7b80437227b90a577cc078c0216160ae61b031 padauk-2.80/Padauk-Bold.ttf RHEL 7.2*/
--    case ENCODE (1046, 47030, 12600):
-+    case HB_CODEPOINT_ENCODE3 (1046, 47030, 12600):
-     /* d3dde9aa0a6b7f8f6a89ef1002e9aaa11b882290 padauk-2.80/Padauk.ttf Ubuntu 16.04 */
--    case ENCODE (1058, 71796, 16770):
-+    case HB_CODEPOINT_ENCODE3 (1058, 71796, 16770):
-     /* 5f3c98ccccae8a953be2d122c1b3a77fd805093f padauk-2.80/Padauk-Bold.ttf Ubuntu 16.04 */
--    case ENCODE (1046, 71790, 17862):
-+    case HB_CODEPOINT_ENCODE3 (1046, 71790, 17862):
-     /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */
--    case ENCODE (1046, 71788, 17112):
-+    case HB_CODEPOINT_ENCODE3 (1046, 71788, 17112):
-     /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */
--    case ENCODE (1058, 71794, 17514):
-+    case HB_CODEPOINT_ENCODE3 (1058, 71794, 17514):
-     /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */
--    case ENCODE (1330, 109904, 57938):
-+    case HB_CODEPOINT_ENCODE3 (1330, 109904, 57938):
-     /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */
--    case ENCODE (1330, 109904, 58972):
-+    case HB_CODEPOINT_ENCODE3 (1330, 109904, 58972):
-     /* sha1sum: c26e41d567ed821bed997e937bc0c41435689e85  Padauk.ttf
-      *  "Padauk Regular" "Version 2.5", see https://crbug.com/681813 */
--    case ENCODE (1004, 59092, 14836):
-+    case HB_CODEPOINT_ENCODE3 (1004, 59092, 14836):
-       return true;
--#undef ENCODE
-   }
-   return false;
- }
- 
- static void
- _hb_ot_layout_set_glyph_props (hb_font_t *font,
- 			       hb_buffer_t *buffer)
- {
-@@ -214,68 +251,134 @@ static void
-     _hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
-     _hb_glyph_info_clear_lig_props (&buffer->info[i]);
-     buffer->info[i].syllable() = 0;
-   }
- }
- 
- /* Public API */
- 
-+/**
-+ * hb_ot_layout_has_glyph_classes:
-+ * @face: #hb_face_t to work upon
-+ *
-+ * Tests whether a face has any glyph classes defined in its GDEF table.
-+ *
-+ * Return value: true if data found, false otherwise
-+ *
-+ **/
- hb_bool_t
- hb_ot_layout_has_glyph_classes (hb_face_t *face)
- {
-   return face->table.GDEF->table->has_glyph_classes ();
- }
- 
- /**
-  * hb_ot_layout_get_glyph_class:
-+ * @face: The #hb_face_t to work on
-+ * @glyph: The #hb_codepoint_t code point to query
-+ *
-+ * Fetches the GDEF class of the requested glyph in the specified face.
-+ *
-+ * Return value: The #hb_ot_layout_glyph_class_t glyph class of the given code 
-+ * point in the GDEF table of the face.
-  *
-  * Since: 0.9.7
-  **/
- hb_ot_layout_glyph_class_t
- hb_ot_layout_get_glyph_class (hb_face_t      *face,
- 			      hb_codepoint_t  glyph)
- {
-   return (hb_ot_layout_glyph_class_t) face->table.GDEF->table->get_glyph_class (glyph);
- }
- 
- /**
-  * hb_ot_layout_get_glyphs_in_class:
-+ * @face: The #hb_face_t to work on
-+ * @klass: The #hb_ot_layout_glyph_class_t GDEF class to retrieve
-+ * @glyphs: (out): The #hb_set_t set of all glyphs belonging to the requested
-+ *          class.
-+ *
-+ * Retrieves the set of all glyphs from the face that belong to the requested
-+ * glyph class in the face's GDEF table.
-  *
-  * Since: 0.9.7
-  **/
- void
- hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
- 				  hb_ot_layout_glyph_class_t  klass,
- 				  hb_set_t                   *glyphs /* OUT */)
- {
-   return face->table.GDEF->table->get_glyphs_in_class (klass, glyphs);
- }
- 
-+
-+/**
-+ * hb_ot_layout_get_attach_points:
-+ * @face: The #hb_face_t to work on
-+ * @glyph: The #hb_codepoint_t code point to query
-+ * @start_offset: offset of the first attachment point to retrieve
-+ * @point_count: (inout) (allow-none): Input = the maximum number of attachment points to return;
-+ *               Output = the actual number of attachment points returned (may be zero)
-+ * @point_array: (out) (array length=point_count): The array of attachment points found for the query
-+ *
-+ * Fetches a list of all attachment points for the specified glyph in the GDEF
-+ * table of the face. The list returned will begin at the offset provided. 
-+ *
-+ * Useful if the client program wishes to cache the list.
-+ *
-+ **/
- unsigned int
- hb_ot_layout_get_attach_points (hb_face_t      *face,
- 				hb_codepoint_t  glyph,
- 				unsigned int    start_offset,
- 				unsigned int   *point_count /* IN/OUT */,
- 				unsigned int   *point_array /* OUT */)
- {
-+#ifdef HB_NO_LAYOUT_UNUSED
-+  if (point_count)
-+    *point_count = 0;
-+  return 0;
-+#endif
-+
-   return face->table.GDEF->table->get_attach_points (glyph,
- 						     start_offset,
- 						     point_count,
- 						     point_array);
- }
- 
-+
-+/**
-+ * hb_ot_layout_get_ligature_carets:
-+ * @font: The #hb_font_t to work on
-+ * @direction: The #hb_direction_t text direction to use
-+ * @glyph: The #hb_codepoint_t code point to query
-+ * @start_offset: offset of the first caret position to retrieve
-+ * @caret_count: (inout) (allow-none): Input = the maximum number of caret positions to return;
-+ *               Output = the actual number of caret positions returned (may be zero)
-+ * @caret_array: (out) (array length=caret_count): The array of caret positions found for the query
-+ *
-+ * Fetches a list of the caret positions defined for a ligature glyph in the GDEF
-+ * table of the font. The list returned will begin at the offset provided.
-+ *
-+ **/
- unsigned int
- hb_ot_layout_get_ligature_carets (hb_font_t      *font,
- 				  hb_direction_t  direction,
- 				  hb_codepoint_t  glyph,
- 				  unsigned int    start_offset,
- 				  unsigned int   *caret_count /* IN/OUT */,
- 				  hb_position_t  *caret_array /* OUT */)
- {
-+#ifdef HB_NO_LAYOUT_UNUSED
-+  if (caret_count)
-+    *caret_count = 0;
-+  return 0;
-+#endif
-+
-   unsigned int result_caret_count = 0;
-   unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array);
-   if (result)
-   {
-     if (caret_count) *caret_count = result_caret_count;
-   }
-   else
-     result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
-@@ -286,16 +389,19 @@ hb_ot_layout_get_ligature_carets (hb_fon
- /*
-  * GSUB/GPOS
-  */
- 
- bool
- OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
- 			  hb_face_t *face) const
- {
-+#ifdef HB_NO_OT_LAYOUT_BLACKLIST
-+  return false;
-+#endif
-   /* Mac OS X prefers morx over GSUB.  It also ships with various Indic fonts,
-    * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
-    * GSUB/GPOS tables.  Some have GSUB with zero scripts, those are ignored by
-    * our morx/GSUB preference code.  But if GSUB has non-zero scripts, we tend
-    * to prefer it over morx because we want to be consistent with other OpenType
-    * shapers.
-    *
-    * To work around broken Indic Mac system fonts, we ignore GSUB table if
-@@ -311,50 +417,79 @@ OT::GSUB::is_blacklisted (hb_blob_t *blo
- 
-   return false;
- }
- 
- bool
- OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
- 			  hb_face_t *face HB_UNUSED) const
- {
-+#ifdef HB_NO_OT_LAYOUT_BLACKLIST
-+  return false;
-+#endif
-   return false;
- }
- 
- static const OT::GSUBGPOS&
- get_gsubgpos_table (hb_face_t *face,
- 		    hb_tag_t   table_tag)
- {
-   switch (table_tag) {
-     case HB_OT_TAG_GSUB: return *face->table.GSUB->table;
-     case HB_OT_TAG_GPOS: return *face->table.GPOS->table;
-     default:             return Null(OT::GSUBGPOS);
-   }
- }
- 
- 
-+/**
-+ * hb_ot_layout_table_get_script_tags:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @start_offset: offset of the first script tag to retrieve
-+ * @script_count: (inout) (allow-none): Input = the maximum number of script tags to return;
-+ *                Output = the actual number of script tags returned (may be zero)
-+ * @script_tags: (out) (array length=script_count): The array of #hb_tag_t script tags found for the query
-+ *
-+ * Fetches a list of all scripts enumerated in the specified face's GSUB table
-+ * or GPOS table. The list returned will begin at the offset provided.
-+ *
-+ **/
- unsigned int
- hb_ot_layout_table_get_script_tags (hb_face_t    *face,
- 				    hb_tag_t      table_tag,
- 				    unsigned int  start_offset,
- 				    unsigned int *script_count /* IN/OUT */,
- 				    hb_tag_t     *script_tags  /* OUT */)
- {
-   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
- 
-   return g.get_script_tags (start_offset, script_count, script_tags);
- }
- 
- #define HB_OT_TAG_LATIN_SCRIPT		HB_TAG ('l', 'a', 't', 'n')
- 
-+/**
-+ * hb_ot_layout_table_find_script:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_tag: #hb_tag_t of the script tag requested
-+ * @script_index: (out): The index of the requested script tag
-+ *
-+ * Fetches the index if a given script tag in the specified face's GSUB table
-+ * or GPOS table.
-+ *
-+ * Return value: true if the script is found, false otherwise
-+ *
-+ **/
- hb_bool_t
- hb_ot_layout_table_find_script (hb_face_t    *face,
- 				hb_tag_t      table_tag,
- 				hb_tag_t      script_tag,
--				unsigned int *script_index)
-+				unsigned int *script_index /* OUT */)
- {
-   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX), "");
-   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
- 
-   if (g.find_script_index (script_tag, script_index))
-     return true;
- 
-   /* try finding 'DFLT' */
-@@ -370,30 +505,48 @@ hb_ot_layout_table_find_script (hb_face_
-      they're really trying to support Thai, for example :( */
-   if (g.find_script_index (HB_OT_TAG_LATIN_SCRIPT, script_index))
-     return false;
- 
-   if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
-   return false;
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
-+/**
-+ * hb_ot_layout_table_choose_script:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_tags: Array of #hb_tag_t script tags
-+ * @script_index: (out): The index of the requested script tag
-+ * @chosen_script: (out): #hb_tag_t of the script tag requested
-+ *
-+ * Deprecated since 2.0.0
-+ **/
- hb_bool_t
- hb_ot_layout_table_choose_script (hb_face_t      *face,
- 				  hb_tag_t        table_tag,
- 				  const hb_tag_t *script_tags,
--				  unsigned int   *script_index,
--				  hb_tag_t       *chosen_script)
-+				  unsigned int   *script_index  /* OUT */,
-+				  hb_tag_t       *chosen_script /* OUT */)
- {
-   const hb_tag_t *t;
-   for (t = script_tags; *t; t++);
-   return hb_ot_layout_table_select_script (face, table_tag, t - script_tags, script_tags, script_index, chosen_script);
- }
-+#endif
- 
- /**
-  * hb_ot_layout_table_select_script:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_count: Number of script tags in the array
-+ * @script_tags: Array of #hb_tag_t script tags
-+ * @script_index: (out): The index of the requested script
-+ * @chosen_script: (out): #hb_tag_t of the requested script
-  *
-  * Since: 2.0.0
-  **/
- hb_bool_t
- hb_ot_layout_table_select_script (hb_face_t      *face,
- 				  hb_tag_t        table_tag,
- 				  unsigned int    script_count,
- 				  const hb_tag_t *script_tags,
-@@ -437,33 +590,59 @@ hb_ot_layout_table_select_script (hb_fac
-   }
- 
-   if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
-   if (chosen_script)
-     *chosen_script = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
-   return false;
- }
- 
-+
-+/**
-+ * hb_ot_layout_table_get_feature_tags:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @start_offset: offset of the first feature tag to retrieve
-+ * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return;
-+ *                 Output = the actual number of feature tags returned (may be zero)
-+ * @feature_tags: (out) (array length=feature_count): Array of feature tags found in the table
-+ *
-+ * Fetches a list of all feature tags in the given face's GSUB or GPOS table.
-+ *
-+ **/
- unsigned int
- hb_ot_layout_table_get_feature_tags (hb_face_t    *face,
- 				     hb_tag_t      table_tag,
- 				     unsigned int  start_offset,
- 				     unsigned int *feature_count /* IN/OUT */,
- 				     hb_tag_t     *feature_tags  /* OUT */)
- {
-   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
- 
-   return g.get_feature_tags (start_offset, feature_count, feature_tags);
- }
- 
-+
-+/**
-+ * hb_ot_layout_table_find_feature:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @feature_tag: The #hb_tag_t og the requested feature tag
-+ * @feature_index: (out): The index of the requested feature
-+ *
-+ * Fetches the index for a given feature tag in the specified face's GSUB table
-+ * or GPOS table.
-+ *
-+ * Return value: true if the feature is found, false otherwise
-+ **/
- bool
- hb_ot_layout_table_find_feature (hb_face_t    *face,
- 				 hb_tag_t      table_tag,
- 				 hb_tag_t      feature_tag,
--				 unsigned int *feature_index)
-+				 unsigned int *feature_index /* OUT */)
- {
-   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX), "");
-   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
- 
-   unsigned int num_features = g.get_feature_count ();
-   for (unsigned int i = 0; i < num_features; i++)
-   {
-     if (feature_tag == g.get_feature_tag (i)) {
-@@ -472,46 +651,91 @@ hb_ot_layout_table_find_feature (hb_face
-     }
-   }
- 
-   if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
-   return false;
- }
- 
- 
-+/**
-+ * hb_ot_layout_script_get_language_tags:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_index: The index of the requested script tag
-+ * @start_offset: offset of the first language tag to retrieve
-+ * @language_count: (inout) (allow-none): Input = the maximum number of language tags to return;
-+ *                  Output = the actual number of language tags returned (may be zero)
-+ * @language_tags: (out) (array length=language_count): Array of language tags found in the table
-+ *
-+ * Fetches a list of language tags in the given face's GSUB or GPOS table, underneath
-+ * the specified script index. The list returned will begin at the offset provided.
-+ *
-+ **/
- unsigned int
- hb_ot_layout_script_get_language_tags (hb_face_t    *face,
- 				       hb_tag_t      table_tag,
- 				       unsigned int  script_index,
- 				       unsigned int  start_offset,
- 				       unsigned int *language_count /* IN/OUT */,
- 				       hb_tag_t     *language_tags  /* OUT */)
- {
-   const OT::Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index);
- 
-   return s.get_lang_sys_tags (start_offset, language_count, language_tags);
- }
- 
-+
-+#ifndef HB_DISABLE_DEPRECATED
-+/**
-+ * hb_ot_layout_script_find_language:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_index: The index of the requested script tag
-+ * @language_tag: The #hb_tag_t of the requested language
-+ * @language_index: The index of the requested language
-+ *
-+ * Fetches the index of a given language tag in the specified face's GSUB table
-+ * or GPOS table, underneath the specified script tag.
-+ *
-+ * Return value: true if the language tag is found, false otherwise
-+ *
-+ * Since: ??
-+ * Deprecated: ??
-+ **/
- hb_bool_t
- hb_ot_layout_script_find_language (hb_face_t    *face,
- 				   hb_tag_t      table_tag,
- 				   unsigned int  script_index,
- 				   hb_tag_t      language_tag,
- 				   unsigned int *language_index)
- {
-   return hb_ot_layout_script_select_language (face,
- 					      table_tag,
- 					      script_index,
- 					      1,
- 					      &language_tag,
- 					      language_index);
- }
-+#endif
-+
- 
- /**
-  * hb_ot_layout_script_select_language:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_index: The index of the requested script tag
-+ * @language_count: The number of languages in the specified script
-+ * @language_tags: The array of language tags
-+ * @language_index: (out): The index of the requested language
-+ *
-+ * Fetches the index of a given language tag in the specified face's GSUB table
-+ * or GPOS table, underneath the specified script index.
-+ *
-+ * Return value: true if the language tag is found, false otherwise
-  *
-  * Since: 2.0.0
-  **/
- hb_bool_t
- hb_ot_layout_script_select_language (hb_face_t      *face,
- 				     hb_tag_t        table_tag,
- 				     unsigned int    script_index,
- 				     unsigned int    language_count,
-@@ -531,33 +755,60 @@ hb_ot_layout_script_select_language (hb_
-   /* try finding 'dflt' */
-   if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index))
-     return false;
- 
-   if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
-   return false;
- }
- 
-+
-+/**
-+ * hb_ot_layout_language_get_required_feature_index:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_index: The index of the requested script tag
-+ * @language_index: The index of the requested language tag
-+ * @feature_index: (out): The index of the requested feature
-+ *
-+ * Fetches the index of a requested feature in the given face's GSUB or GPOS table,
-+ * underneath the specified script and language.
-+ *
-+ * Return value: true if the feature is found, false otherwise
-+ *
-+ **/
- hb_bool_t
- hb_ot_layout_language_get_required_feature_index (hb_face_t    *face,
- 						  hb_tag_t      table_tag,
- 						  unsigned int  script_index,
- 						  unsigned int  language_index,
- 						  unsigned int *feature_index)
- {
-   return hb_ot_layout_language_get_required_feature (face,
- 						     table_tag,
- 						     script_index,
- 						     language_index,
- 						     feature_index,
- 						     nullptr);
- }
- 
-+
- /**
-  * hb_ot_layout_language_get_required_feature:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_index: The index of the requested script tag
-+ * @language_index: The index of the requested language tag
-+ * @feature_index: The index of the requested feature
-+ * @feature_tag: (out): The #hb_tag_t of the requested feature
-+ *
-+ * Fetches the tag of a requested feature index in the given face's GSUB or GPOS table,
-+ * underneath the specified script and language.
-+ *
-+ * Return value: true if the feature is found, false otherwise
-  *
-  * Since: 0.9.30
-  **/
- hb_bool_t
- hb_ot_layout_language_get_required_feature (hb_face_t    *face,
- 					    hb_tag_t      table_tag,
- 					    unsigned int  script_index,
- 					    unsigned int  language_index,
-@@ -569,31 +820,64 @@ hb_ot_layout_language_get_required_featu
- 
-   unsigned int index = l.get_required_feature_index ();
-   if (feature_index) *feature_index = index;
-   if (feature_tag) *feature_tag = g.get_feature_tag (index);
- 
-   return l.has_required_feature ();
- }
- 
-+
-+/**
-+ * hb_ot_layout_language_get_feature_indexes:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_index: The index of the requested script tag
-+ * @language_index: The index of the requested language tag
-+ * @start_offset: offset of the first feature tag to retrieve
-+ * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return;
-+ *                 Output: the actual number of feature tags returned (may be zero)
-+ * @feature_indexes: (out) (array length=feature_count): The array of feature indexes found for the query
-+ *
-+ * Fetches a list of all features in the specified face's GSUB table
-+ * or GPOS table, underneath the specified script and language. The list
-+ * returned will begin at the offset provided.
-+ **/
- unsigned int
- hb_ot_layout_language_get_feature_indexes (hb_face_t    *face,
- 					   hb_tag_t      table_tag,
- 					   unsigned int  script_index,
- 					   unsigned int  language_index,
- 					   unsigned int  start_offset,
- 					   unsigned int *feature_count   /* IN/OUT */,
- 					   unsigned int *feature_indexes /* OUT */)
- {
-   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-   const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
- 
-   return l.get_feature_indexes (start_offset, feature_count, feature_indexes);
- }
- 
-+
-+/**
-+ * hb_ot_layout_language_get_feature_tags:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_index: The index of the requested script tag
-+ * @language_index: The index of the requested language tag
-+ * @start_offset: offset of the first feature tag to retrieve
-+ * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return;
-+ *                 Output = the actual number of feature tags returned (may be zero)
-+ * @feature_tags: (out) (array length=feature_count): The array of #hb_tag_t feature tags found for the query
-+ *
-+ * Fetches a list of all features in the specified face's GSUB table
-+ * or GPOS table, underneath the specified script and language. The list
-+ * returned will begin at the offset provided.
-+ *
-+ **/
- unsigned int
- hb_ot_layout_language_get_feature_tags (hb_face_t    *face,
- 					hb_tag_t      table_tag,
- 					unsigned int  script_index,
- 					unsigned int  language_index,
- 					unsigned int  start_offset,
- 					unsigned int *feature_count /* IN/OUT */,
- 					hb_tag_t     *feature_tags  /* OUT */)
-@@ -609,23 +893,38 @@ hb_ot_layout_language_get_feature_tags (
-     for (unsigned int i = 0; i < count; i++)
-       feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]);
-   }
- 
-   return ret;
- }
- 
- 
-+/**
-+ * hb_ot_layout_language_find_feature:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @script_index: The index of the requested script tag
-+ * @language_index: The index of the requested language tag
-+ * @feature_tag: #hb_tag_t of the feature tag requested
-+ * @feature_index: (out): The index of the requested feature
-+ *
-+ * Fetches the index of a given feature tag in the specified face's GSUB table
-+ * or GPOS table, underneath the specified script and language.
-+ *
-+ * Return value: true if the feature is found, false otherwise
-+ *
-+ **/
- hb_bool_t
- hb_ot_layout_language_find_feature (hb_face_t    *face,
- 				    hb_tag_t      table_tag,
- 				    unsigned int  script_index,
- 				    unsigned int  language_index,
- 				    hb_tag_t      feature_tag,
--				    unsigned int *feature_index)
-+				    unsigned int *feature_index /* OUT */)
- {
-   static_assert ((OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX), "");
-   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
-   const OT::LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
- 
-   unsigned int num_features = l.get_feature_count ();
-   for (unsigned int i = 0; i < num_features; i++) {
-     unsigned int f_index = l.get_feature_index (i);
-@@ -635,18 +934,30 @@ hb_ot_layout_language_find_feature (hb_f
-       return true;
-     }
-   }
- 
-   if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
-   return false;
- }
- 
-+
- /**
-  * hb_ot_layout_feature_get_lookups:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @feature_index: The index of the requested feature
-+ * @start_offset: offset of the first lookup to retrieve
-+ * @lookup_count: (inout) (allow-none): Input = the maximum number of lookups to return;
-+ *                Output = the actual number of lookups returned (may be zero)
-+ * @lookup_indexes: (out) (array length=lookup_count): The array of lookup indexes found for the query
-+ *
-+ * Fetches a list of all lookups enumerated for the specified feature, in
-+ * the specified face's GSUB table or GPOS table. The list returned will
-+ * begin at the offset provided.
-  *
-  * Since: 0.9.7
-  **/
- unsigned int
- hb_ot_layout_feature_get_lookups (hb_face_t    *face,
- 				  hb_tag_t      table_tag,
- 				  unsigned int  feature_index,
- 				  unsigned int  start_offset,
-@@ -657,18 +968,24 @@ hb_ot_layout_feature_get_lookups (hb_fac
- 							   table_tag,
- 							   feature_index,
- 							   HB_OT_LAYOUT_NO_VARIATIONS_INDEX,
- 							   start_offset,
- 							   lookup_count,
- 							   lookup_indexes);
- }
- 
-+
- /**
-  * hb_ot_layout_table_get_lookup_count:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ *
-+ * Fetches the total number of lookups enumerated in the specified 
-+ * face's GSUB table or GPOS table.
-  *
-  * Since: 0.9.22
-  **/
- unsigned int
- hb_ot_layout_table_get_lookup_count (hb_face_t    *face,
- 				     hb_tag_t      table_tag)
- {
-   return get_gsubgpos_table (face, table_tag).get_lookup_count ();
-@@ -800,18 +1117,31 @@ script_collect_features (hb_collect_feat
-       if (s.find_lang_sys_index (*languages, &language_index))
- 	langsys_collect_features (c,
- 				  s.get_lang_sys (language_index),
- 				  features);
-     }
-   }
- }
- 
-+
- /**
-  * hb_ot_layout_collect_features:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @scripts: The array of scripts to collect features for
-+ * @languages: The array of languages to collect features for
-+ * @features: The array of features to collect
-+ * @feature_indexes: (out): The array of feature indexes found for the query
-+ *
-+ * Fetches a list of all feature indexes in the specified face's GSUB table
-+ * or GPOS table, underneath the specified scripts, languages, and features.
-+ * If no list of scripts is provided, all scripts will be queried. If no list
-+ * of languages is provided, all languages will be queried. If no list of
-+ * features is provided, all features will be queried.
-  *
-  * Since: 1.8.5
-  **/
- void
- hb_ot_layout_collect_features (hb_face_t      *face,
-                                hb_tag_t        table_tag,
-                                const hb_tag_t *scripts,
-                                const hb_tag_t *languages,
-@@ -838,18 +1168,31 @@ hb_ot_layout_collect_features (hb_face_t
- 	script_collect_features (&c,
- 				 c.g.get_script (script_index),
- 				 languages,
- 				 features);
-     }
-   }
- }
- 
-+
- /**
-  * hb_ot_layout_collect_lookups:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @scripts: The array of scripts to collect lookups for
-+ * @languages: The array of languages to collect lookups for
-+ * @features: The array of features to collect lookups for
-+ * @lookup_indexes: (out): The array of lookup indexes found for the query
-+ *
-+ * Fetches a list of all feature-lookup indexes in the specified face's GSUB
-+ * table or GPOS table, underneath the specified scripts, languages, and
-+ * features. If no list of scripts is provided, all scripts will be queried.
-+ * If no list of languages is provided, all languages will be queried. If no
-+ * list of features is provided, all features will be queried. 
-  *
-  * Since: 0.9.8
-  **/
- void
- hb_ot_layout_collect_lookups (hb_face_t      *face,
- 			      hb_tag_t        table_tag,
- 			      const hb_tag_t *scripts,
- 			      const hb_tag_t *languages,
-@@ -861,18 +1204,29 @@ hb_ot_layout_collect_lookups (hb_face_t 
-   hb_set_t feature_indexes;
-   hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
- 
-   for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
-        hb_set_next (&feature_indexes, &feature_index);)
-     g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
- }
- 
-+
- /**
-  * hb_ot_layout_lookup_collect_glyphs:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @lookup_index: The index of the feature lookup to query
-+ * @glyphs_before: (out): Array of glyphs preceding the substitution range
-+ * @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup
-+ * @glyphs_after: (out): Array of glyphs following the substition range
-+ * @glyphs_output: (out): Array of glyphs that would be the substitued output of the lookup
-+ *
-+ * Fetches a list of all glyphs affected by the specified lookup in the
-+ * specified face's GSUB table of GPOS table.
-  *
-  * Since: 0.9.7
-  **/
- void
- hb_ot_layout_lookup_collect_glyphs (hb_face_t    *face,
- 				    hb_tag_t      table_tag,
- 				    unsigned int  lookup_index,
- 				    hb_set_t     *glyphs_before, /* OUT.  May be NULL */
-@@ -901,28 +1255,58 @@ hb_ot_layout_lookup_collect_glyphs (hb_f
-       return;
-     }
-   }
- }
- 
- 
- /* Variations support */
- 
-+
-+/**
-+ * hb_ot_layout_table_find_feature_variations:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @coords: The variation coordinates to query
-+ * @num_coords: The number of variation coorinates
-+ * @variations_index: (out): The array of feature variations found for the query
-+ *
-+ * Fetches a list of feature variations in the specified face's GSUB table
-+ * or GPOS table, at the specified variation coordinates.
-+ *
-+ **/
- hb_bool_t
- hb_ot_layout_table_find_feature_variations (hb_face_t    *face,
- 					    hb_tag_t      table_tag,
- 					    const int    *coords,
- 					    unsigned int  num_coords,
- 					    unsigned int *variations_index /* out */)
- {
-   const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag);
- 
-   return g.find_variations_index (coords, num_coords, variations_index);
- }
- 
-+
-+/**
-+ * hb_ot_layout_feature_with_variations_get_lookups:
-+ * @face: #hb_face_t to work upon
-+ * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-+ * @feature_index: The index of the feature to query
-+ * @variations_index: The index of the feature variation to query
-+ * @start_offset: offset of the first lookup to retrieve
-+ * @lookup_count: (inout) (allow-none): Input = the maximum number of lookups to return;
-+ *                Output = the actual number of lookups returned (may be zero)
-+ * @lookup_indexes: (out) (array length=lookup_count): The array of lookups found for the query
-+ *
-+ * Fetches a list of all lookups enumerated for the specified feature, in
-+ * the specified face's GSUB table or GPOS table, enabled at the specified
-+ * variations index. The list returned will begin at the offset provided.
-+ *
-+ **/
- unsigned int
- hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
- 						  hb_tag_t      table_tag,
- 						  unsigned int  feature_index,
- 						  unsigned int  variations_index,
- 						  unsigned int  start_offset,
- 						  unsigned int *lookup_count /* IN/OUT */,
- 						  unsigned int *lookup_indexes /* OUT */)
-@@ -935,24 +1319,45 @@ hb_ot_layout_feature_with_variations_get
-   return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes);
- }
- 
- 
- /*
-  * OT::GSUB
-  */
- 
-+
-+/**
-+ * hb_ot_layout_has_substitution:
-+ * @face: #hb_face_t to work upon
-+ *
-+ * Tests whether the specified face includes any GSUB substitutions.
-+ *
-+ * Return value: true if data found, false otherwise
-+ *
-+ **/
- hb_bool_t
- hb_ot_layout_has_substitution (hb_face_t *face)
- {
-   return face->table.GSUB->table->has_data ();
- }
- 
-+
- /**
-  * hb_ot_layout_lookup_would_substitute:
-+ * @face: #hb_face_t to work upon
-+ * @lookup_index: The index of the lookup to query
-+ * @glyphs: The sequence of glyphs to query for substitution
-+ * @glyphs_length: The length of the glyph sequence
-+ * @zero_context: #hb_bool_t indicating whether substitutions should be context-free
-+ *
-+ * Tests whether a specified lookup in the specified face would
-+ * trigger a substitution on the given glyph sequence.
-+ *
-+ * Return value: true if a substitution would be triggered, false otherwise
-  *
-  * Since: 0.9.7
-  **/
- hb_bool_t
- hb_ot_layout_lookup_would_substitute (hb_face_t            *face,
- 				      unsigned int          lookup_index,
- 				      const hb_codepoint_t *glyphs,
- 				      unsigned int          glyphs_length,
-@@ -961,16 +1366,26 @@ hb_ot_layout_lookup_would_substitute (hb
-   if (unlikely (lookup_index >= face->table.GSUB->lookup_count)) return false;
-   OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
- 
-   const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
- 
-   return l.would_apply (&c, &face->table.GSUB->accels[lookup_index]);
- }
- 
-+
-+/**
-+ * hb_ot_layout_substitute_start:
-+ * @font: #hb_font_t to use
-+ * @buffer: #hb_buffer_t buffer to work upon
-+ *
-+ * Called before substitution lookups are performed, to ensure that glyph
-+ * class and other properties are set on the glyphs in the buffer.
-+ *
-+ **/
- void
- hb_ot_layout_substitute_start (hb_font_t    *font,
- 			       hb_buffer_t  *buffer)
- {
- _hb_ot_layout_set_glyph_props (font, buffer);
- }
- 
- void
-@@ -1020,44 +1435,53 @@ hb_ot_layout_delete_glyphs_inplace (hb_b
-     }
-     j++;
-   }
-   buffer->len = j;
- }
- 
- /**
-  * hb_ot_layout_lookup_substitute_closure:
-+ * @face: #hb_face_t to work upon
-+ * @lookup_index: index of the feature lookup to query
-+ * @glyphs: (out): Array of glyphs comprising the transitive closure of the lookup
-+ *
-+ * Compute the transitive closure of glyphs needed for a
-+ * specified lookup.
-  *
-  * Since: 0.9.7
-  **/
- void
- hb_ot_layout_lookup_substitute_closure (hb_face_t    *face,
- 				        unsigned int  lookup_index,
--				        hb_set_t     *glyphs)
-+				        hb_set_t     *glyphs /* OUT */)
- {
-   hb_map_t done_lookups;
-   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
- 
-   const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
- 
-   l.closure (&c, lookup_index);
- }
- 
- /**
-  * hb_ot_layout_lookups_substitute_closure:
-+ * @face: #hb_face_t to work upon
-+ * @lookups: The set of lookups to query
-+ * @glyphs: (out): Array of glyphs comprising the transitive closure of the lookups
-  *
-  * Compute the transitive closure of glyphs needed for all of the
-  * provided lookups.
-  *
-  * Since: 1.8.1
-  **/
- void
- hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
-                                          const hb_set_t *lookups,
--                                         hb_set_t       *glyphs)
-+                                         hb_set_t       *glyphs /* OUT */)
- {
-   hb_map_t done_lookups;
-   OT::hb_closure_context_t c (face, glyphs, &done_lookups);
-   const OT::GSUB& gsub = *face->table.GSUB->table;
- 
-   unsigned int iteration_count = 0;
-   unsigned int glyphs_length;
-   do
-@@ -1076,42 +1500,94 @@ hb_ot_layout_lookups_substitute_closure 
-   } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
- 	   glyphs_length != glyphs->get_population ());
- }
- 
- /*
-  * OT::GPOS
-  */
- 
-+
-+/**
-+ * hb_ot_layout_has_positioning:
-+ * @face: #hb_face_t to work upon
-+ *
-+ * Return value: true if the face has GPOS data, false otherwise
-+ *
-+ **/
- hb_bool_t
- hb_ot_layout_has_positioning (hb_face_t *face)
- {
-   return face->table.GPOS->table->has_data ();
- }
- 
-+/**
-+ * hb_ot_layout_position_start:
-+ * @font: #hb_font_t to use
-+ * @buffer: #hb_buffer_t buffer to work upon
-+ *
-+ * Called before positioning lookups are performed, to ensure that glyph
-+ * attachment types and glyph-attachment chains are set for the glyphs in the buffer.
-+ *
-+ **/
- void
- hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
- {
-   OT::GPOS::position_start (font, buffer);
- }
- 
-+
-+/**
-+ * hb_ot_layout_position_finish_advances:
-+ * @font: #hb_font_t to use
-+ * @buffer: #hb_buffer_t buffer to work upon
-+ *
-+ * Called after positioning lookups are performed, to finish glyph advances.
-+ *
-+ **/
- void
- hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
- {
-   OT::GPOS::position_finish_advances (font, buffer);
- }
- 
-+/**
-+ * hb_ot_layout_position_finish_offsets:
-+ * @font: #hb_font_t to use
-+ * @buffer: #hb_buffer_t buffer to work upon
-+ *
-+ * Called after positioning lookups are performed, to finish glyph offsets.
-+ *
-+ **/
- void
- hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
- {
-   OT::GPOS::position_finish_offsets (font, buffer);
- }
- 
-+
- /**
-  * hb_ot_layout_get_size_params:
-+ * @face: #hb_face_t to work upon
-+ * @design_size: (out): The design size of the face
-+ * @subfamily_id: (out): The identifier of the face within the font subfamily
-+ * @subfamily_name_id: (out): The ‘name’ table name ID of the face within the font subfamily
-+ * @range_start: (out): The minimum size of the recommended size range for the face
-+ * @range_end: (out): The maximum size of the recommended size range for the face
-+ *
-+ * Fetches optical-size feature data (i.e., the `size` feature from GPOS). Note that
-+ * the subfamily_id and the subfamily name string (accessible via the subfamily_name_id)
-+ * as used here are defined as pertaining only to fonts within a font family that differ
-+ * specifically in their respective size ranges; other ways to differentiate fonts within
-+ * a subfamily are not covered by the `size` feature.
-+ * 
-+ * For more information on this distinction, see the `size` documentation at
-+ * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-39size39
-+ *
-+ * Return value: true if data found, false otherwise
-  *
-  * Since: 0.9.10
-  **/
- hb_bool_t
- hb_ot_layout_get_size_params (hb_face_t       *face,
- 			      unsigned int    *design_size,       /* OUT.  May be NULL */
- 			      unsigned int    *subfamily_id,      /* OUT.  May be NULL */
- 			      hb_ot_name_id_t *subfamily_name_id, /* OUT.  May be NULL */
-@@ -1146,16 +1622,17 @@ hb_ot_layout_get_size_params (hb_face_t 
-   if (subfamily_id) *subfamily_id = 0;
-   if (subfamily_name_id) *subfamily_name_id = HB_OT_NAME_ID_INVALID;
-   if (range_start) *range_start = 0;
-   if (range_end) *range_end = 0;
- 
-   return false;
- }
- 
-+
- /**
-  * hb_ot_layout_feature_get_name_ids:
-  * @face: #hb_face_t to work upon
-  * @table_tag: table tag to query, "GSUB" or "GPOS".
-  * @feature_index: index of feature to query.
-  * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
-  *            for a user-interface label for this feature. (May be NULL.)
-  * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
-@@ -1221,34 +1698,38 @@ hb_ot_layout_feature_get_name_ids (hb_fa
-   if (label_id) *label_id = HB_OT_NAME_ID_INVALID;
-   if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
-   if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
-   if (num_named_parameters) *num_named_parameters = 0;
-   if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
-   return false;
- }
- 
-+
- /**
-  * hb_ot_layout_feature_get_characters:
-  * @face: #hb_face_t to work upon
-  * @table_tag: table tag to query, "GSUB" or "GPOS".
-  * @feature_index: index of feature to query.
-- * @start_offset: In case the resulting char_count was equal to its input value, there
-- *                is a chance there were more characters on the tag so this API can be
-- *                called with an offset till resulting char_count gets to a number
-- *                lower than input buffer (or consider using just a bigger buffer for
-- *                one shot copying).
-- * @char_count: (inout) (allow-none): The count of characters for which this feature
-- *              provides glyph variants. (May be zero.)
-- * @characters: (out caller-allocates) (array length=char_count): A buffer pointer. The Unicode codepoints
-- *              of the characters for which this feature provides glyph variants.
-+ * @start_offset: offset of the first character to retrieve
-+ * @char_count: (inout) (allow-none): Input = the maximum number of characters to return;
-+ *              Output = the actual number of characters returned (may be zero)
-+ * @characters: (out caller-allocates) (array length=char_count): A buffer pointer.
-+ *              The Unicode codepoints of the characters for which this feature provides
-+ *               glyph variants.
-  *
-- * Fetches characters listed by designer under feature parameters for "Character
-- * Variant" ("cvXX") features.
-+ * Fetches a list of the characters defined as having a variant under the specified
-+ * "Character Variant" ("cvXX") feature tag.
-  *
-+ * <note>Note: If the char_count output value is equal to its input value, then there
-+ *       is a chance there were more characters defined under the feature tag than were
-+ *       returned. This function can be called with incrementally larger start_offset
-+ *       until the char_count output value is lower than its input value, or the size
-+ *       of the characters array can be increased.</note>
-+ * 
-  * Return value: Number of total sample characters in the cvXX feature.
-  *
-  * Since: 2.0.0
-  **/
- unsigned int
- hb_ot_layout_feature_get_characters (hb_face_t      *face,
- 				     hb_tag_t        table_tag,
- 				     unsigned int    feature_index,
-@@ -1264,17 +1745,17 @@ hb_ot_layout_feature_get_characters (hb_
-   const OT::FeatureParams &feature_params = f.get_feature_params ();
- 
-   const OT::FeatureParamsCharacterVariants& cv_params =
-     feature_params.get_character_variants_params(feature_tag);
- 
-   unsigned int len = 0;
-   if (char_count && characters && start_offset < cv_params.characters.len)
-   {
--    len = MIN (cv_params.characters.len - start_offset, *char_count);
-+    len = hb_min (cv_params.characters.len - start_offset, *char_count);
-     for (unsigned int i = 0; i < len; ++i)
-       characters[i] = cv_params.characters[start_offset + i];
-   }
-   if (char_count) *char_count = len;
-   return cv_params.characters.len;
- }
- 
- 
-@@ -1502,16 +1983,32 @@ typedef enum {
-   HB_OT_LAYOUT_BASELINE_ICFB = HB_TAG('i','c','f','b'),
-   HB_OT_LAYOUT_BASELINE_ICFT = HB_TAG('i','c','f','t'),
-   HB_OT_LAYOUT_BASELINE_IDEO = HB_TAG('i','d','e','o'),
-   HB_OT_LAYOUT_BASELINE_IDTB = HB_TAG('i','d','t','b'),
-   HB_OT_LAYOUT_BASELINE_MATH = HB_TAG('m','a','t','h'),
-   HB_OT_LAYOUT_BASELINE_ROMN = HB_TAG('r','o','m','n')
- } hb_ot_layout_baseline_t;
- 
-+
-+/**
-+ * hb_ot_layout_get_baseline:
-+ * @font: The #hb_font_t to work upon
-+ * @baseline: The #hb_ot_layout_baseline_t to query
-+ * @direction: The #hb_direction_t text direction to use (horizontal or vertical)
-+ * @script_tag:  #hb_tag_t of the script to use
-+ * @language_tag: #hb_tag_t of the language to use
-+ * @coord: (out): The position of the requested baseline
-+ *
-+ * Fetches the coordinates of the specified baseline in the face, underneath
-+ * the specified script and language and in the specified text direction.
-+ *
-+ * Return value: true if the baseline is found for the settings queried, false otherwise
-+ *
-+ **/
- HB_EXTERN hb_bool_t
- hb_ot_layout_get_baseline (hb_font_t               *font,
- 			   hb_ot_layout_baseline_t  baseline,
- 			   hb_direction_t           direction,
- 			   hb_tag_t                 script_tag,
- 			   hb_tag_t                 language_tag,
- 			   hb_position_t           *coord        /* OUT.  May be NULL. */);
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-layout.h b/gfx/harfbuzz/src/hb-ot-layout.h
---- a/gfx/harfbuzz/src/hb-ot-layout.h
-+++ b/gfx/harfbuzz/src/hb-ot-layout.h
-@@ -88,16 +88,27 @@ hb_ot_tags_to_script_and_language (hb_ta
- 
- /*
-  * GDEF
-  */
- 
- HB_EXTERN hb_bool_t
- hb_ot_layout_has_glyph_classes (hb_face_t *face);
- 
-+/**
-+ * hb_ot_layout_glyph_class_t:
-+ * @HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: Glyphs not matching the other classifications
-+ * @HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: Spacing, single characters, capable of accepting marks
-+ * @HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: Glyphs that represent ligation of multiple characters
-+ * @HB_OT_LAYOUT_GLYPH_CLASS_MARK: Non-spacing, combining glyphs that represent marks
-+ * @HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT: Spacing glyphs that represent part of a single character
-+ *
-+ * The GDEF classes defined for glyphs.
-+ *
-+ **/
- typedef enum {
-   HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED	= 0,
-   HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH	= 1,
-   HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE	= 2,
-   HB_OT_LAYOUT_GLYPH_CLASS_MARK		= 3,
-   HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT	= 4
- } hb_ot_layout_glyph_class_t;
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-map.cc b/gfx/harfbuzz/src/hb-ot-map.cc
---- a/gfx/harfbuzz/src/hb-ot-map.cc
-+++ b/gfx/harfbuzz/src/hb-ot-map.cc
-@@ -183,22 +183,22 @@ hb_ot_map_builder_t::compile (hb_ot_map_
- 	feature_infos[++j] = feature_infos[i];
-       else {
- 	if (feature_infos[i].flags & F_GLOBAL) {
- 	  feature_infos[j].flags |= F_GLOBAL;
- 	  feature_infos[j].max_value = feature_infos[i].max_value;
- 	  feature_infos[j].default_value = feature_infos[i].default_value;
- 	} else {
- 	  feature_infos[j].flags &= ~F_GLOBAL;
--	  feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value);
-+	  feature_infos[j].max_value = hb_max (feature_infos[j].max_value, feature_infos[i].max_value);
- 	  /* Inherit default_value from j */
- 	}
- 	feature_infos[j].flags |= (feature_infos[i].flags & F_HAS_FALLBACK);
--	feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_infos[i].stage[0]);
--	feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]);
-+	feature_infos[j].stage[0] = hb_min (feature_infos[j].stage[0], feature_infos[i].stage[0]);
-+	feature_infos[j].stage[1] = hb_min (feature_infos[j].stage[1], feature_infos[i].stage[1]);
-       }
-     feature_infos.shrink (j + 1);
-   }
- 
- 
-   /* Allocate bits now */
-   unsigned int next_bit = global_bit_shift + 1;
- 
-@@ -208,44 +208,44 @@ hb_ot_map_builder_t::compile (hb_ot_map_
- 
-     unsigned int bits_needed;
- 
-     if ((info->flags & F_GLOBAL) && info->max_value == 1)
-       /* Uses the global bit */
-       bits_needed = 0;
-     else
-       /* Limit bits per feature. */
--      bits_needed = MIN(HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
-+      bits_needed = hb_min (HB_OT_MAP_MAX_BITS, hb_bit_storage (info->max_value));
- 
-     if (!info->max_value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
-       continue; /* Feature disabled, or not enough bits. */
- 
- 
--    hb_bool_t found = false;
-+    bool found = false;
-     unsigned int feature_index[2];
-     for (unsigned int table_index = 0; table_index < 2; table_index++)
-     {
-       if (required_feature_tag[table_index] == info->tag)
- 	required_feature_stage[table_index] = info->stage[table_index];
- 
--      found |= hb_ot_layout_language_find_feature (face,
--						   table_tags[table_index],
--						   script_index[table_index],
--						   language_index[table_index],
--						   info->tag,
--						   &feature_index[table_index]);
-+      found |= (bool) hb_ot_layout_language_find_feature (face,
-+							  table_tags[table_index],
-+							  script_index[table_index],
-+							  language_index[table_index],
-+							  info->tag,
-+							  &feature_index[table_index]);
-     }
-     if (!found && (info->flags & F_GLOBAL_SEARCH))
-     {
-       for (unsigned int table_index = 0; table_index < 2; table_index++)
-       {
--	found |= hb_ot_layout_table_find_feature (face,
--						  table_tags[table_index],
--						  info->tag,
--						  &feature_index[table_index]);
-+	found |= (bool) hb_ot_layout_table_find_feature (face,
-+							 table_tags[table_index],
-+							 info->tag,
-+							 &feature_index[table_index]);
-       }
-     }
-     if (!found && !(info->flags & F_HAS_FALLBACK))
-       continue;
- 
- 
-     hb_ot_map_t::feature_map_t *map = m.features.push ();
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-map.hh b/gfx/harfbuzz/src/hb-ot-map.hh
---- a/gfx/harfbuzz/src/hb-ot-map.hh
-+++ b/gfx/harfbuzz/src/hb-ot-map.hh
-@@ -63,17 +63,17 @@ struct hb_ot_map_t
- 
-   struct lookup_map_t {
-     unsigned short index;
-     unsigned short auto_zwnj : 1;
-     unsigned short auto_zwj : 1;
-     unsigned short random : 1;
-     hb_mask_t mask;
- 
--    static int cmp (const void *pa, const void *pb)
-+    HB_INTERNAL static int cmp (const void *pa, const void *pb)
-     {
-       const lookup_map_t *a = (const lookup_map_t *) pa;
-       const lookup_map_t *b = (const lookup_map_t *) pb;
-       return a->index < b->index ? -1 : a->index > b->index ? 1 : 0;
-     }
-   };
- 
-   typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer);
-@@ -162,17 +162,17 @@ struct hb_ot_map_t
-   public:
-   hb_tag_t chosen_script[2];
-   bool found_script[2];
- 
-   private:
- 
-   hb_mask_t global_mask;
- 
--  hb_vector_t<feature_map_t> features;
-+  hb_sorted_vector_t<feature_map_t> features;
-   hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */
-   hb_vector_t<stage_map_t> stages[2]; /* GSUB/GPOS */
- };
- 
- enum hb_ot_map_feature_flags_t
- {
-   F_NONE		= 0x0000u,
-   F_GLOBAL		= 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */
-@@ -242,17 +242,17 @@ struct hb_ot_map_builder_t
-   struct feature_info_t {
-     hb_tag_t tag;
-     unsigned int seq; /* sequence#, used for stable sorting only */
-     unsigned int max_value;
-     hb_ot_map_feature_flags_t flags;
-     unsigned int default_value; /* for non-global features, what should the unset glyphs take */
-     unsigned int stage[2]; /* GSUB/GPOS */
- 
--    static int cmp (const void *pa, const void *pb)
-+    HB_INTERNAL static int cmp (const void *pa, const void *pb)
-     {
-       const feature_info_t *a = (const feature_info_t *) pa;
-       const feature_info_t *b = (const feature_info_t *) pb;
-       return (a->tag != b->tag) ?  (a->tag < b->tag ? -1 : 1) :
- 	     (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
-     }
-   };
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-math-table.hh b/gfx/harfbuzz/src/hb-ot-math-table.hh
---- a/gfx/harfbuzz/src/hb-ot-math-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-math-table.hh
-@@ -457,17 +457,17 @@ struct MathGlyphPartRecord
- 		hb_font_t *font) const
-   {
-     out.glyph			= glyph;
- 
-     out.start_connector_length	= font->em_scale (startConnectorLength, scale);
-     out.end_connector_length	= font->em_scale (endConnectorLength, scale);
-     out.full_advance		= font->em_scale (fullAdvance, scale);
- 
--    static_assert ((unsigned int) HB_MATH_GLYPH_PART_FLAG_EXTENDER ==
-+    static_assert ((unsigned int) HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER ==
- 		   (unsigned int) PartFlags::Extender, "");
- 
-     out.flags = (hb_ot_math_glyph_part_flags_t)
- 		(unsigned int)
- 		(partFlags & PartFlags::Defined);
-   }
- 
-   protected:
-@@ -659,17 +659,17 @@ struct MathVariants
- 					   * vertically growing variants. */
-   HBUINT16	     horizGlyphCount;     /* Number of glyphs for which
- 					   * information is provided for
- 					   * horizontally growing variants. */
- 
-   /* Array of offsets to MathGlyphConstruction tables - from the beginning of
-      the MathVariants table, for shapes growing in vertical/horizontal
-      direction. */
--  UnsizedArrayOf<OffsetTo<MathGlyphConstruction> >
-+  UnsizedArrayOf<OffsetTo<MathGlyphConstruction>>
-  			glyphConstruction;
- 
-   public:
-   DEFINE_SIZE_ARRAY (10, glyphConstruction);
- };
- 
- 
- /*
-diff --git a/gfx/harfbuzz/src/hb-ot-math.cc b/gfx/harfbuzz/src/hb-ot-math.cc
---- a/gfx/harfbuzz/src/hb-ot-math.cc
-+++ b/gfx/harfbuzz/src/hb-ot-math.cc
-@@ -32,222 +32,298 @@
- 
- /**
-  * SECTION:hb-ot-math
-  * @title: hb-ot-math
-  * @short_description: OpenType Math information
-  * @include: hb-ot.h
-  *
-  * Functions for fetching mathematics layout data from OpenType fonts.
-+ *
-+ * HarfBuzz itself does not implement a math layout solution. The
-+ * functions and types provided can be used by client programs to access
-+ * the font data necessary for typesetting OpenType Math layout.
-+ *
-  **/
- 
- 
- /*
-  * OT::MATH
-  */
- 
- /**
-  * hb_ot_math_has_data:
-  * @face: #hb_face_t to test
-  *
-- * This function allows to verify the presence of an OpenType MATH table on the
-- * face.
-+ * Tests whether a face has a `MATH` table.
-  *
-- * Return value: true if face has a MATH table, false otherwise
-+ * Return value: true if the table is found, false otherwise
-  *
-  * Since: 1.3.3
-  **/
- hb_bool_t
- hb_ot_math_has_data (hb_face_t *face)
- {
-+#ifdef HB_NO_MATH
-+  return false;
-+#endif
-+
-   return face->table.MATH->has_data ();
- }
- 
- /**
-  * hb_ot_math_get_constant:
-- * @font: #hb_font_t from which to retrieve the value
-+ * @font: #hb_font_t to work upon
-  * @constant: #hb_ot_math_constant_t the constant to retrieve
-  *
-- * This function returns the requested math constants as a #hb_position_t.
-- * If the request constant is HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
-- * HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
-- * HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN then the return value is
-- * actually an integer between 0 and 100 representing that percentage.
-+ * Fetches the specified math constant. For most constants, the value returned
-+ * is an #hb_position_t.
-  *
-- * Return value: the requested constant or 0
-+ * However, if the requested constant is #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN,
-+ * #HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN or
-+ * #HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN, then the return value is
-+ * an integer between 0 and 100 representing that percentage.
-+ *
-+ * Return value: the requested constant or zero
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_constant (hb_font_t *font,
- 			 hb_ot_math_constant_t constant)
- {
-+#ifdef HB_NO_MATH
-+  return 0;
-+#endif
-+
-   return font->face->table.MATH->get_constant(constant, font);
- }
- 
- /**
-  * hb_ot_math_get_glyph_italics_correction:
-- * @font: #hb_font_t from which to retrieve the value
-- * @glyph: glyph index from which to retrieve the value
-+ * @font: #hb_font_t to work upon
-+ * @glyph: The glyph index from which to retrieve the value
-  *
-- * Return value: the italics correction of the glyph or 0
-+ * Fetches an italics-correction value (if one exists) for the specified
-+ * glyph index.
-+ *
-+  * Return value: the italics correction of the glyph or zero
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
- 					 hb_codepoint_t glyph)
- {
-+#ifdef HB_NO_MATH
-+  return 0;
-+#endif
-+
-   return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font);
- }
- 
- /**
-  * hb_ot_math_get_glyph_top_accent_attachment:
-- * @font: #hb_font_t from which to retrieve the value
-- * @glyph: glyph index from which to retrieve the value
-+ * @font: #hb_font_t to work upon
-+ * @glyph: The glyph index from which to retrieve the value
-+ *
-+ * Fetches a top-accent-attachment value (if one exists) for the specified
-+ * glyph index.
-  *
-- * Return value: the top accent attachment of the glyph or 0
-+ * For any glyph that does not have a top-accent-attachment value - that is,
-+ * a glyph not covered by the `MathTopAccentAttachment` table (or, when
-+ * @font has no `MathTopAccentAttachment` table or no `MATH` table, any
-+ * glyph) - the function synthesizes a value, returning the position at
-+ * one-half the glyph's advance width.
-+ *
-+ * Return value: the top accent attachment of the glyph or 0.5 * the advance
-+ *               width of @glyph
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
- 					    hb_codepoint_t glyph)
- {
-+#ifdef HB_NO_MATH
-+  return 0;
-+#endif
-+
-   return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font);
- }
- 
- /**
-  * hb_ot_math_is_glyph_extended_shape:
-- * @face: a #hb_face_t to test
-- * @glyph: a glyph index to test
-+ * @face: #hb_face_t to work upon
-+ * @glyph: The glyph index to test
-+ *
-+ * Tests whether the given glyph index is an extended shape in the face.
-  *
-  * Return value: true if the glyph is an extended shape, false otherwise
-  *
-  * Since: 1.3.3
-  **/
- hb_bool_t
- hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
- 				    hb_codepoint_t glyph)
- {
-+#ifdef HB_NO_MATH
-+  return false;
-+#endif
-+
-   return face->table.MATH->get_glyph_info().is_extended_shape (glyph);
- }
- 
- /**
-  * hb_ot_math_get_glyph_kerning:
-- * @font: #hb_font_t from which to retrieve the value
-- * @glyph: glyph index from which to retrieve the value
-- * @kern: the #hb_ot_math_kern_t from which to retrieve the value
-+ * @font: #hb_font_t to work upon
-+ * @glyph: The glyph index from which to retrieve the value
-+ * @kern: The #hb_ot_math_kern_t from which to retrieve the value
-  * @correction_height: the correction height to use to determine the kerning.
-  *
-- * This function tries to retrieve the MathKern table for the specified font,
-- * glyph and #hb_ot_math_kern_t. Then it browses the list of heights from the
-- * MathKern table to find one value that is greater or equal to specified
-- * correction_height. If one is found the corresponding value from the list of
-- * kerns is returned and otherwise the last kern value is returned.
-+ * Fetches the math kerning (cut-ins) value for the specified font, glyph index, and
-+ * @kern. 
-  *
-- * Return value: requested kerning or 0
-+ * If the MathKern table is found, the function examines it to find a height
-+ * value that is greater or equal to @correction_height. If such a height
-+ * value is found, corresponding kerning value from the table is returned. If
-+ * no such height value is found, the last kerning value is returned.
-+ *
-+ * Return value: requested kerning value or zero
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_glyph_kerning (hb_font_t *font,
- 			      hb_codepoint_t glyph,
- 			      hb_ot_math_kern_t kern,
- 			      hb_position_t correction_height)
- {
-+#ifdef HB_NO_MATH
-+  return 0;
-+#endif
-+
-   return font->face->table.MATH->get_glyph_info().get_kerning (glyph,
- 							       kern,
- 							       correction_height,
- 							       font);
- }
- 
- /**
-  * hb_ot_math_get_glyph_variants:
-- * @font: #hb_font_t from which to retrieve the values
-- * @glyph: index of the glyph to stretch
-- * @direction: direction of the stretching
-+ * @font: #hb_font_t to work upon
-+ * @glyph: The index of the glyph to stretch
-+ * @direction: The direction of the stretching (horizontal or vertical)
-  * @start_offset: offset of the first variant to retrieve
-- * @variants_count: maximum number of variants to retrieve after start_offset
-- * (IN) and actual number of variants retrieved (OUT)
-- * @variants: array of size at least @variants_count to store the result
-+ * @variants_count: (inout): Input = the maximum number of variants to return;
-+ *                           Output = the actual number of variants returned
-+ * @variants: (out) (array length=variants_count): array of variants returned
-  *
-- * This function tries to retrieve the MathGlyphConstruction for the specified
-- * font, glyph and direction. Note that only the value of
-- * #HB_DIRECTION_IS_HORIZONTAL is considered. It provides the corresponding list
-- * of size variants as an array of hb_ot_math_glyph_variant_t structs.
-+ * Fetches the MathGlyphConstruction for the specified font, glyph index, and
-+ * direction. The corresponding list of size variants is returned as a list of
-+ * #hb_ot_math_glyph_variant_t structs.
-  *
-- * Return value: the total number of size variants available or 0
-+ * <note>The @direction parameter is only used to select between horizontal
-+ * or vertical directions for the construction. Even though all #hb_direction_t
-+ * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is
-+ * considered.</note> 
-+ *
-+ * Return value: the total number of size variants available or zero
-  *
-  * Since: 1.3.3
-  **/
- unsigned int
- hb_ot_math_get_glyph_variants (hb_font_t *font,
- 			       hb_codepoint_t glyph,
- 			       hb_direction_t direction,
- 			       unsigned int start_offset,
- 			       unsigned int *variants_count, /* IN/OUT */
- 			       hb_ot_math_glyph_variant_t *variants /* OUT */)
- {
-+#ifdef HB_NO_MATH
-+  if (variants_count)
-+    *variants_count = 0;
-+  return 0;
-+#endif
-+
-   return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font,
- 								    start_offset,
- 								    variants_count,
- 								    variants);
- }
- 
- /**
-  * hb_ot_math_get_min_connector_overlap:
-- * @font: #hb_font_t from which to retrieve the value
-- * @direction: direction of the stretching
-+ * @font: #hb_font_t to work upon
-+ * @direction: direction of the stretching (horizontal or vertical)
-+ *
-+ * Fetches the MathVariants table for the specified font and returns the
-+ * minimum overlap of connecting glyphs that are required to draw a glyph
-+ * assembly in the specified direction.
-  *
-- * This function tries to retrieve the MathVariants table for the specified
-- * font and returns the minimum overlap of connecting glyphs to draw a glyph
-- * assembly in the specified direction. Note that only the value of
-- * #HB_DIRECTION_IS_HORIZONTAL is considered.
-+ * <note>The @direction parameter is only used to select between horizontal
-+ * or vertical directions for the construction. Even though all #hb_direction_t
-+ * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is
-+ * considered.</note> 
-  *
-- * Return value: requested min connector overlap or 0
-+ * Return value: requested minimum connector overlap or zero
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_min_connector_overlap (hb_font_t *font,
- 				      hb_direction_t direction)
- {
-+#ifdef HB_NO_MATH
-+  return 0;
-+#endif
-+
-   return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font);
- }
- 
- /**
-  * hb_ot_math_get_glyph_assembly:
-- * @font: #hb_font_t from which to retrieve the values
-- * @glyph: index of the glyph to stretch
-- * @direction: direction of the stretching
-+ * @font: #hb_font_t to work upon
-+ * @glyph: The index of the glyph to stretch
-+ * @direction: direction of the stretching (horizontal or vertical)
-  * @start_offset: offset of the first glyph part to retrieve
-- * @parts_count: maximum number of glyph parts to retrieve after start_offset
-- * (IN) and actual number of parts retrieved (OUT)
-- * @parts: array of size at least @parts_count to store the result
-- * @italics_correction: italic correction of the glyph assembly
-+ * @parts_count: (inout): Input = maximum number of glyph parts to return;
-+ *               Output = actual number of parts returned
-+ * @parts: (out) (array length=parts_count): the glyph parts returned
-+ * @italics_correction: (out): italics correction of the glyph assembly
-  *
-- * This function tries to retrieve the GlyphAssembly for the specified font,
-- * glyph and direction. Note that only the value of #HB_DIRECTION_IS_HORIZONTAL
-- * is considered. It provides the information necessary to draw the glyph
-- * assembly as an array of #hb_ot_math_glyph_part_t.
-+ * Fetches the GlyphAssembly for the specified font, glyph index, and direction.
-+ * Returned are a list of #hb_ot_math_glyph_part_t glyph parts that can be
-+ * used to draw the glyph and an italics-correction value (if one is defined
-+ * in the font).
-+ *
-+ * <note>The @direction parameter is only used to select between horizontal
-+ * or vertical directions for the construction. Even though all #hb_direction_t
-+ * values are accepted, only the result of #HB_DIRECTION_IS_HORIZONTAL is
-+ * considered.</note> 
-  *
-  * Return value: the total number of parts in the glyph assembly
-  *
-  * Since: 1.3.3
-  **/
- unsigned int
- hb_ot_math_get_glyph_assembly (hb_font_t *font,
- 			       hb_codepoint_t glyph,
- 			       hb_direction_t direction,
- 			       unsigned int start_offset,
- 			       unsigned int *parts_count, /* IN/OUT */
- 			       hb_ot_math_glyph_part_t *parts, /* OUT */
- 			       hb_position_t *italics_correction /* OUT */)
- {
-+#ifdef HB_NO_MATH
-+  if (parts_count)
-+    *parts_count = 0;
-+  return 0;
-+#endif
-+
-   return font->face->table.MATH->get_variants().get_glyph_parts (glyph,
- 								 direction,
- 								 font,
- 								 start_offset,
- 								 parts_count,
- 								 parts,
- 								 italics_correction);
- }
-diff --git a/gfx/harfbuzz/src/hb-ot-math.h b/gfx/harfbuzz/src/hb-ot-math.h
---- a/gfx/harfbuzz/src/hb-ot-math.h
-+++ b/gfx/harfbuzz/src/hb-ot-math.h
-@@ -45,16 +45,19 @@ HB_BEGIN_DECLS
- /* Use with hb_buffer_set_script() for math shaping. */
- #define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
- 
- /* Types */
- 
- /**
-  * hb_ot_math_constant_t:
-  *
-+ * The 'MATH' table constants specified at
-+ * https://docs.microsoft.com/en-us/typography/opentype/spec/math
-+ *
-  * Since: 1.3.3
-  */
- typedef enum {
-   HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN = 0,
-   HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN = 1,
-   HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT = 2,
-   HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT = 3,
-   HB_OT_MATH_CONSTANT_MATH_LEADING = 4,
-@@ -109,46 +112,64 @@ typedef enum {
-   HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE = 53,
-   HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE = 54,
-   HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT = 55
- } hb_ot_math_constant_t;
- 
- /**
-  * hb_ot_math_kern_t:
-  *
-+ * The math kerning-table types defined for the four corners
-+ * of a glyph.
-+ *
-  * Since: 1.3.3
-  */
- typedef enum {
-   HB_OT_MATH_KERN_TOP_RIGHT = 0,
-   HB_OT_MATH_KERN_TOP_LEFT = 1,
-   HB_OT_MATH_KERN_BOTTOM_RIGHT = 2,
-   HB_OT_MATH_KERN_BOTTOM_LEFT = 3
- } hb_ot_math_kern_t;
- 
- /**
-  * hb_ot_math_glyph_variant_t:
-+ * @glyph: The glyph index of the variant
-+ * @advance: The advance width of the variant
-+ *
-+ * Data type to hold math-variant information for a glyph.
-  *
-  * Since: 1.3.3
-  */
- typedef struct hb_ot_math_glyph_variant_t {
-   hb_codepoint_t glyph;
-   hb_position_t advance;
- } hb_ot_math_glyph_variant_t;
- 
- /**
-  * hb_ot_math_glyph_part_flags_t:
-  *
-+ * Flags for math glyph parts.
-+ *
-  * Since: 1.3.3
-  */
- typedef enum { /*< flags >*/
--  HB_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
-+  HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER	= 0x00000001u  /* Extender glyph */
- } hb_ot_math_glyph_part_flags_t;
- 
- /**
-  * hb_ot_math_glyph_part_t:
-+ * @glyph: The glyph index of the variant part
-+ * @start_connector_length: The length of the connector on the starting side of the variant part
-+ * @end_connection_length: The length of the connector on the ending side of the variant part
-+ * @full_advance: The total advance of the part
-+ * @flags: #hb_ot_math_glyph_part_flags_t flags for the part
-+ * 
-+ * Data type to hold information for a "part" component of a math-variant glyph.
-+ * Large variants for stretchable math glyphs (such as parentheses) can be constructed
-+ * on the fly from parts.
-  *
-  * Since: 1.3.3
-  */
- typedef struct hb_ot_math_glyph_part_t {
-   hb_codepoint_t glyph;
-   hb_position_t start_connector_length;
-   hb_position_t end_connector_length;
-   hb_position_t full_advance;
-diff --git a/gfx/harfbuzz/src/hb-ot-maxp-table.hh b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
---- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
-@@ -72,17 +72,17 @@ struct maxpV1Tail
- struct maxp
- {
-   static constexpr hb_tag_t tableTag = HB_OT_TAG_maxp;
- 
-   unsigned int get_num_glyphs () const { return numGlyphs; }
- 
-   void set_num_glyphs (unsigned int count)
-   {
--    numGlyphs.set (count);
-+    numGlyphs = count;
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!c->check_struct (this)))
-       return_trace (false);
- 
-@@ -114,23 +114,23 @@ struct maxp
-     return result;
-   }
- 
-   static void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime)
-   {
-     if (maxp_prime->version.major == 1)
-     {
-       maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*maxp_prime);
--      v1.maxZones.set (1);
--      v1.maxTwilightPoints.set (0);
--      v1.maxStorage.set (0);
--      v1.maxFunctionDefs.set (0);
--      v1.maxInstructionDefs.set (0);
--      v1.maxStackElements.set (0);
--      v1.maxSizeOfInstructions.set (0);
-+      v1.maxZones = 1;
-+      v1.maxTwilightPoints = 0;
-+      v1.maxStorage = 0;
-+      v1.maxFunctionDefs = 0;
-+      v1.maxInstructionDefs = 0;
-+      v1.maxStackElements = 0;
-+      v1.maxSizeOfInstructions = 0;
-     }
-   }
- 
-   protected:
-   FixedVersion<>version;		/* Version of the maxp table (0.5 or 1.0),
- 					 * 0x00005000u or 0x00010000u. */
-   HBUINT16	numGlyphs;		/* The number of glyphs in the font. */
- /*maxpV1Tail	v1Tail[VAR]; */
-diff --git a/gfx/harfbuzz/src/hb-ot-name-language.cc b/gfx/harfbuzz/src/hb-ot-name-language-static.hh
-rename from gfx/harfbuzz/src/hb-ot-name-language.cc
-rename to gfx/harfbuzz/src/hb-ot-name-language-static.hh
---- a/gfx/harfbuzz/src/hb-ot-name-language.cc
-+++ b/gfx/harfbuzz/src/hb-ot-name-language-static.hh
-@@ -19,16 +19,19 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
-+#ifndef HB_OT_NAME_LANGUAGE_STATIC_HH
-+#define HB_OT_NAME_LANGUAGE_STATIC_HH
-+
- #include "hb-ot-name-language.hh"
- 
- /* Following two tables were generated by joining FreeType, FontConfig,
-  * and OpenType specification language lists, then filled in missing
-  * entries using:
-  * https://docs.microsoft.com/en-us/windows/desktop/intl/language-identifier-constants-and-strings
-  */
- 
-@@ -422,16 +425,19 @@ hb_mac_language_map[] =
- };
- 
- 
- static hb_language_t
- _hb_ot_name_language_for (unsigned int code,
- 			  const hb_ot_language_map_t *array,
- 			  unsigned int len)
- {
-+#ifdef HB_NO_OT_NAME_LANGUAGE
-+  return HB_LANGUAGE_INVALID;
-+#endif
-   const hb_ot_language_map_t *entry = (const hb_ot_language_map_t *)
- 				      hb_bsearch (&code,
- 						  array,
- 						  len,
- 						  sizeof (array[0]),
- 						  hb_ot_language_map_t::cmp);
- 
-   if (entry)
-@@ -450,8 +456,10 @@ hb_language_t
- 
- hb_language_t
- _hb_ot_name_language_for_mac_code (unsigned int code)
- {
-   return _hb_ot_name_language_for (code,
- 				   hb_mac_language_map,
- 				   ARRAY_LENGTH (hb_mac_language_map));
- }
-+
-+#endif /* HB_OT_NAME_LANGUAGE_STATIC_HH */
-diff --git a/gfx/harfbuzz/src/hb-ot-name-table.hh b/gfx/harfbuzz/src/hb-ot-name-table.hh
---- a/gfx/harfbuzz/src/hb-ot-name-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-name-table.hh
-@@ -46,28 +46,32 @@ namespace OT {
- #define HB_OT_TAG_name HB_TAG('n','a','m','e')
- 
- #define UNSUPPORTED	42
- 
- struct NameRecord
- {
-   hb_language_t language (hb_face_t *face) const
-   {
-+#ifndef HB_NO_OT_NAME_LANGUAGE
-     unsigned int p = platformID;
-     unsigned int l = languageID;
- 
-     if (p == 3)
-       return _hb_ot_name_language_for_ms_code (l);
- 
-     if (p == 1)
-       return _hb_ot_name_language_for_mac_code (l);
- 
-+#ifndef HB_NO_OT_NAME_LANGUAGE_AAT
-     if (p == 0)
-       return _hb_aat_language_get (face, l);
-+#endif
- 
-+#endif
-     return HB_LANGUAGE_INVALID;
-   }
- 
-   uint16_t score () const
-   {
-     /* Same order as in cmap::find_best_subtable(). */
-     unsigned int p = platformID;
-     unsigned int e = encodingID;
-@@ -88,29 +92,40 @@ struct NameRecord
-     if (p == 3 && e ==  0) return 8;
- 
-     /* We treat all Mac Latin names as ASCII only. */
-     if (p == 1 && e ==  0) return 10; /* 10 is magic number :| */
- 
-     return UNSUPPORTED;
-   }
- 
-+  NameRecord* copy (hb_serialize_context_t *c,
-+		    const void *src_base,
-+		    const void *dst_base) const
-+  {
-+    TRACE_SERIALIZE (this);
-+    auto *out = c->embed (this);
-+    if (unlikely (!out)) return_trace (nullptr);
-+    out->offset.serialize_copy (c, offset, src_base, dst_base, length);
-+    return_trace (out);
-+  }
-+
-   bool sanitize (hb_sanitize_context_t *c, const void *base) const
-   {
-     TRACE_SANITIZE (this);
--    /* We can check from base all the way up to the end of string... */
--    return_trace (c->check_struct (this) && c->check_range ((char *) base, (unsigned int) length + offset));
-+    return_trace (c->check_struct (this) && offset.sanitize (c, base, length));
-   }
- 
-   HBUINT16	platformID;	/* Platform ID. */
-   HBUINT16	encodingID;	/* Platform-specific encoding ID. */
-   HBUINT16	languageID;	/* Language ID. */
-   HBUINT16	nameID;		/* Name ID. */
-   HBUINT16	length;		/* String length (in bytes). */
--  HBUINT16	offset;		/* String offset from start of storage area (in bytes). */
-+  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
-+		offset;		/* String offset from start of storage area (in bytes). */
-   public:
-   DEFINE_SIZE_STATIC (12);
- };
- 
- static int
- _hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
- {
-   const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
-@@ -151,34 +166,78 @@ static int
- 
- struct name
- {
-   static constexpr hb_tag_t tableTag = HB_OT_TAG_name;
- 
-   unsigned int get_size () const
-   { return min_size + count * nameRecordZ.item_size; }
- 
-+  template <typename Iterator,
-+	    hb_requires (hb_is_source_of (Iterator, const NameRecord &))>
-+  bool serialize (hb_serialize_context_t *c,
-+		  Iterator it,
-+		  const void *src_string_pool)
-+  {
-+    TRACE_SERIALIZE (this);
-+
-+    if (unlikely (!c->extend_min ((*this))))  return_trace (false);
-+
-+    this->format = 0;
-+    this->count = it.len ();
-+
-+    auto snap = c->snapshot ();
-+    this->nameRecordZ.serialize (c, this->count);
-+    if (unlikely (!c->check_assign (this->stringOffset, c->length ()))) return_trace (false);
-+    c->revert (snap);
-+
-+    const void *dst_string_pool = &(this + this->stringOffset);
-+
-+    + it
-+    | hb_apply ([=] (const NameRecord& _) { c->copy (_, src_string_pool, dst_string_pool); })
-+    ;
-+
-+    if (unlikely (c->ran_out_of_room)) return_trace (false);
-+
-+    assert (this->stringOffset == c->length ());
-+
-+    return_trace (true);
-+  }
-+
-+  bool subset (hb_subset_context_t *c) const
-+  {
-+    TRACE_SUBSET (this);
-+
-+    name *name_prime = c->serializer->start_embed<name> ();
-+    if (unlikely (!name_prime)) return_trace (false);
-+
-+    auto it =
-+    + nameRecordZ.as_array (count)
-+    | hb_filter (c->plan->name_ids, &NameRecord::nameID)
-+    ;
-+
-+    name_prime->serialize (c->serializer, it, hb_addressof (this + stringOffset));
-+    return_trace (name_prime->count);
-+  }
-+
-   bool sanitize_records (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     const void *string_pool = (this+stringOffset).arrayZ;
--    unsigned int _count = count;
--    /* Move to run-time?! */
--    for (unsigned int i = 0; i < _count; i++)
--      if (!nameRecordZ[i].sanitize (c, string_pool)) return_trace (false);
--    return_trace (true);
-+    return_trace (nameRecordZ.sanitize (c, count, string_pool));
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  likely (format == 0 || format == 1) &&
- 		  c->check_array (nameRecordZ.arrayZ, count) &&
--		  c->check_range (this, stringOffset));
-+		  c->check_range (this, stringOffset) &&
-+		  sanitize_records (c));
-   }
- 
-   struct accelerator_t
-   {
-     void init (hb_face_t *face)
-     {
-       this->table = hb_sanitize_context_t().reference_table<name> (face);
-       assert (this->table.get_length () >= this->table->stringOffset);
-@@ -258,17 +317,17 @@ struct name
-     public:
-     hb_blob_ptr_t<name> table;
-     hb_vector_t<hb_ot_name_entry_t> names;
-   };
- 
-   /* We only implement format 0 for now. */
-   HBUINT16	format;			/* Format selector (=0/1). */
-   HBUINT16	count;			/* Number of name records. */
--  NNOffsetTo<UnsizedArrayOf<HBUINT8> >
-+  NNOffsetTo<UnsizedArrayOf<HBUINT8>>
- 		stringOffset;		/* Offset to start of string storage (from start of table). */
-   UnsizedArrayOf<NameRecord>
- 		nameRecordZ;		/* The name records where count is the number of records. */
-   public:
-   DEFINE_SIZE_ARRAY (6, nameRecordZ);
- };
- 
- struct name_accelerator_t : name::accelerator_t {};
-diff --git a/gfx/harfbuzz/src/hb-ot-name.cc b/gfx/harfbuzz/src/hb-ot-name.cc
---- a/gfx/harfbuzz/src/hb-ot-name.cc
-+++ b/gfx/harfbuzz/src/hb-ot-name.cc
-@@ -53,16 +53,21 @@
-  *
-  * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
-  * Since: 2.1.0
-  **/
- const hb_ot_name_entry_t *
- hb_ot_name_list_names (hb_face_t    *face,
- 		       unsigned int *num_entries /* OUT */)
- {
-+#ifdef HB_NO_NAME
-+  if (num_entries)
-+    *num_entries = 0;
-+  return 0;
-+#endif
-   const OT::name_accelerator_t &name = *face->table.name;
-   if (num_entries) *num_entries = name.names.length;
-   return (const hb_ot_name_entry_t *) name.names;
- }
- 
- 
- template <typename in_utf_t, typename out_utf_t>
- static inline unsigned int
-@@ -88,29 +93,29 @@ hb_ot_name_convert_utf (hb_bytes_t      
-     {
-       const typename in_utf_t::codepoint_t *src_next = in_utf_t::next (src, src_end, &unicode, replacement);
-       typename out_utf_t::codepoint_t *dst_next = out_utf_t::encode (dst, dst_end, unicode);
-       if (dst_next == dst)
-         break; /* Out-of-room. */
- 
-       dst = dst_next;
-       src = src_next;
--    };
-+    }
- 
-     *text_size = dst - text;
-     *dst = 0; /* NUL-terminate. */
-   }
- 
-   /* Accumulate length of rest. */
-   unsigned int dst_len = dst - text;
-   while (src < src_end)
-   {
-     src = in_utf_t::next (src, src_end, &unicode, replacement);
-     dst_len += out_utf_t::encode_len (unicode);
--  };
-+  }
-   return dst_len;
- }
- 
- template <typename utf_t>
- static inline unsigned int
- hb_ot_name_get_utf (hb_face_t       *face,
- 		    hb_ot_name_id_t  name_id,
- 		    hb_language_t    language,
-@@ -162,16 +167,21 @@ hb_ot_name_get_utf (hb_face_t       *fac
-  **/
- unsigned int
- hb_ot_name_get_utf8 (hb_face_t       *face,
- 		     hb_ot_name_id_t  name_id,
- 		     hb_language_t    language,
- 		     unsigned int    *text_size /* IN/OUT */,
- 		     char            *text      /* OUT */)
- {
-+#ifdef HB_NO_NAME
-+  if (text_size)
-+    *text_size = 0;
-+  return 0;
-+#endif
-   return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size,
- 					(hb_utf8_t::codepoint_t *) text);
- }
- 
- /**
-  * hb_ot_name_get_utf16:
-  * @face: font face.
-  * @name_id: OpenType name identifier to fetch.
-@@ -189,16 +199,21 @@ hb_ot_name_get_utf8 (hb_face_t       *fa
-  **/
- unsigned int
- hb_ot_name_get_utf16 (hb_face_t       *face,
- 		      hb_ot_name_id_t  name_id,
- 		      hb_language_t    language,
- 		      unsigned int    *text_size /* IN/OUT */,
- 		      uint16_t        *text      /* OUT */)
- {
-+#ifdef HB_NO_NAME
-+  if (text_size)
-+    *text_size = 0;
-+  return 0;
-+#endif
-   return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text);
- }
- 
- /**
-  * hb_ot_name_get_utf32:
-  * @face: font face.
-  * @name_id: OpenType name identifier to fetch.
-  * @language: language to fetch the name for.
-@@ -215,10 +230,15 @@ hb_ot_name_get_utf16 (hb_face_t       *f
-  **/
- unsigned int
- hb_ot_name_get_utf32 (hb_face_t       *face,
- 		      hb_ot_name_id_t  name_id,
- 		      hb_language_t    language,
- 		      unsigned int    *text_size /* IN/OUT */,
- 		      uint32_t        *text      /* OUT */)
- {
-+#ifdef HB_NO_NAME
-+  if (text_size)
-+    *text_size = 0;
-+  return 0;
-+#endif
-   return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
- }
-diff --git a/gfx/harfbuzz/src/hb-ot-os2-table.hh b/gfx/harfbuzz/src/hb-ot-os2-table.hh
---- a/gfx/harfbuzz/src/hb-ot-os2-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-os2-table.hh
-@@ -155,48 +155,48 @@ struct OS2
-     OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
-     if (unlikely (!os2_prime)) {
-       hb_blob_destroy (os2_prime_blob);
-       return false;
-     }
- 
-     uint16_t min_cp, max_cp;
-     find_min_and_max_codepoint (plan->unicodes, &min_cp, &max_cp);
--    os2_prime->usFirstCharIndex.set (min_cp);
--    os2_prime->usLastCharIndex.set (max_cp);
-+    os2_prime->usFirstCharIndex = min_cp;
-+    os2_prime->usLastCharIndex = max_cp;
- 
-     _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
-     bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob);
- 
-     hb_blob_destroy (os2_prime_blob);
-     return result;
-   }
- 
-   void _update_unicode_ranges (const hb_set_t *codepoints,
- 			       HBUINT32 ulUnicodeRange[4]) const
-   {
-     for (unsigned int i = 0; i < 4; i++)
--      ulUnicodeRange[i].set (0);
-+      ulUnicodeRange[i] = 0;
- 
-     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-     while (codepoints->next (&cp)) {
-       unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
-       if (bit < 128)
-       {
- 	unsigned int block = bit / 32;
- 	unsigned int bit_in_block = bit % 32;
- 	unsigned int mask = 1 << bit_in_block;
--	ulUnicodeRange[block].set (ulUnicodeRange[block] | mask);
-+	ulUnicodeRange[block] = ulUnicodeRange[block] | mask;
-       }
-       if (cp >= 0x10000 && cp <= 0x110000)
-       {
- 	/* the spec says that bit 57 ("Non Plane 0") implies that there's
- 	   at least one codepoint beyond the BMP; so I also include all
- 	   the non-BMP codepoints here */
--	ulUnicodeRange[1].set (ulUnicodeRange[1] | (1 << 25));
-+	ulUnicodeRange[1] = ulUnicodeRange[1] | (1 << 25);
-       }
-     }
-   }
- 
-   static void find_min_and_max_codepoint (const hb_set_t *codepoints,
- 						 uint16_t *min_cp, /* OUT */
- 						 uint16_t *max_cp  /* OUT */)
-   {
-diff --git a/gfx/harfbuzz/src/hb-ot-post-table.hh b/gfx/harfbuzz/src/hb-ot-post-table.hh
---- a/gfx/harfbuzz/src/hb-ot-post-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-post-table.hh
-@@ -83,17 +83,17 @@ struct post
- 
-     if (unlikely (!post_prime || post_prime_length != post::min_size))
-     {
-       hb_blob_destroy (post_prime_blob);
-       DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length);
-       return false;
-     }
- 
--    post_prime->version.major.set (3); // Version 3 does not have any glyph names.
-+    post_prime->version.major = 3; // Version 3 does not have any glyph names.
-     bool result = plan->add_table (HB_OT_TAG_post, post_prime_blob);
-     hb_blob_destroy (post_prime_blob);
- 
-     return result;
-   }
- 
-   struct accelerator_t
-   {
-@@ -126,17 +126,17 @@ struct post
-     }
- 
-     bool get_glyph_name (hb_codepoint_t glyph,
- 			 char *buf, unsigned int buf_len) const
-     {
-       hb_bytes_t s = find_glyph_name (glyph);
-       if (!s.length) return false;
-       if (!buf_len) return true;
--      unsigned int len = MIN (buf_len - 1, s.length);
-+      unsigned int len = hb_min (buf_len - 1, s.length);
-       strncpy (buf, s.arrayZ, len);
-       buf[len] = '\0';
-       return true;
-     }
- 
-     bool get_glyph_from_name (const char *name, int len,
- 			      hb_codepoint_t *glyph) const
-     {
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
-@@ -61,40 +61,41 @@ arabic_fallback_synthesize_lookup_single
- 
-     if (!s ||
- 	!hb_font_get_glyph (font, u, 0, &u_glyph) ||
- 	!hb_font_get_glyph (font, s, 0, &s_glyph) ||
- 	u_glyph == s_glyph ||
- 	u_glyph > 0xFFFFu || s_glyph > 0xFFFFu)
-       continue;
- 
--    glyphs[num_glyphs].set (u_glyph);
--    substitutes[num_glyphs].set (s_glyph);
-+    glyphs[num_glyphs] = u_glyph;
-+    substitutes[num_glyphs] = s_glyph;
- 
-     num_glyphs++;
-   }
- 
-   if (!num_glyphs)
-     return nullptr;
- 
-   /* Bubble-sort or something equally good!
-    * May not be good-enough for presidential candidate interviews, but good-enough for us... */
--  hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
-+  hb_stable_sort (&glyphs[0], num_glyphs,
-+		  (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::GlyphID::cmp,
-+		  &substitutes[0]);
- 
- 
-   /* Each glyph takes four bytes max, and there's some overhead. */
-   char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
-   hb_serialize_context_t c (buf, sizeof (buf));
-   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
-   bool ret = lookup->serialize_single (&c,
- 				       OT::LookupFlag::IgnoreMarks,
--				       hb_array (glyphs, num_glyphs),
-+				       hb_sorted_array (glyphs, num_glyphs),
- 				       hb_array (substitutes, num_glyphs));
-   c.end_serialize ();
--  /* TODO sanitize the results? */
- 
-   return ret ? c.copy<OT::SubstLookup> () : nullptr;
- }
- 
- static OT::SubstLookup *
- arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED,
- 					    hb_font_t *font)
- {
-@@ -113,22 +114,24 @@ arabic_fallback_synthesize_lookup_ligatu
- 
-   /* Sort out the first-glyphs */
-   for (unsigned int first_glyph_idx = 0; first_glyph_idx < ARRAY_LENGTH (first_glyphs); first_glyph_idx++)
-   {
-     hb_codepoint_t first_u = ligature_table[first_glyph_idx].first;
-     hb_codepoint_t first_glyph;
-     if (!hb_font_get_glyph (font, first_u, 0, &first_glyph))
-       continue;
--    first_glyphs[num_first_glyphs].set (first_glyph);
-+    first_glyphs[num_first_glyphs] = first_glyph;
-     ligature_per_first_glyph_count_list[num_first_glyphs] = 0;
-     first_glyphs_indirection[num_first_glyphs] = first_glyph_idx;
-     num_first_glyphs++;
-   }
--  hb_stable_sort (&first_glyphs[0], num_first_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &first_glyphs_indirection[0]);
-+  hb_stable_sort (&first_glyphs[0], num_first_glyphs,
-+		  (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::GlyphID::cmp,
-+		  &first_glyphs_indirection[0]);
- 
-   /* Now that the first-glyphs are sorted, walk again, populate ligatures. */
-   for (unsigned int i = 0; i < num_first_glyphs; i++)
-   {
-     unsigned int first_glyph_idx = first_glyphs_indirection[i];
- 
-     for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++)
-     {
-@@ -137,34 +140,34 @@ arabic_fallback_synthesize_lookup_ligatu
-       hb_codepoint_t second_glyph, ligature_glyph;
-       if (!second_u ||
- 	  !hb_font_get_glyph (font, second_u,   0, &second_glyph) ||
- 	  !hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph))
- 	continue;
- 
-       ligature_per_first_glyph_count_list[i]++;
- 
--      ligature_list[num_ligatures].set (ligature_glyph);
-+      ligature_list[num_ligatures] = ligature_glyph;
-       component_count_list[num_ligatures] = 2;
--      component_list[num_ligatures].set (second_glyph);
-+      component_list[num_ligatures] = second_glyph;
-       num_ligatures++;
-     }
-   }
- 
-   if (!num_ligatures)
-     return nullptr;
- 
- 
-   /* 16 bytes per ligature ought to be enough... */
-   char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
-   hb_serialize_context_t c (buf, sizeof (buf));
-   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
-   bool ret = lookup->serialize_ligature (&c,
- 					 OT::LookupFlag::IgnoreMarks,
--					 hb_array (first_glyphs, num_first_glyphs),
-+					 hb_sorted_array (first_glyphs, num_first_glyphs),
- 					 hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
- 					 hb_array (ligature_list, num_ligatures),
- 					 hb_array (component_count_list, num_ligatures),
- 					 hb_array (component_list, num_ligatures));
-   c.end_serialize ();
-   /* TODO sanitize the results? */
- 
-   return ret ? c.copy<OT::SubstLookup> () : nullptr;
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-arabic.cc
-@@ -378,16 +378,20 @@ setup_masks_arabic (const hb_ot_shape_pl
-   setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
- }
- 
- static void
- arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
- 		       hb_font_t *font,
- 		       hb_buffer_t *buffer)
- {
-+#ifdef HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
-+  return;
-+#endif
-+
-   const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
- 
-   if (!arabic_plan->do_fallback)
-     return;
- 
- retry:
-   arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
-   if (unlikely (!fallback_plan))
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
-@@ -65,16 +65,20 @@ compose_hebrew (const hb_ot_shape_normal
-     0xFB47u, /* QOF */
-     0xFB48u, /* RESH */
-     0xFB49u, /* SHIN */
-     0xFB4Au /* TAV */
-   };
- 
-   bool found = (bool) c->unicode->compose (a, b, ab);
- 
-+#ifdef HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
-+  return found;
-+#endif
-+
-   if (!found && !c->plan->has_gpos_mark)
-   {
-       /* Special-case Hebrew presentation forms that are excluded from
-        * standard normalization, but wanted for old fonts. */
-       switch (b) {
-       case 0x05B4u: /* HIRIQ */
- 	  if (a == 0x05D9u) { /* YOD */
- 	      *ab = 0xFB1Du;
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
-@@ -29,967 +29,364 @@
- #ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
- #define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
- 
- #include "hb.hh"
- 
- 
- #line 36 "hb-ot-shape-complex-indic-machine.hh"
- static const unsigned char _indic_syllable_machine_trans_keys[] = {
--	8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
--	5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 
--	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 
--	16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 
--	4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
--	7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 4u, 8u, 
--	6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 
--	4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 
--	4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 8u, 8u, 4u, 8u, 5u, 7u, 7u, 7u, 
--	5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 
--	7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
--	6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 4u, 13u, 
--	4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 8u, 8u, 4u, 8u, 5u, 7u, 
--	7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 5u, 7u, 7u, 7u, 5u, 8u, 
--	5u, 7u, 7u, 7u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 
--	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 13u, 4u, 8u, 
--	4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 8u, 4u, 13u, 4u, 13u, 
--	5u, 8u, 8u, 8u, 1u, 19u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
--	3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
--	3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 
--	5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 
--	4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
--	3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
--	3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 
--	1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
--	3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 
--	1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 
--	1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 
--	10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
--	3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 
--	4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 
--	1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
--	3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 4u, 8u, 3u, 17u, 3u, 17u, 
--	4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 
--	4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 
--	4u, 17u, 5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 
--	3u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 
--	3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 
--	1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 
--	3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 
--	1u, 16u, 1u, 16u, 4u, 13u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 
--	1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 
--	1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 3u, 17u, 4u, 17u, 
--	5u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 10u, 10u, 10u, 10u, 5u, 10u, 3u, 10u, 
--	5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 5u, 10u, 3u, 10u, 
--	4u, 10u, 5u, 10u, 3u, 10u, 4u, 10u, 4u, 10u, 3u, 17u, 3u, 17u, 1u, 16u, 
--	1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 
--	3u, 17u, 1u, 16u, 1u, 16u, 1u, 16u, 3u, 17u, 3u, 17u, 1u, 16u, 1u, 16u, 
--	1u, 16u, 3u, 17u, 1u, 17u, 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 
--	10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 5u, 10u, 5u, 10u, 10u, 10u, 
--	10u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0
-+	8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 
-+	4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 
-+	4u, 8u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 
-+	6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, 
-+	4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 5u, 8u, 8u, 8u, 1u, 19u, 
-+	3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, 
-+	1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 
-+	3u, 10u, 5u, 10u, 3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-+	3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 
-+	1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 
-+	5u, 10u, 3u, 17u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 
-+	3u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, 
-+	4u, 10u, 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 
-+	3u, 17u, 4u, 13u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u, 
-+	1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, 
-+	5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 1u, 17u, 
-+	3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u, 
-+	5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0
- };
- 
- static const char _indic_syllable_machine_key_spans[] = {
--	1, 5, 3, 1, 4, 3, 1, 4, 
--	3, 1, 4, 3, 1, 5, 1, 1, 
--	5, 1, 1, 5, 1, 1, 5, 1, 
--	1, 10, 5, 10, 5, 10, 5, 10, 
--	5, 10, 1, 5, 3, 1, 4, 3, 
--	1, 4, 3, 1, 4, 3, 1, 5, 
--	1, 1, 5, 1, 1, 5, 1, 1, 
--	5, 1, 1, 10, 5, 10, 5, 10, 
--	5, 10, 5, 10, 1, 5, 3, 1, 
--	4, 3, 1, 4, 3, 1, 4, 3, 
--	1, 5, 1, 1, 5, 1, 1, 5, 
--	1, 1, 5, 1, 1, 10, 5, 10, 
--	5, 10, 5, 10, 5, 1, 5, 3, 
--	1, 4, 3, 1, 4, 3, 1, 4, 
--	3, 1, 5, 1, 1, 5, 1, 1, 
--	5, 1, 1, 5, 1, 1, 10, 5, 
--	10, 5, 10, 5, 10, 5, 10, 10, 
--	4, 1, 19, 15, 15, 14, 16, 15, 
--	15, 14, 16, 15, 15, 14, 16, 15, 
--	15, 14, 16, 15, 15, 14, 6, 6, 
--	6, 1, 1, 1, 6, 8, 6, 8, 
--	7, 6, 8, 7, 6, 8, 7, 6, 
--	8, 7, 7, 15, 15, 16, 16, 16, 
--	15, 15, 16, 16, 16, 15, 15, 16, 
--	16, 16, 15, 15, 16, 16, 16, 15, 
--	15, 15, 15, 14, 16, 15, 15, 14, 
--	16, 15, 15, 14, 16, 15, 15, 14, 
--	16, 15, 15, 14, 6, 6, 6, 1, 
--	1, 1, 6, 8, 6, 8, 7, 6, 
--	8, 7, 6, 8, 7, 6, 8, 7, 
--	7, 15, 15, 16, 16, 16, 15, 15, 
--	16, 16, 16, 15, 15, 16, 16, 16, 
--	15, 15, 16, 16, 16, 5, 15, 15, 
--	14, 16, 15, 15, 14, 16, 15, 15, 
--	14, 16, 15, 15, 14, 16, 15, 15, 
--	14, 6, 6, 6, 1, 1, 1, 6, 
--	8, 6, 8, 7, 6, 8, 7, 6, 
--	8, 7, 6, 8, 7, 7, 15, 15, 
--	16, 16, 16, 15, 15, 16, 16, 16, 
--	15, 15, 16, 16, 16, 15, 15, 16, 
--	16, 16, 10, 15, 5, 15, 15, 14, 
--	16, 15, 15, 14, 16, 15, 15, 14, 
--	16, 15, 15, 14, 16, 15, 15, 14, 
--	6, 6, 6, 1, 1, 1, 6, 8, 
--	6, 8, 7, 6, 8, 7, 6, 8, 
--	7, 6, 8, 7, 7, 15, 15, 16, 
--	16, 16, 15, 15, 16, 16, 16, 15, 
--	15, 16, 16, 16, 15, 15, 16, 16, 
--	16, 15, 17, 15, 17, 10, 6, 1, 
--	1, 1, 6, 16, 8, 6, 6, 1, 
--	1, 1, 6, 16
-+	1, 5, 3, 4, 5, 1, 1, 5, 
-+	10, 5, 1, 3, 4, 5, 1, 1, 
-+	5, 10, 10, 10, 1, 3, 4, 5, 
-+	1, 1, 5, 5, 10, 1, 3, 4, 
-+	5, 1, 1, 5, 5, 4, 1, 19, 
-+	15, 15, 14, 16, 6, 6, 1, 6, 
-+	16, 16, 16, 8, 7, 6, 7, 6, 
-+	8, 6, 15, 15, 15, 15, 14, 16, 
-+	15, 15, 14, 16, 6, 1, 6, 16, 
-+	16, 8, 7, 6, 7, 6, 6, 8, 
-+	6, 15, 15, 5, 15, 15, 14, 16, 
-+	15, 16, 6, 1, 6, 16, 16, 8, 
-+	7, 6, 15, 7, 6, 6, 8, 6, 
-+	15, 10, 5, 15, 15, 14, 16, 15, 
-+	16, 6, 1, 6, 16, 16, 8, 7, 
-+	6, 15, 7, 6, 6, 8, 6, 17, 
-+	15, 17, 10, 6, 1, 6, 16, 8, 
-+	6, 6, 1, 6, 16
- };
- 
- static const short _indic_syllable_machine_index_offsets[] = {
--	0, 2, 8, 12, 14, 19, 23, 25, 
--	30, 34, 36, 41, 45, 47, 53, 55, 
--	57, 63, 65, 67, 73, 75, 77, 83, 
--	85, 87, 98, 104, 115, 121, 132, 138, 
--	149, 155, 166, 168, 174, 178, 180, 185, 
--	189, 191, 196, 200, 202, 207, 211, 213, 
--	219, 221, 223, 229, 231, 233, 239, 241, 
--	243, 249, 251, 253, 264, 270, 281, 287, 
--	298, 304, 315, 321, 332, 334, 340, 344, 
--	346, 351, 355, 357, 362, 366, 368, 373, 
--	377, 379, 385, 387, 389, 395, 397, 399, 
--	405, 407, 409, 415, 417, 419, 430, 436, 
--	447, 453, 464, 470, 481, 487, 489, 495, 
--	499, 501, 506, 510, 512, 517, 521, 523, 
--	528, 532, 534, 540, 542, 544, 550, 552, 
--	554, 560, 562, 564, 570, 572, 574, 585, 
--	591, 602, 608, 619, 625, 636, 642, 653, 
--	664, 669, 671, 691, 707, 723, 738, 755, 
--	771, 787, 802, 819, 835, 851, 866, 883, 
--	899, 915, 930, 947, 963, 979, 994, 1001, 
--	1008, 1015, 1017, 1019, 1021, 1028, 1037, 1044, 
--	1053, 1061, 1068, 1077, 1085, 1092, 1101, 1109, 
--	1116, 1125, 1133, 1141, 1157, 1173, 1190, 1207, 
--	1224, 1240, 1256, 1273, 1290, 1307, 1323, 1339, 
--	1356, 1373, 1390, 1406, 1422, 1439, 1456, 1473, 
--	1489, 1505, 1521, 1537, 1552, 1569, 1585, 1601, 
--	1616, 1633, 1649, 1665, 1680, 1697, 1713, 1729, 
--	1744, 1761, 1777, 1793, 1808, 1815, 1822, 1829, 
--	1831, 1833, 1835, 1842, 1851, 1858, 1867, 1875, 
--	1882, 1891, 1899, 1906, 1915, 1923, 1930, 1939, 
--	1947, 1955, 1971, 1987, 2004, 2021, 2038, 2054, 
--	2070, 2087, 2104, 2121, 2137, 2153, 2170, 2187, 
--	2204, 2220, 2236, 2253, 2270, 2287, 2293, 2309, 
--	2325, 2340, 2357, 2373, 2389, 2404, 2421, 2437, 
--	2453, 2468, 2485, 2501, 2517, 2532, 2549, 2565, 
--	2581, 2596, 2603, 2610, 2617, 2619, 2621, 2623, 
--	2630, 2639, 2646, 2655, 2663, 2670, 2679, 2687, 
--	2694, 2703, 2711, 2718, 2727, 2735, 2743, 2759, 
--	2775, 2792, 2809, 2826, 2842, 2858, 2875, 2892, 
--	2909, 2925, 2941, 2958, 2975, 2992, 3008, 3024, 
--	3041, 3058, 3075, 3086, 3102, 3108, 3124, 3140, 
--	3155, 3172, 3188, 3204, 3219, 3236, 3252, 3268, 
--	3283, 3300, 3316, 3332, 3347, 3364, 3380, 3396, 
--	3411, 3418, 3425, 3432, 3434, 3436, 3438, 3445, 
--	3454, 3461, 3470, 3478, 3485, 3494, 3502, 3509, 
--	3518, 3526, 3533, 3542, 3550, 3558, 3574, 3590, 
--	3607, 3624, 3641, 3657, 3673, 3690, 3707, 3724, 
--	3740, 3756, 3773, 3790, 3807, 3823, 3839, 3856, 
--	3873, 3890, 3906, 3924, 3940, 3958, 3969, 3976, 
--	3978, 3980, 3982, 3989, 4006, 4015, 4022, 4029, 
--	4031, 4033, 4035, 4042
-+	0, 2, 8, 12, 17, 23, 25, 27, 
-+	33, 44, 50, 52, 56, 61, 67, 69, 
-+	71, 77, 88, 99, 110, 112, 116, 121, 
-+	127, 129, 131, 137, 143, 154, 156, 160, 
-+	165, 171, 173, 175, 181, 187, 192, 194, 
-+	214, 230, 246, 261, 278, 285, 292, 294, 
-+	301, 318, 335, 352, 361, 369, 376, 384, 
-+	391, 400, 407, 423, 439, 455, 471, 486, 
-+	503, 519, 535, 550, 567, 574, 576, 583, 
-+	600, 617, 626, 634, 641, 649, 656, 663, 
-+	672, 679, 695, 711, 717, 733, 749, 764, 
-+	781, 797, 814, 821, 823, 830, 847, 864, 
-+	873, 881, 888, 904, 912, 919, 926, 935, 
-+	942, 958, 969, 975, 991, 1007, 1022, 1039, 
-+	1055, 1072, 1079, 1081, 1088, 1105, 1122, 1131, 
-+	1139, 1146, 1162, 1170, 1177, 1184, 1193, 1200, 
-+	1218, 1234, 1252, 1263, 1270, 1272, 1279, 1296, 
-+	1305, 1312, 1319, 1321, 1328
- };
- 
--static const short _indic_syllable_machine_indicies[] = {
-+static const unsigned char _indic_syllable_machine_indicies[] = {
- 	1, 0, 2, 3, 3, 4, 1, 0, 
--	5, 5, 4, 0, 4, 0, 6, 6, 
--	7, 1, 0, 8, 8, 7, 0, 7, 
--	0, 9, 9, 10, 1, 0, 11, 11, 
--	10, 0, 10, 0, 12, 12, 13, 1, 
--	0, 14, 14, 13, 0, 13, 0, 15, 
--	0, 0, 0, 1, 0, 16, 0, 17, 
--	0, 18, 12, 12, 13, 1, 0, 19, 
--	0, 20, 0, 21, 9, 9, 10, 1, 
--	0, 22, 0, 23, 0, 24, 6, 6, 
--	7, 1, 0, 25, 0, 26, 0, 2, 
--	3, 3, 4, 1, 0, 0, 0, 0, 
--	27, 0, 28, 3, 3, 4, 1, 0, 
--	28, 3, 3, 4, 1, 0, 0, 0, 
--	0, 29, 0, 30, 3, 3, 4, 1, 
--	0, 30, 3, 3, 4, 1, 0, 0, 
--	0, 0, 31, 0, 32, 3, 3, 4, 
--	1, 0, 32, 3, 3, 4, 1, 0, 
--	0, 0, 0, 33, 0, 34, 3, 3, 
--	4, 1, 0, 34, 3, 3, 4, 1, 
--	0, 0, 0, 0, 35, 0, 37, 36, 
--	38, 39, 39, 40, 37, 36, 41, 41, 
--	40, 36, 40, 36, 42, 42, 43, 37, 
--	36, 44, 44, 43, 36, 43, 36, 45, 
--	45, 46, 37, 36, 47, 47, 46, 36, 
--	46, 36, 48, 48, 49, 37, 36, 50, 
--	50, 49, 36, 49, 36, 51, 36, 36, 
--	36, 37, 36, 52, 36, 53, 36, 54, 
--	48, 48, 49, 37, 36, 55, 36, 56, 
--	36, 57, 45, 45, 46, 37, 36, 58, 
--	36, 59, 36, 60, 42, 42, 43, 37, 
--	36, 61, 36, 62, 36, 38, 39, 39, 
--	40, 37, 36, 36, 36, 36, 63, 36, 
--	64, 39, 39, 40, 37, 36, 64, 39, 
--	39, 40, 37, 36, 36, 36, 36, 65, 
--	36, 66, 39, 39, 40, 37, 36, 66, 
--	39, 39, 40, 37, 36, 36, 36, 36, 
--	67, 36, 68, 39, 39, 40, 37, 36, 
--	68, 39, 39, 40, 37, 36, 36, 36, 
--	36, 69, 36, 70, 39, 39, 40, 37, 
--	36, 70, 39, 39, 40, 37, 36, 36, 
--	36, 36, 71, 36, 73, 72, 74, 75, 
--	75, 76, 73, 72, 78, 78, 76, 77, 
--	76, 77, 79, 79, 80, 73, 72, 81, 
--	81, 80, 72, 80, 72, 82, 82, 83, 
--	73, 72, 84, 84, 83, 72, 83, 72, 
--	85, 85, 86, 73, 72, 87, 87, 86, 
--	72, 86, 72, 88, 72, 72, 72, 73, 
--	72, 89, 72, 90, 72, 91, 85, 85, 
--	86, 73, 72, 92, 72, 93, 72, 94, 
--	82, 82, 83, 73, 72, 95, 72, 96, 
--	72, 97, 79, 79, 80, 73, 72, 98, 
--	72, 99, 72, 74, 75, 75, 76, 73, 
--	72, 72, 72, 72, 100, 72, 101, 75, 
--	75, 76, 73, 72, 101, 75, 75, 76, 
--	73, 72, 72, 72, 72, 102, 72, 103, 
--	75, 75, 76, 73, 72, 103, 75, 75, 
--	76, 73, 72, 72, 72, 72, 104, 72, 
--	105, 75, 75, 76, 73, 72, 105, 75, 
--	75, 76, 73, 72, 72, 72, 72, 106, 
--	72, 107, 75, 75, 76, 73, 72, 109, 
--	108, 110, 111, 111, 112, 109, 108, 113, 
--	113, 112, 108, 112, 108, 114, 114, 115, 
--	109, 108, 116, 116, 115, 108, 115, 108, 
--	117, 117, 118, 109, 108, 119, 119, 118, 
--	108, 118, 108, 120, 120, 121, 109, 108, 
--	122, 122, 121, 108, 121, 108, 123, 108, 
--	108, 108, 109, 108, 124, 108, 125, 108, 
--	126, 120, 120, 121, 109, 108, 127, 108, 
--	128, 108, 129, 117, 117, 118, 109, 108, 
--	130, 108, 131, 108, 132, 114, 114, 115, 
--	109, 108, 133, 108, 134, 108, 110, 111, 
--	111, 112, 109, 108, 108, 108, 108, 135, 
--	108, 136, 111, 111, 112, 109, 108, 136, 
--	111, 111, 112, 109, 108, 108, 108, 108, 
--	137, 108, 138, 111, 111, 112, 109, 108, 
--	138, 111, 111, 112, 109, 108, 108, 108, 
--	108, 139, 108, 140, 111, 111, 112, 109, 
--	108, 140, 111, 111, 112, 109, 108, 108, 
--	108, 108, 141, 108, 142, 111, 111, 112, 
--	109, 108, 142, 111, 111, 112, 109, 108, 
--	108, 108, 108, 143, 108, 107, 75, 75, 
--	76, 73, 72, 72, 72, 72, 144, 72, 
--	78, 78, 76, 1, 0, 146, 145, 148, 
--	149, 150, 151, 152, 153, 76, 73, 147, 
--	154, 155, 155, 144, 147, 156, 157, 158, 
--	159, 160, 147, 162, 163, 164, 165, 4, 
--	1, 161, 166, 161, 161, 35, 161, 161, 
--	161, 167, 161, 168, 163, 169, 169, 4, 
--	1, 161, 166, 161, 161, 161, 161, 161, 
--	161, 167, 161, 163, 169, 169, 4, 1, 
--	161, 166, 161, 161, 161, 161, 161, 161, 
--	167, 161, 170, 161, 161, 161, 17, 171, 
--	161, 1, 161, 166, 161, 161, 161, 161, 
--	161, 170, 161, 172, 173, 174, 175, 4, 
--	1, 161, 166, 161, 161, 33, 161, 161, 
--	161, 167, 161, 176, 173, 177, 177, 4, 
--	1, 161, 166, 161, 161, 161, 161, 161, 
--	161, 167, 161, 173, 177, 177, 4, 1, 
--	161, 166, 161, 161, 161, 161, 161, 161, 
--	167, 161, 178, 161, 161, 161, 17, 179, 
--	161, 1, 161, 166, 161, 161, 161, 161, 
--	161, 178, 161, 180, 181, 182, 183, 4, 
--	1, 161, 166, 161, 161, 31, 161, 161, 
--	161, 167, 161, 184, 181, 185, 185, 4, 
--	1, 161, 166, 161, 161, 161, 161, 161, 
--	161, 167, 161, 181, 185, 185, 4, 1, 
--	161, 166, 161, 161, 161, 161, 161, 161, 
--	167, 161, 186, 161, 161, 161, 17, 187, 
--	161, 1, 161, 166, 161, 161, 161, 161, 
--	161, 186, 161, 188, 189, 190, 191, 4, 
--	1, 161, 166, 161, 161, 29, 161, 161, 
--	161, 167, 161, 192, 189, 193, 193, 4, 
--	1, 161, 166, 161, 161, 161, 161, 161, 
--	161, 167, 161, 189, 193, 193, 4, 1, 
--	161, 166, 161, 161, 161, 161, 161, 161, 
--	167, 161, 194, 161, 161, 161, 17, 195, 
--	161, 1, 161, 166, 161, 161, 161, 161, 
--	161, 194, 161, 196, 197, 198, 199, 4, 
--	1, 161, 166, 161, 161, 27, 161, 161, 
--	161, 167, 161, 200, 197, 201, 201, 4, 
--	1, 161, 166, 161, 161, 161, 161, 161, 
--	161, 167, 161, 197, 201, 201, 4, 1, 
--	161, 166, 161, 161, 161, 161, 161, 161, 
--	167, 161, 17, 202, 161, 1, 161, 166, 
--	161, 203, 203, 161, 1, 161, 166, 161, 
--	204, 161, 161, 205, 161, 166, 161, 166, 
--	161, 206, 161, 207, 161, 204, 161, 161, 
--	161, 161, 166, 161, 17, 161, 203, 203, 
--	161, 1, 161, 166, 161, 203, 202, 161, 
--	1, 161, 166, 161, 208, 26, 209, 210, 
--	7, 1, 161, 166, 161, 26, 209, 210, 
--	7, 1, 161, 166, 161, 209, 209, 7, 
--	1, 161, 166, 161, 211, 23, 212, 213, 
--	10, 1, 161, 166, 161, 23, 212, 213, 
--	10, 1, 161, 166, 161, 212, 212, 10, 
--	1, 161, 166, 161, 214, 20, 215, 216, 
--	13, 1, 161, 166, 161, 20, 215, 216, 
--	13, 1, 161, 166, 161, 215, 215, 13, 
--	1, 161, 166, 161, 217, 17, 203, 218, 
--	161, 1, 161, 166, 161, 17, 203, 218, 
--	161, 1, 161, 166, 161, 197, 201, 201, 
--	4, 1, 161, 166, 161, 196, 197, 201, 
--	201, 4, 1, 161, 166, 161, 161, 161, 
--	161, 161, 161, 167, 161, 196, 197, 198, 
--	201, 4, 1, 161, 166, 161, 161, 27, 
--	161, 161, 161, 167, 161, 194, 161, 219, 
--	161, 203, 203, 161, 1, 161, 166, 161, 
--	161, 161, 161, 161, 194, 161, 194, 161, 
--	161, 161, 203, 203, 161, 1, 161, 166, 
--	161, 161, 161, 161, 161, 194, 161, 194, 
--	161, 161, 161, 203, 195, 161, 1, 161, 
--	166, 161, 161, 161, 161, 161, 194, 161, 
--	188, 189, 193, 193, 4, 1, 161, 166, 
--	161, 161, 161, 161, 161, 161, 167, 161, 
--	188, 189, 190, 193, 4, 1, 161, 166, 
--	161, 161, 29, 161, 161, 161, 167, 161, 
--	186, 161, 220, 161, 203, 203, 161, 1, 
--	161, 166, 161, 161, 161, 161, 161, 186, 
--	161, 186, 161, 161, 161, 203, 203, 161, 
--	1, 161, 166, 161, 161, 161, 161, 161, 
--	186, 161, 186, 161, 161, 161, 203, 187, 
--	161, 1, 161, 166, 161, 161, 161, 161, 
--	161, 186, 161, 180, 181, 185, 185, 4, 
--	1, 161, 166, 161, 161, 161, 161, 161, 
--	161, 167, 161, 180, 181, 182, 185, 4, 
--	1, 161, 166, 161, 161, 31, 161, 161, 
--	161, 167, 161, 178, 161, 221, 161, 203, 
--	203, 161, 1, 161, 166, 161, 161, 161, 
--	161, 161, 178, 161, 178, 161, 161, 161, 
--	203, 203, 161, 1, 161, 166, 161, 161, 
--	161, 161, 161, 178, 161, 178, 161, 161, 
--	161, 203, 179, 161, 1, 161, 166, 161, 
--	161, 161, 161, 161, 178, 161, 172, 173, 
--	177, 177, 4, 1, 161, 166, 161, 161, 
--	161, 161, 161, 161, 167, 161, 172, 173, 
--	174, 177, 4, 1, 161, 166, 161, 161, 
--	33, 161, 161, 161, 167, 161, 170, 161, 
--	222, 161, 203, 203, 161, 1, 161, 166, 
--	161, 161, 161, 161, 161, 170, 161, 170, 
--	161, 161, 161, 203, 203, 161, 1, 161, 
--	166, 161, 161, 161, 161, 161, 170, 161, 
--	170, 161, 161, 161, 203, 171, 161, 1, 
--	161, 166, 161, 161, 161, 161, 161, 170, 
--	161, 162, 163, 169, 169, 4, 1, 161, 
--	166, 161, 161, 161, 161, 161, 161, 167, 
--	161, 162, 163, 164, 169, 4, 1, 161, 
--	166, 161, 161, 35, 161, 161, 161, 167, 
--	161, 224, 225, 226, 227, 40, 37, 223, 
--	228, 223, 223, 71, 223, 223, 223, 229, 
--	223, 230, 225, 231, 227, 40, 37, 223, 
--	228, 223, 223, 223, 223, 223, 223, 229, 
--	223, 225, 231, 227, 40, 37, 223, 228, 
--	223, 223, 223, 223, 223, 223, 229, 223, 
--	232, 223, 223, 223, 53, 233, 223, 37, 
--	223, 228, 223, 223, 223, 223, 223, 232, 
--	223, 234, 235, 236, 237, 40, 37, 223, 
--	228, 223, 223, 69, 223, 223, 223, 229, 
--	223, 238, 235, 239, 239, 40, 37, 223, 
--	228, 223, 223, 223, 223, 223, 223, 229, 
--	223, 235, 239, 239, 40, 37, 223, 228, 
--	223, 223, 223, 223, 223, 223, 229, 223, 
--	240, 223, 223, 223, 53, 241, 223, 37, 
--	223, 228, 223, 223, 223, 223, 223, 240, 
--	223, 242, 243, 244, 245, 40, 37, 223, 
--	228, 223, 223, 67, 223, 223, 223, 229, 
--	223, 246, 243, 247, 247, 40, 37, 223, 
--	228, 223, 223, 223, 223, 223, 223, 229, 
--	223, 243, 247, 247, 40, 37, 223, 228, 
--	223, 223, 223, 223, 223, 223, 229, 223, 
--	248, 223, 223, 223, 53, 249, 223, 37, 
--	223, 228, 223, 223, 223, 223, 223, 248, 
--	223, 250, 251, 252, 253, 40, 37, 223, 
--	228, 223, 223, 65, 223, 223, 223, 229, 
--	223, 254, 251, 255, 255, 40, 37, 223, 
--	228, 223, 223, 223, 223, 223, 223, 229, 
--	223, 251, 255, 255, 40, 37, 223, 228, 
--	223, 223, 223, 223, 223, 223, 229, 223, 
--	256, 223, 223, 223, 53, 257, 223, 37, 
--	223, 228, 223, 223, 223, 223, 223, 256, 
--	223, 258, 259, 260, 261, 40, 37, 223, 
--	228, 223, 223, 63, 223, 223, 223, 229, 
--	223, 262, 259, 263, 263, 40, 37, 223, 
--	228, 223, 223, 223, 223, 223, 223, 229, 
--	223, 259, 263, 263, 40, 37, 223, 228, 
--	223, 223, 223, 223, 223, 223, 229, 223, 
--	53, 264, 223, 37, 223, 228, 223, 265, 
--	265, 223, 37, 223, 228, 223, 266, 223, 
--	223, 267, 223, 228, 223, 228, 223, 268, 
--	223, 269, 223, 266, 223, 223, 223, 223, 
--	228, 223, 53, 223, 265, 265, 223, 37, 
--	223, 228, 223, 265, 264, 223, 37, 223, 
--	228, 223, 270, 62, 271, 272, 43, 37, 
--	223, 228, 223, 62, 271, 272, 43, 37, 
--	223, 228, 223, 271, 271, 43, 37, 223, 
--	228, 223, 273, 59, 274, 275, 46, 37, 
--	223, 228, 223, 59, 274, 275, 46, 37, 
--	223, 228, 223, 274, 274, 46, 37, 223, 
--	228, 223, 276, 56, 277, 278, 49, 37, 
--	223, 228, 223, 56, 277, 278, 49, 37, 
--	223, 228, 223, 277, 277, 49, 37, 223, 
--	228, 223, 279, 53, 265, 280, 223, 37, 
--	223, 228, 223, 53, 265, 280, 223, 37, 
--	223, 228, 223, 259, 263, 263, 40, 37, 
--	223, 228, 223, 258, 259, 263, 263, 40, 
--	37, 223, 228, 223, 223, 223, 223, 223, 
--	223, 229, 223, 258, 259, 260, 263, 40, 
--	37, 223, 228, 223, 223, 63, 223, 223, 
--	223, 229, 223, 256, 223, 281, 223, 265, 
--	265, 223, 37, 223, 228, 223, 223, 223, 
--	223, 223, 256, 223, 256, 223, 223, 223, 
--	265, 265, 223, 37, 223, 228, 223, 223, 
--	223, 223, 223, 256, 223, 256, 223, 223, 
--	223, 265, 257, 223, 37, 223, 228, 223, 
--	223, 223, 223, 223, 256, 223, 250, 251, 
--	255, 255, 40, 37, 223, 228, 223, 223, 
--	223, 223, 223, 223, 229, 223, 250, 251, 
--	252, 255, 40, 37, 223, 228, 223, 223, 
--	65, 223, 223, 223, 229, 223, 248, 223, 
--	282, 223, 265, 265, 223, 37, 223, 228, 
--	223, 223, 223, 223, 223, 248, 223, 248, 
--	223, 223, 223, 265, 265, 223, 37, 223, 
--	228, 223, 223, 223, 223, 223, 248, 223, 
--	248, 223, 223, 223, 265, 249, 223, 37, 
--	223, 228, 223, 223, 223, 223, 223, 248, 
--	223, 242, 243, 247, 247, 40, 37, 223, 
--	228, 223, 223, 223, 223, 223, 223, 229, 
--	223, 242, 243, 244, 247, 40, 37, 223, 
--	228, 223, 223, 67, 223, 223, 223, 229, 
--	223, 240, 223, 283, 223, 265, 265, 223, 
--	37, 223, 228, 223, 223, 223, 223, 223, 
--	240, 223, 240, 223, 223, 223, 265, 265, 
--	223, 37, 223, 228, 223, 223, 223, 223, 
--	223, 240, 223, 240, 223, 223, 223, 265, 
--	241, 223, 37, 223, 228, 223, 223, 223, 
--	223, 223, 240, 223, 234, 235, 239, 239, 
--	40, 37, 223, 228, 223, 223, 223, 223, 
--	223, 223, 229, 223, 234, 235, 236, 239, 
--	40, 37, 223, 228, 223, 223, 69, 223, 
--	223, 223, 229, 223, 232, 223, 284, 223, 
--	265, 265, 223, 37, 223, 228, 223, 223, 
--	223, 223, 223, 232, 223, 232, 223, 223, 
--	223, 265, 265, 223, 37, 223, 228, 223, 
--	223, 223, 223, 223, 232, 223, 232, 223, 
--	223, 223, 265, 233, 223, 37, 223, 228, 
--	223, 223, 223, 223, 223, 232, 223, 70, 
--	39, 39, 40, 37, 223, 224, 225, 231, 
--	227, 40, 37, 223, 228, 223, 223, 223, 
--	223, 223, 223, 229, 223, 286, 151, 287, 
--	287, 76, 73, 285, 154, 285, 285, 285, 
--	285, 285, 285, 158, 285, 151, 287, 287, 
--	76, 73, 285, 154, 285, 285, 285, 285, 
--	285, 285, 158, 285, 288, 285, 285, 285, 
--	90, 289, 285, 73, 285, 154, 285, 285, 
--	285, 285, 285, 288, 285, 290, 291, 292, 
--	293, 76, 73, 285, 154, 285, 285, 106, 
--	285, 285, 285, 158, 285, 294, 291, 295, 
--	295, 76, 73, 285, 154, 285, 285, 285, 
--	285, 285, 285, 158, 285, 291, 295, 295, 
--	76, 73, 285, 154, 285, 285, 285, 285, 
--	285, 285, 158, 285, 296, 285, 285, 285, 
--	90, 297, 285, 73, 285, 154, 285, 285, 
--	285, 285, 285, 296, 285, 298, 299, 300, 
--	301, 76, 73, 285, 154, 285, 285, 104, 
--	285, 285, 285, 158, 285, 302, 299, 303, 
--	303, 76, 73, 285, 154, 285, 285, 285, 
--	285, 285, 285, 158, 285, 299, 303, 303, 
--	76, 73, 285, 154, 285, 285, 285, 285, 
--	285, 285, 158, 285, 304, 285, 285, 285, 
--	90, 305, 285, 73, 285, 154, 285, 285, 
--	285, 285, 285, 304, 285, 306, 307, 308, 
--	309, 76, 73, 285, 154, 285, 285, 102, 
--	285, 285, 285, 158, 285, 310, 307, 311, 
--	311, 76, 73, 285, 154, 285, 285, 285, 
--	285, 285, 285, 158, 285, 307, 311, 311, 
--	76, 73, 285, 154, 285, 285, 285, 285, 
--	285, 285, 158, 285, 312, 285, 285, 285, 
--	90, 313, 285, 73, 285, 154, 285, 285, 
--	285, 285, 285, 312, 285, 314, 315, 316, 
--	317, 76, 73, 285, 154, 285, 285, 100, 
--	285, 285, 285, 158, 285, 318, 315, 319, 
--	319, 76, 73, 285, 154, 285, 285, 285, 
--	285, 285, 285, 158, 285, 315, 319, 319, 
--	76, 73, 285, 154, 285, 285, 285, 285, 
--	285, 285, 158, 285, 90, 320, 285, 73, 
--	285, 154, 285, 321, 321, 285, 73, 285, 
--	154, 285, 322, 285, 285, 323, 285, 154, 
--	285, 154, 285, 324, 285, 325, 285, 322, 
--	285, 285, 285, 285, 154, 285, 90, 285, 
--	321, 321, 285, 73, 285, 154, 285, 321, 
--	320, 285, 73, 285, 154, 285, 326, 99, 
--	327, 328, 80, 73, 285, 154, 285, 99, 
--	327, 328, 80, 73, 285, 154, 285, 327, 
--	327, 80, 73, 285, 154, 285, 329, 96, 
--	330, 331, 83, 73, 285, 154, 285, 96, 
--	330, 331, 83, 73, 285, 154, 285, 330, 
--	330, 83, 73, 285, 154, 285, 332, 93, 
--	333, 334, 86, 73, 285, 154, 285, 93, 
--	333, 334, 86, 73, 285, 154, 285, 333, 
--	333, 86, 73, 285, 154, 285, 335, 90, 
--	321, 336, 285, 73, 285, 154, 285, 90, 
--	321, 336, 285, 73, 285, 154, 285, 315, 
--	319, 319, 76, 73, 285, 154, 285, 314, 
--	315, 319, 319, 76, 73, 285, 154, 285, 
--	285, 285, 285, 285, 285, 158, 285, 314, 
--	315, 316, 319, 76, 73, 285, 154, 285, 
--	285, 100, 285, 285, 285, 158, 285, 312, 
--	285, 337, 285, 321, 321, 285, 73, 285, 
--	154, 285, 285, 285, 285, 285, 312, 285, 
--	312, 285, 285, 285, 321, 321, 285, 73, 
--	285, 154, 285, 285, 285, 285, 285, 312, 
--	285, 312, 285, 285, 285, 321, 313, 285, 
--	73, 285, 154, 285, 285, 285, 285, 285, 
--	312, 285, 306, 307, 311, 311, 76, 73, 
--	285, 154, 285, 285, 285, 285, 285, 285, 
--	158, 285, 306, 307, 308, 311, 76, 73, 
--	285, 154, 285, 285, 102, 285, 285, 285, 
--	158, 285, 304, 285, 338, 285, 321, 321, 
--	285, 73, 285, 154, 285, 285, 285, 285, 
--	285, 304, 285, 304, 285, 285, 285, 321, 
--	321, 285, 73, 285, 154, 285, 285, 285, 
--	285, 285, 304, 285, 304, 285, 285, 285, 
--	321, 305, 285, 73, 285, 154, 285, 285, 
--	285, 285, 285, 304, 285, 298, 299, 303, 
--	303, 76, 73, 285, 154, 285, 285, 285, 
--	285, 285, 285, 158, 285, 298, 299, 300, 
--	303, 76, 73, 285, 154, 285, 285, 104, 
--	285, 285, 285, 158, 285, 296, 285, 339, 
--	285, 321, 321, 285, 73, 285, 154, 285, 
--	285, 285, 285, 285, 296, 285, 296, 285, 
--	285, 285, 321, 321, 285, 73, 285, 154, 
--	285, 285, 285, 285, 285, 296, 285, 296, 
--	285, 285, 285, 321, 297, 285, 73, 285, 
--	154, 285, 285, 285, 285, 285, 296, 285, 
--	290, 291, 295, 295, 76, 73, 285, 154, 
--	285, 285, 285, 285, 285, 285, 158, 285, 
--	290, 291, 292, 295, 76, 73, 285, 154, 
--	285, 285, 106, 285, 285, 285, 158, 285, 
--	288, 285, 340, 285, 321, 321, 285, 73, 
--	285, 154, 285, 285, 285, 285, 285, 288, 
--	285, 288, 285, 285, 285, 321, 321, 285, 
--	73, 285, 154, 285, 285, 285, 285, 285, 
--	288, 285, 288, 285, 285, 285, 321, 289, 
--	285, 73, 285, 154, 285, 285, 285, 285, 
--	285, 288, 285, 107, 75, 75, 76, 73, 
--	341, 341, 341, 341, 144, 341, 150, 151, 
--	287, 287, 76, 73, 285, 154, 285, 285, 
--	285, 285, 285, 285, 158, 285, 107, 75, 
--	75, 76, 73, 341, 343, 344, 345, 346, 
--	112, 109, 342, 347, 342, 342, 143, 342, 
--	342, 342, 348, 342, 349, 344, 346, 346, 
--	112, 109, 342, 347, 342, 342, 342, 342, 
--	342, 342, 348, 342, 344, 346, 346, 112, 
--	109, 342, 347, 342, 342, 342, 342, 342, 
--	342, 348, 342, 350, 342, 342, 342, 125, 
--	351, 342, 109, 342, 347, 342, 342, 342, 
--	342, 342, 350, 342, 352, 353, 354, 355, 
--	112, 109, 342, 347, 342, 342, 141, 342, 
--	342, 342, 348, 342, 356, 353, 357, 357, 
--	112, 109, 342, 347, 342, 342, 342, 342, 
--	342, 342, 348, 342, 353, 357, 357, 112, 
--	109, 342, 347, 342, 342, 342, 342, 342, 
--	342, 348, 342, 358, 342, 342, 342, 125, 
--	359, 342, 109, 342, 347, 342, 342, 342, 
--	342, 342, 358, 342, 360, 361, 362, 363, 
--	112, 109, 342, 347, 342, 342, 139, 342, 
--	342, 342, 348, 342, 364, 361, 365, 365, 
--	112, 109, 342, 347, 342, 342, 342, 342, 
--	342, 342, 348, 342, 361, 365, 365, 112, 
--	109, 342, 347, 342, 342, 342, 342, 342, 
--	342, 348, 342, 366, 342, 342, 342, 125, 
--	367, 342, 109, 342, 347, 342, 342, 342, 
--	342, 342, 366, 342, 368, 369, 370, 371, 
--	112, 109, 342, 347, 342, 342, 137, 342, 
--	342, 342, 348, 342, 372, 369, 373, 373, 
--	112, 109, 342, 347, 342, 342, 342, 342, 
--	342, 342, 348, 342, 369, 373, 373, 112, 
--	109, 342, 347, 342, 342, 342, 342, 342, 
--	342, 348, 342, 374, 342, 342, 342, 125, 
--	375, 342, 109, 342, 347, 342, 342, 342, 
--	342, 342, 374, 342, 376, 377, 378, 379, 
--	112, 109, 342, 347, 342, 342, 135, 342, 
--	342, 342, 348, 342, 380, 377, 381, 381, 
--	112, 109, 342, 347, 342, 342, 342, 342, 
--	342, 342, 348, 342, 377, 381, 381, 112, 
--	109, 342, 347, 342, 342, 342, 342, 342, 
--	342, 348, 342, 125, 382, 342, 109, 342, 
--	347, 342, 383, 383, 342, 109, 342, 347, 
--	342, 384, 342, 342, 385, 342, 347, 342, 
--	347, 342, 386, 342, 387, 342, 384, 342, 
--	342, 342, 342, 347, 342, 125, 342, 383, 
--	383, 342, 109, 342, 347, 342, 383, 382, 
--	342, 109, 342, 347, 342, 388, 134, 389, 
--	390, 115, 109, 342, 347, 342, 134, 389, 
--	390, 115, 109, 342, 347, 342, 389, 389, 
--	115, 109, 342, 347, 342, 391, 131, 392, 
--	393, 118, 109, 342, 347, 342, 131, 392, 
--	393, 118, 109, 342, 347, 342, 392, 392, 
--	118, 109, 342, 347, 342, 394, 128, 395, 
--	396, 121, 109, 342, 347, 342, 128, 395, 
--	396, 121, 109, 342, 347, 342, 395, 395, 
--	121, 109, 342, 347, 342, 397, 125, 383, 
--	398, 342, 109, 342, 347, 342, 125, 383, 
--	398, 342, 109, 342, 347, 342, 377, 381, 
--	381, 112, 109, 342, 347, 342, 376, 377, 
--	381, 381, 112, 109, 342, 347, 342, 342, 
--	342, 342, 342, 342, 348, 342, 376, 377, 
--	378, 381, 112, 109, 342, 347, 342, 342, 
--	135, 342, 342, 342, 348, 342, 374, 342, 
--	399, 342, 383, 383, 342, 109, 342, 347, 
--	342, 342, 342, 342, 342, 374, 342, 374, 
--	342, 342, 342, 383, 383, 342, 109, 342, 
--	347, 342, 342, 342, 342, 342, 374, 342, 
--	374, 342, 342, 342, 383, 375, 342, 109, 
--	342, 347, 342, 342, 342, 342, 342, 374, 
--	342, 368, 369, 373, 373, 112, 109, 342, 
--	347, 342, 342, 342, 342, 342, 342, 348, 
--	342, 368, 369, 370, 373, 112, 109, 342, 
--	347, 342, 342, 137, 342, 342, 342, 348, 
--	342, 366, 342, 400, 342, 383, 383, 342, 
--	109, 342, 347, 342, 342, 342, 342, 342, 
--	366, 342, 366, 342, 342, 342, 383, 383, 
--	342, 109, 342, 347, 342, 342, 342, 342, 
--	342, 366, 342, 366, 342, 342, 342, 383, 
--	367, 342, 109, 342, 347, 342, 342, 342, 
--	342, 342, 366, 342, 360, 361, 365, 365, 
--	112, 109, 342, 347, 342, 342, 342, 342, 
--	342, 342, 348, 342, 360, 361, 362, 365, 
--	112, 109, 342, 347, 342, 342, 139, 342, 
--	342, 342, 348, 342, 358, 342, 401, 342, 
--	383, 383, 342, 109, 342, 347, 342, 342, 
--	342, 342, 342, 358, 342, 358, 342, 342, 
--	342, 383, 383, 342, 109, 342, 347, 342, 
--	342, 342, 342, 342, 358, 342, 358, 342, 
--	342, 342, 383, 359, 342, 109, 342, 347, 
--	342, 342, 342, 342, 342, 358, 342, 352, 
--	353, 357, 357, 112, 109, 342, 347, 342, 
--	342, 342, 342, 342, 342, 348, 342, 352, 
--	353, 354, 357, 112, 109, 342, 347, 342, 
--	342, 141, 342, 342, 342, 348, 342, 350, 
--	342, 402, 342, 383, 383, 342, 109, 342, 
--	347, 342, 342, 342, 342, 342, 350, 342, 
--	350, 342, 342, 342, 383, 383, 342, 109, 
--	342, 347, 342, 342, 342, 342, 342, 350, 
--	342, 350, 342, 342, 342, 383, 351, 342, 
--	109, 342, 347, 342, 342, 342, 342, 342, 
--	350, 342, 343, 344, 346, 346, 112, 109, 
--	342, 347, 342, 342, 342, 342, 342, 342, 
--	348, 342, 148, 149, 150, 151, 403, 287, 
--	76, 73, 285, 154, 155, 155, 144, 285, 
--	285, 148, 158, 285, 162, 404, 164, 165, 
--	4, 1, 161, 166, 161, 161, 35, 161, 
--	161, 161, 167, 161, 170, 149, 150, 151, 
--	405, 406, 76, 407, 161, 408, 161, 155, 
--	144, 161, 161, 170, 158, 161, 107, 409, 
--	409, 76, 407, 161, 166, 161, 161, 144, 
--	161, 410, 161, 161, 411, 161, 408, 161, 
--	408, 161, 412, 161, 207, 161, 410, 161, 
--	161, 161, 161, 408, 161, 170, 161, 222, 
--	107, 409, 409, 76, 407, 161, 166, 161, 
--	161, 161, 161, 161, 170, 161, 414, 413, 
--	415, 415, 413, 146, 413, 416, 413, 415, 
--	415, 413, 146, 413, 416, 413, 417, 413, 
--	413, 418, 413, 416, 413, 416, 413, 419, 
--	413, 420, 413, 417, 413, 413, 413, 413, 
--	416, 413, 148, 341, 341, 341, 341, 341, 
--	341, 341, 341, 341, 155, 341, 341, 341, 
--	341, 148, 341, 0
-+	3, 3, 4, 0, 3, 3, 4, 1, 
-+	0, 5, 3, 3, 4, 1, 0, 6, 
-+	0, 7, 0, 8, 3, 3, 4, 1, 
-+	0, 2, 3, 3, 4, 1, 0, 0, 
-+	0, 0, 9, 0, 11, 12, 12, 13, 
-+	14, 10, 14, 10, 12, 12, 13, 10, 
-+	12, 12, 13, 14, 10, 15, 12, 12, 
-+	13, 14, 10, 16, 10, 17, 10, 18, 
-+	12, 12, 13, 14, 10, 11, 12, 12, 
-+	13, 14, 10, 10, 10, 10, 19, 10, 
-+	11, 12, 12, 13, 14, 10, 10, 10, 
-+	10, 20, 10, 22, 23, 23, 24, 25, 
-+	21, 21, 21, 21, 26, 21, 25, 21, 
-+	23, 23, 24, 27, 23, 23, 24, 25, 
-+	21, 28, 23, 23, 24, 25, 21, 29, 
-+	21, 30, 21, 22, 23, 23, 24, 25, 
-+	21, 31, 23, 23, 24, 25, 21, 33, 
-+	34, 34, 35, 36, 32, 32, 32, 32, 
-+	37, 32, 36, 32, 34, 34, 35, 32, 
-+	34, 34, 35, 36, 32, 38, 34, 34, 
-+	35, 36, 32, 39, 32, 40, 32, 33, 
-+	34, 34, 35, 36, 32, 41, 34, 34, 
-+	35, 36, 32, 23, 23, 24, 1, 0, 
-+	43, 42, 45, 46, 47, 48, 49, 50, 
-+	24, 25, 44, 51, 52, 52, 26, 44, 
-+	53, 54, 55, 56, 57, 44, 59, 60, 
-+	61, 62, 4, 1, 58, 63, 58, 58, 
-+	9, 58, 58, 58, 64, 58, 65, 60, 
-+	66, 66, 4, 1, 58, 63, 58, 58, 
-+	58, 58, 58, 58, 64, 58, 60, 66, 
-+	66, 4, 1, 58, 63, 58, 58, 58, 
-+	58, 58, 58, 64, 58, 45, 58, 58, 
-+	58, 67, 68, 58, 1, 58, 63, 58, 
-+	58, 58, 58, 58, 45, 58, 69, 69, 
-+	58, 1, 58, 63, 58, 63, 58, 58, 
-+	70, 58, 63, 58, 63, 58, 63, 58, 
-+	58, 58, 58, 63, 58, 45, 58, 71, 
-+	58, 69, 69, 58, 1, 58, 63, 58, 
-+	58, 58, 58, 58, 45, 58, 45, 58, 
-+	58, 58, 69, 69, 58, 1, 58, 63, 
-+	58, 58, 58, 58, 58, 45, 58, 45, 
-+	58, 58, 58, 69, 68, 58, 1, 58, 
-+	63, 58, 58, 58, 58, 58, 45, 58, 
-+	72, 7, 73, 74, 4, 1, 58, 63, 
-+	58, 7, 73, 74, 4, 1, 58, 63, 
-+	58, 73, 73, 4, 1, 58, 63, 58, 
-+	75, 76, 76, 4, 1, 58, 63, 58, 
-+	67, 77, 58, 1, 58, 63, 58, 67, 
-+	58, 69, 69, 58, 1, 58, 63, 58, 
-+	69, 77, 58, 1, 58, 63, 58, 59, 
-+	60, 66, 66, 4, 1, 58, 63, 58, 
-+	58, 58, 58, 58, 58, 64, 58, 59, 
-+	60, 61, 66, 4, 1, 58, 63, 58, 
-+	58, 9, 58, 58, 58, 64, 58, 79, 
-+	80, 81, 82, 13, 14, 78, 83, 78, 
-+	78, 20, 78, 78, 78, 84, 78, 85, 
-+	80, 86, 82, 13, 14, 78, 83, 78, 
-+	78, 78, 78, 78, 78, 84, 78, 80, 
-+	86, 82, 13, 14, 78, 83, 78, 78, 
-+	78, 78, 78, 78, 84, 78, 87, 78, 
-+	78, 78, 88, 89, 78, 14, 78, 83, 
-+	78, 78, 78, 78, 78, 87, 78, 90, 
-+	80, 91, 92, 13, 14, 78, 83, 78, 
-+	78, 19, 78, 78, 78, 84, 78, 93, 
-+	80, 86, 86, 13, 14, 78, 83, 78, 
-+	78, 78, 78, 78, 78, 84, 78, 80, 
-+	86, 86, 13, 14, 78, 83, 78, 78, 
-+	78, 78, 78, 78, 84, 78, 87, 78, 
-+	78, 78, 94, 89, 78, 14, 78, 83, 
-+	78, 78, 78, 78, 78, 87, 78, 83, 
-+	78, 78, 95, 78, 83, 78, 83, 78, 
-+	83, 78, 78, 78, 78, 83, 78, 87, 
-+	78, 96, 78, 94, 94, 78, 14, 78, 
-+	83, 78, 78, 78, 78, 78, 87, 78, 
-+	87, 78, 78, 78, 94, 94, 78, 14, 
-+	78, 83, 78, 78, 78, 78, 78, 87, 
-+	78, 97, 17, 98, 99, 13, 14, 78, 
-+	83, 78, 17, 98, 99, 13, 14, 78, 
-+	83, 78, 98, 98, 13, 14, 78, 83, 
-+	78, 100, 101, 101, 13, 14, 78, 83, 
-+	78, 88, 102, 78, 14, 78, 83, 78, 
-+	94, 94, 78, 14, 78, 83, 78, 88, 
-+	78, 94, 94, 78, 14, 78, 83, 78, 
-+	94, 102, 78, 14, 78, 83, 78, 90, 
-+	80, 86, 86, 13, 14, 78, 83, 78, 
-+	78, 78, 78, 78, 78, 84, 78, 90, 
-+	80, 91, 86, 13, 14, 78, 83, 78, 
-+	78, 19, 78, 78, 78, 84, 78, 11, 
-+	12, 12, 13, 14, 78, 79, 80, 86, 
-+	82, 13, 14, 78, 83, 78, 78, 78, 
-+	78, 78, 78, 84, 78, 104, 48, 105, 
-+	105, 24, 25, 103, 51, 103, 103, 103, 
-+	103, 103, 103, 55, 103, 48, 105, 105, 
-+	24, 25, 103, 51, 103, 103, 103, 103, 
-+	103, 103, 55, 103, 106, 103, 103, 103, 
-+	107, 108, 103, 25, 103, 51, 103, 103, 
-+	103, 103, 103, 106, 103, 47, 48, 109, 
-+	110, 24, 25, 103, 51, 103, 103, 26, 
-+	103, 103, 103, 55, 103, 106, 103, 103, 
-+	103, 111, 108, 103, 25, 103, 51, 103, 
-+	103, 103, 103, 103, 106, 103, 51, 103, 
-+	103, 112, 103, 51, 103, 51, 103, 51, 
-+	103, 103, 103, 103, 51, 103, 106, 103, 
-+	113, 103, 111, 111, 103, 25, 103, 51, 
-+	103, 103, 103, 103, 103, 106, 103, 106, 
-+	103, 103, 103, 111, 111, 103, 25, 103, 
-+	51, 103, 103, 103, 103, 103, 106, 103, 
-+	114, 30, 115, 116, 24, 25, 103, 51, 
-+	103, 30, 115, 116, 24, 25, 103, 51, 
-+	103, 115, 115, 24, 25, 103, 51, 103, 
-+	47, 48, 105, 105, 24, 25, 103, 51, 
-+	103, 103, 103, 103, 103, 103, 55, 103, 
-+	117, 118, 118, 24, 25, 103, 51, 103, 
-+	107, 119, 103, 25, 103, 51, 103, 111, 
-+	111, 103, 25, 103, 51, 103, 107, 103, 
-+	111, 111, 103, 25, 103, 51, 103, 111, 
-+	119, 103, 25, 103, 51, 103, 47, 48, 
-+	109, 105, 24, 25, 103, 51, 103, 103, 
-+	26, 103, 103, 103, 55, 103, 22, 23, 
-+	23, 24, 25, 120, 120, 120, 120, 26, 
-+	120, 22, 23, 23, 24, 25, 120, 122, 
-+	123, 124, 125, 35, 36, 121, 126, 121, 
-+	121, 37, 121, 121, 121, 127, 121, 128, 
-+	123, 125, 125, 35, 36, 121, 126, 121, 
-+	121, 121, 121, 121, 121, 127, 121, 123, 
-+	125, 125, 35, 36, 121, 126, 121, 121, 
-+	121, 121, 121, 121, 127, 121, 129, 121, 
-+	121, 121, 130, 131, 121, 36, 121, 126, 
-+	121, 121, 121, 121, 121, 129, 121, 122, 
-+	123, 124, 52, 35, 36, 121, 126, 121, 
-+	121, 37, 121, 121, 121, 127, 121, 129, 
-+	121, 121, 121, 132, 131, 121, 36, 121, 
-+	126, 121, 121, 121, 121, 121, 129, 121, 
-+	126, 121, 121, 133, 121, 126, 121, 126, 
-+	121, 126, 121, 121, 121, 121, 126, 121, 
-+	129, 121, 134, 121, 132, 132, 121, 36, 
-+	121, 126, 121, 121, 121, 121, 121, 129, 
-+	121, 129, 121, 121, 121, 132, 132, 121, 
-+	36, 121, 126, 121, 121, 121, 121, 121, 
-+	129, 121, 135, 40, 136, 137, 35, 36, 
-+	121, 126, 121, 40, 136, 137, 35, 36, 
-+	121, 126, 121, 136, 136, 35, 36, 121, 
-+	126, 121, 122, 123, 125, 125, 35, 36, 
-+	121, 126, 121, 121, 121, 121, 121, 121, 
-+	127, 121, 138, 139, 139, 35, 36, 121, 
-+	126, 121, 130, 140, 121, 36, 121, 126, 
-+	121, 132, 132, 121, 36, 121, 126, 121, 
-+	130, 121, 132, 132, 121, 36, 121, 126, 
-+	121, 132, 140, 121, 36, 121, 126, 121, 
-+	45, 46, 47, 48, 109, 105, 24, 25, 
-+	103, 51, 52, 52, 26, 103, 103, 45, 
-+	55, 103, 59, 141, 61, 62, 4, 1, 
-+	58, 63, 58, 58, 9, 58, 58, 58, 
-+	64, 58, 45, 46, 47, 48, 142, 143, 
-+	24, 144, 58, 145, 58, 52, 26, 58, 
-+	58, 45, 55, 58, 22, 146, 146, 24, 
-+	144, 58, 63, 58, 58, 26, 58, 145, 
-+	58, 58, 147, 58, 145, 58, 145, 58, 
-+	145, 58, 58, 58, 58, 145, 58, 45, 
-+	58, 71, 22, 146, 146, 24, 144, 58, 
-+	63, 58, 58, 58, 58, 58, 45, 58, 
-+	149, 148, 150, 150, 148, 43, 148, 151, 
-+	148, 150, 150, 148, 43, 148, 151, 148, 
-+	151, 148, 148, 152, 148, 151, 148, 151, 
-+	148, 151, 148, 148, 148, 148, 151, 148, 
-+	45, 120, 120, 120, 120, 120, 120, 120, 
-+	120, 120, 52, 120, 120, 120, 120, 45, 
-+	120, 0
- };
- 
--static const short _indic_syllable_machine_trans_targs[] = {
--	138, 160, 166, 2, 167, 3, 5, 170, 
--	6, 8, 173, 9, 11, 176, 12, 14, 
--	15, 159, 17, 18, 175, 20, 21, 172, 
--	23, 24, 169, 179, 183, 184, 188, 189, 
--	193, 194, 198, 199, 138, 222, 228, 36, 
--	229, 37, 39, 232, 40, 42, 235, 43, 
--	45, 238, 46, 48, 49, 221, 51, 52, 
--	237, 54, 55, 234, 57, 58, 231, 241, 
--	245, 246, 250, 251, 255, 256, 260, 262, 
--	138, 283, 289, 70, 290, 138, 71, 73, 
--	293, 74, 76, 296, 77, 79, 299, 80, 
--	82, 83, 282, 85, 86, 298, 88, 89, 
--	295, 91, 92, 292, 302, 306, 307, 311, 
--	312, 316, 317, 321, 138, 346, 352, 103, 
--	353, 104, 106, 356, 107, 109, 359, 110, 
--	112, 362, 113, 115, 116, 345, 118, 119, 
--	361, 121, 122, 358, 124, 125, 355, 365, 
--	369, 370, 374, 375, 379, 380, 384, 385, 
--	323, 138, 398, 138, 139, 201, 263, 265, 
--	322, 324, 285, 325, 386, 387, 301, 396, 
--	403, 138, 140, 142, 33, 200, 162, 178, 
--	141, 32, 143, 196, 144, 146, 31, 195, 
--	145, 30, 147, 191, 148, 150, 29, 190, 
--	149, 28, 151, 186, 152, 154, 27, 185, 
--	153, 26, 155, 181, 156, 158, 25, 180, 
--	157, 1, 165, 0, 161, 164, 163, 138, 
--	168, 4, 22, 171, 7, 19, 174, 10, 
--	16, 177, 13, 182, 187, 192, 197, 138, 
--	202, 204, 67, 261, 224, 240, 203, 66, 
--	205, 258, 206, 208, 65, 257, 207, 64, 
--	209, 253, 210, 212, 63, 252, 211, 62, 
--	213, 248, 214, 216, 61, 247, 215, 60, 
--	217, 243, 218, 220, 59, 242, 219, 35, 
--	227, 34, 223, 226, 225, 138, 230, 38, 
--	56, 233, 41, 53, 236, 44, 50, 239, 
--	47, 244, 249, 254, 259, 138, 264, 100, 
--	266, 319, 267, 269, 99, 318, 268, 98, 
--	270, 314, 271, 273, 97, 313, 272, 96, 
--	274, 309, 275, 277, 95, 308, 276, 94, 
--	278, 304, 279, 281, 93, 303, 280, 69, 
--	288, 68, 284, 287, 286, 138, 291, 72, 
--	90, 294, 75, 87, 297, 78, 84, 300, 
--	81, 305, 310, 315, 320, 138, 138, 326, 
--	328, 134, 133, 348, 364, 327, 329, 382, 
--	330, 332, 132, 381, 331, 131, 333, 377, 
--	334, 336, 130, 376, 335, 129, 337, 372, 
--	338, 340, 128, 371, 339, 127, 341, 367, 
--	342, 344, 126, 366, 343, 102, 351, 101, 
--	347, 350, 349, 138, 354, 105, 123, 357, 
--	108, 120, 360, 111, 117, 363, 114, 368, 
--	373, 378, 383, 135, 388, 389, 395, 390, 
--	392, 136, 391, 394, 393, 138, 397, 137, 
--	400, 399, 402, 401, 138
-+static const unsigned char _indic_syllable_machine_trans_targs[] = {
-+	39, 45, 50, 2, 51, 5, 6, 53, 
-+	57, 58, 39, 67, 11, 73, 68, 14, 
-+	15, 75, 80, 81, 84, 39, 89, 21, 
-+	95, 90, 98, 39, 24, 25, 97, 103, 
-+	39, 112, 30, 118, 113, 121, 33, 34, 
-+	120, 126, 39, 137, 39, 40, 60, 85, 
-+	87, 105, 106, 91, 107, 127, 128, 99, 
-+	135, 140, 39, 41, 43, 8, 59, 46, 
-+	54, 42, 1, 44, 48, 0, 47, 49, 
-+	52, 3, 4, 55, 7, 56, 39, 61, 
-+	63, 18, 83, 69, 76, 62, 9, 64, 
-+	78, 71, 65, 17, 82, 66, 10, 70, 
-+	72, 74, 12, 13, 77, 16, 79, 39, 
-+	86, 26, 88, 101, 93, 19, 104, 20, 
-+	92, 94, 96, 22, 23, 100, 27, 102, 
-+	39, 39, 108, 110, 28, 35, 114, 122, 
-+	109, 111, 124, 116, 29, 115, 117, 119, 
-+	31, 32, 123, 36, 125, 129, 130, 134, 
-+	131, 132, 37, 133, 39, 136, 38, 138, 
-+	139
- };
- 
- static const char _indic_syllable_machine_trans_actions[] = {
- 	1, 0, 2, 0, 2, 0, 0, 2, 
--	0, 0, 2, 0, 0, 2, 0, 0, 
--	0, 2, 0, 0, 2, 0, 0, 2, 
--	0, 0, 2, 2, 2, 2, 2, 2, 
--	2, 2, 2, 2, 3, 0, 2, 0, 
--	2, 0, 0, 2, 0, 0, 2, 0, 
--	0, 2, 0, 0, 0, 2, 0, 0, 
--	2, 0, 0, 2, 0, 0, 2, 2, 
--	2, 2, 2, 2, 2, 2, 2, 2, 
--	4, 0, 2, 0, 2, 5, 0, 0, 
--	2, 0, 0, 2, 0, 0, 2, 0, 
--	0, 0, 2, 0, 0, 2, 0, 0, 
--	2, 0, 0, 2, 6, 2, 6, 2, 
--	6, 2, 6, 2, 7, 0, 2, 0, 
--	2, 0, 0, 2, 0, 0, 2, 0, 
--	0, 2, 0, 0, 0, 2, 0, 0, 
--	2, 0, 0, 2, 0, 0, 2, 2, 
--	2, 2, 2, 2, 2, 2, 2, 2, 
--	6, 8, 0, 11, 2, 2, 6, 0, 
--	12, 12, 0, 2, 6, 2, 6, 2, 
--	0, 13, 2, 0, 0, 2, 0, 2, 
--	2, 0, 2, 2, 2, 0, 0, 2, 
--	2, 0, 2, 2, 2, 0, 0, 2, 
--	2, 0, 2, 2, 2, 0, 0, 2, 
--	2, 0, 2, 2, 2, 0, 0, 2, 
--	2, 0, 2, 0, 0, 0, 0, 14, 
--	2, 0, 0, 2, 0, 0, 2, 0, 
--	0, 2, 0, 2, 2, 2, 2, 15, 
--	2, 0, 0, 2, 0, 2, 2, 0, 
--	2, 2, 2, 0, 0, 2, 2, 0, 
--	2, 2, 2, 0, 0, 2, 2, 0, 
--	2, 2, 2, 0, 0, 2, 2, 0, 
--	2, 2, 2, 0, 0, 2, 2, 0, 
--	2, 0, 0, 0, 0, 16, 2, 0, 
--	0, 2, 0, 0, 2, 0, 0, 2, 
--	0, 2, 2, 2, 2, 17, 6, 0, 
--	6, 2, 6, 0, 0, 6, 6, 0, 
--	6, 2, 6, 0, 0, 6, 6, 0, 
--	6, 2, 6, 0, 0, 6, 6, 0, 
--	6, 2, 6, 0, 0, 6, 6, 0, 
--	2, 0, 0, 0, 0, 18, 2, 0, 
--	0, 2, 0, 0, 2, 0, 0, 2, 
--	0, 2, 2, 2, 2, 19, 20, 2, 
--	0, 0, 0, 0, 2, 2, 2, 2, 
--	2, 0, 0, 2, 2, 0, 2, 2, 
--	2, 0, 0, 2, 2, 0, 2, 2, 
--	2, 0, 0, 2, 2, 0, 2, 2, 
--	2, 0, 0, 2, 2, 0, 2, 0, 
--	0, 0, 0, 21, 2, 0, 0, 2, 
--	0, 0, 2, 0, 0, 2, 0, 2, 
--	2, 2, 2, 0, 0, 22, 22, 0, 
--	0, 0, 0, 0, 0, 23, 2, 0, 
--	0, 0, 0, 0, 24
-+	2, 2, 3, 2, 0, 2, 0, 0, 
-+	0, 2, 2, 2, 2, 4, 2, 0, 
-+	5, 0, 5, 6, 0, 0, 5, 2, 
-+	7, 2, 0, 2, 0, 2, 0, 0, 
-+	2, 2, 8, 0, 11, 2, 2, 5, 
-+	0, 12, 12, 0, 2, 5, 2, 5, 
-+	2, 0, 13, 2, 0, 0, 2, 0, 
-+	2, 2, 0, 2, 2, 0, 0, 2, 
-+	2, 0, 0, 0, 0, 2, 14, 2, 
-+	0, 0, 2, 0, 2, 2, 0, 2, 
-+	2, 2, 2, 0, 2, 2, 0, 0, 
-+	2, 2, 0, 0, 0, 0, 2, 15, 
-+	5, 0, 5, 2, 2, 0, 5, 0, 
-+	0, 2, 5, 0, 0, 0, 0, 2, 
-+	16, 17, 2, 0, 0, 0, 0, 2, 
-+	2, 2, 2, 2, 0, 0, 2, 2, 
-+	0, 0, 0, 0, 2, 0, 18, 18, 
-+	0, 0, 0, 0, 19, 2, 0, 0, 
-+	0
- };
- 
- static const char _indic_syllable_machine_to_state_actions[] = {
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 9, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 9, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0
-+	0, 0, 0, 0, 0
- };
- 
- static const char _indic_syllable_machine_from_state_actions[] = {
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 10, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 10, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0
-+	0, 0, 0, 0, 0
- };
- 
- static const short _indic_syllable_machine_eof_trans[] = {
- 	1, 1, 1, 1, 1, 1, 1, 1, 
--	1, 1, 1, 1, 1, 1, 1, 1, 
--	1, 1, 1, 1, 1, 1, 1, 1, 
--	1, 1, 1, 1, 1, 1, 1, 1, 
--	1, 1, 37, 37, 37, 37, 37, 37, 
--	37, 37, 37, 37, 37, 37, 37, 37, 
--	37, 37, 37, 37, 37, 37, 37, 37, 
--	37, 37, 37, 37, 37, 37, 37, 37, 
--	37, 37, 37, 37, 73, 73, 78, 78, 
--	73, 73, 73, 73, 73, 73, 73, 73, 
--	73, 73, 73, 73, 73, 73, 73, 73, 
--	73, 73, 73, 73, 73, 73, 73, 73, 
--	73, 73, 73, 73, 73, 109, 109, 109, 
--	109, 109, 109, 109, 109, 109, 109, 109, 
--	109, 109, 109, 109, 109, 109, 109, 109, 
--	109, 109, 109, 109, 109, 109, 109, 109, 
--	109, 109, 109, 109, 109, 109, 109, 73, 
--	1, 146, 0, 162, 162, 162, 162, 162, 
--	162, 162, 162, 162, 162, 162, 162, 162, 
--	162, 162, 162, 162, 162, 162, 162, 162, 
--	162, 162, 162, 162, 162, 162, 162, 162, 
--	162, 162, 162, 162, 162, 162, 162, 162, 
--	162, 162, 162, 162, 162, 162, 162, 162, 
--	162, 162, 162, 162, 162, 162, 162, 162, 
--	162, 162, 162, 162, 162, 162, 162, 162, 
--	162, 224, 224, 224, 224, 224, 224, 224, 
--	224, 224, 224, 224, 224, 224, 224, 224, 
--	224, 224, 224, 224, 224, 224, 224, 224, 
--	224, 224, 224, 224, 224, 224, 224, 224, 
--	224, 224, 224, 224, 224, 224, 224, 224, 
--	224, 224, 224, 224, 224, 224, 224, 224, 
--	224, 224, 224, 224, 224, 224, 224, 224, 
--	224, 224, 224, 224, 224, 224, 224, 286, 
--	286, 286, 286, 286, 286, 286, 286, 286, 
--	286, 286, 286, 286, 286, 286, 286, 286, 
--	286, 286, 286, 286, 286, 286, 286, 286, 
--	286, 286, 286, 286, 286, 286, 286, 286, 
--	286, 286, 286, 286, 286, 286, 286, 286, 
--	286, 286, 286, 286, 286, 286, 286, 286, 
--	286, 286, 286, 286, 286, 286, 286, 286, 
--	286, 286, 342, 286, 342, 343, 343, 343, 
--	343, 343, 343, 343, 343, 343, 343, 343, 
--	343, 343, 343, 343, 343, 343, 343, 343, 
--	343, 343, 343, 343, 343, 343, 343, 343, 
--	343, 343, 343, 343, 343, 343, 343, 343, 
--	343, 343, 343, 343, 343, 343, 343, 343, 
--	343, 343, 343, 343, 343, 343, 343, 343, 
--	343, 343, 343, 343, 343, 343, 343, 343, 
--	343, 343, 286, 162, 162, 162, 162, 162, 
--	162, 162, 162, 162, 414, 414, 414, 414, 
--	414, 414, 414, 342
-+	1, 11, 11, 11, 11, 11, 11, 11, 
-+	11, 11, 11, 22, 22, 28, 22, 22, 
-+	22, 22, 22, 22, 33, 33, 33, 33, 
-+	33, 33, 33, 33, 33, 1, 43, 0, 
-+	59, 59, 59, 59, 59, 59, 59, 59, 
-+	59, 59, 59, 59, 59, 59, 59, 59, 
-+	59, 59, 59, 59, 79, 79, 79, 79, 
-+	79, 79, 79, 79, 79, 79, 79, 79, 
-+	79, 79, 79, 79, 79, 79, 79, 79, 
-+	79, 79, 79, 79, 79, 104, 104, 104, 
-+	104, 104, 104, 104, 104, 104, 104, 104, 
-+	104, 104, 104, 104, 104, 104, 104, 104, 
-+	104, 121, 121, 122, 122, 122, 122, 122, 
-+	122, 122, 122, 122, 122, 122, 122, 122, 
-+	122, 122, 122, 122, 122, 122, 122, 104, 
-+	59, 59, 59, 59, 59, 59, 59, 149, 
-+	149, 149, 149, 149, 121
- };
- 
--static const int indic_syllable_machine_start = 138;
--static const int indic_syllable_machine_first_final = 138;
-+static const int indic_syllable_machine_start = 39;
-+static const int indic_syllable_machine_first_final = 39;
- static const int indic_syllable_machine_error = -1;
- 
--static const int indic_syllable_machine_en_main = 138;
-+static const int indic_syllable_machine_en_main = 39;
- 
- 
- #line 36 "hb-ot-shape-complex-indic-machine.rl"
- 
- 
- 
- #line 93 "hb-ot-shape-complex-indic-machine.rl"
- 
-@@ -1005,47 +402,47 @@ static const int indic_syllable_machine_
- 
- static void
- find_syllables (hb_buffer_t *buffer)
- {
-   unsigned int p, pe, eof, ts, te, act;
-   int cs;
-   hb_glyph_info_t *info = buffer->info;
-   
--#line 1014 "hb-ot-shape-complex-indic-machine.hh"
-+#line 411 "hb-ot-shape-complex-indic-machine.hh"
- 	{
- 	cs = indic_syllable_machine_start;
- 	ts = 0;
- 	te = 0;
- 	act = 0;
- 	}
- 
- #line 113 "hb-ot-shape-complex-indic-machine.rl"
- 
- 
-   p = 0;
-   pe = eof = buffer->len;
- 
-   unsigned int syllable_serial = 1;
-   
--#line 1030 "hb-ot-shape-complex-indic-machine.hh"
-+#line 427 "hb-ot-shape-complex-indic-machine.hh"
- 	{
- 	int _slen;
- 	int _trans;
- 	const unsigned char *_keys;
--	const short *_inds;
-+	const unsigned char *_inds;
- 	if ( p == pe )
- 		goto _test_eof;
- _resume:
- 	switch ( _indic_syllable_machine_from_state_actions[cs] ) {
- 	case 10:
- #line 1 "NONE"
- 	{ts = p;}
- 	break;
--#line 1044 "hb-ot-shape-complex-indic-machine.hh"
-+#line 441 "hb-ot-shape-complex-indic-machine.hh"
- 	}
- 
- 	_keys = _indic_syllable_machine_trans_keys + (cs<<1);
- 	_inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
- 
- 	_slen = _indic_syllable_machine_key_spans[cs];
- 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
- 		( info[p].indic_category()) <= _keys[1] ?
-@@ -1057,61 +454,41 @@ find_syllables (hb_buffer_t *buffer)
- 	if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
- 		goto _again;
- 
- 	switch ( _indic_syllable_machine_trans_actions[_trans] ) {
- 	case 2:
- #line 1 "NONE"
- 	{te = p+1;}
- 	break;
--	case 14:
--#line 84 "hb-ot-shape-complex-indic-machine.rl"
--	{te = p+1;{ found_syllable (consonant_syllable); }}
--	break;
--	case 16:
--#line 85 "hb-ot-shape-complex-indic-machine.rl"
--	{te = p+1;{ found_syllable (vowel_syllable); }}
--	break;
--	case 21:
--#line 86 "hb-ot-shape-complex-indic-machine.rl"
--	{te = p+1;{ found_syllable (standalone_cluster); }}
--	break;
--	case 24:
--#line 87 "hb-ot-shape-complex-indic-machine.rl"
--	{te = p+1;{ found_syllable (symbol_cluster); }}
--	break;
--	case 18:
--#line 88 "hb-ot-shape-complex-indic-machine.rl"
--	{te = p+1;{ found_syllable (broken_cluster); }}
--	break;
- 	case 11:
- #line 89 "hb-ot-shape-complex-indic-machine.rl"
- 	{te = p+1;{ found_syllable (non_indic_cluster); }}
- 	break;
- 	case 13:
- #line 84 "hb-ot-shape-complex-indic-machine.rl"
- 	{te = p;p--;{ found_syllable (consonant_syllable); }}
- 	break;
--	case 15:
-+	case 14:
- #line 85 "hb-ot-shape-complex-indic-machine.rl"
- 	{te = p;p--;{ found_syllable (vowel_syllable); }}
- 	break;
--	case 20:
-+	case 17:
- #line 86 "hb-ot-shape-complex-indic-machine.rl"
- 	{te = p;p--;{ found_syllable (standalone_cluster); }}
- 	break;
--	case 23:
-+	case 19:
- #line 87 "hb-ot-shape-complex-indic-machine.rl"
- 	{te = p;p--;{ found_syllable (symbol_cluster); }}
- 	break;
--	case 17:
-+	case 15:
- #line 88 "hb-ot-shape-complex-indic-machine.rl"
- 	{te = p;p--;{ found_syllable (broken_cluster); }}
- 	break;
--	case 19:
-+	case 16:
- #line 89 "hb-ot-shape-complex-indic-machine.rl"
- 	{te = p;p--;{ found_syllable (non_indic_cluster); }}
- 	break;
- 	case 1:
- #line 84 "hb-ot-shape-complex-indic-machine.rl"
- 	{{p = ((te))-1;}{ found_syllable (consonant_syllable); }}
- 	break;
- 	case 3:
-@@ -1125,59 +502,59 @@ find_syllables (hb_buffer_t *buffer)
- 	case 8:
- #line 87 "hb-ot-shape-complex-indic-machine.rl"
- 	{{p = ((te))-1;}{ found_syllable (symbol_cluster); }}
- 	break;
- 	case 4:
- #line 88 "hb-ot-shape-complex-indic-machine.rl"
- 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
- 	break;
--	case 5:
-+	case 6:
- #line 1 "NONE"
- 	{	switch( act ) {
- 	case 1:
- 	{{p = ((te))-1;} found_syllable (consonant_syllable); }
- 	break;
- 	case 5:
- 	{{p = ((te))-1;} found_syllable (broken_cluster); }
- 	break;
- 	case 6:
- 	{{p = ((te))-1;} found_syllable (non_indic_cluster); }
- 	break;
- 	}
- 	}
- 	break;
--	case 22:
-+	case 18:
- #line 1 "NONE"
- 	{te = p+1;}
- #line 84 "hb-ot-shape-complex-indic-machine.rl"
- 	{act = 1;}
- 	break;
--	case 6:
-+	case 5:
- #line 1 "NONE"
- 	{te = p+1;}
- #line 88 "hb-ot-shape-complex-indic-machine.rl"
- 	{act = 5;}
- 	break;
- 	case 12:
- #line 1 "NONE"
- 	{te = p+1;}
- #line 89 "hb-ot-shape-complex-indic-machine.rl"
- 	{act = 6;}
- 	break;
--#line 1167 "hb-ot-shape-complex-indic-machine.hh"
-+#line 544 "hb-ot-shape-complex-indic-machine.hh"
- 	}
- 
- _again:
- 	switch ( _indic_syllable_machine_to_state_actions[cs] ) {
- 	case 9:
- #line 1 "NONE"
- 	{ts = 0;}
- 	break;
--#line 1176 "hb-ot-shape-complex-indic-machine.hh"
-+#line 553 "hb-ot-shape-complex-indic-machine.hh"
- 	}
- 
- 	if ( ++p != pe )
- 		goto _resume;
- 	_test_eof: {}
- 	if ( p == eof )
- 	{
- 	if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic-machine.rl
-@@ -59,24 +59,24 @@ CS    = 19;
- c = (C | Ra);			# is_consonant
- n = ((ZWNJ?.RS)? (N.N?)?);	# is_consonant_modifier
- z = ZWJ|ZWNJ;			# is_joiner
- reph = (Ra H | Repha);		# possible reph
- 
- cn = c.ZWJ?.n?;
- forced_rakar = ZWJ H ZWJ Ra;
- symbol = Symbol.N?;
--matra_group = z{0,3}.M.N?.(H | forced_rakar)?;
--syllable_tail = (z?.SM.SM?.ZWNJ?)? A{0,3}?;
-+matra_group = z*.M.N?.(H | forced_rakar)?;
-+syllable_tail = (z?.SM.SM?.ZWNJ?)? A*;
- halant_group = (z?.H.(ZWJ.N?)?);
- final_halant_group = halant_group | H.ZWNJ;
- medial_group = CM?;
--halant_or_matra_group = (final_halant_group | matra_group{0,4});
-+halant_or_matra_group = (final_halant_group | matra_group*);
- 
--complex_syllable_tail = (halant_group.cn){0,4} medial_group halant_or_matra_group syllable_tail;
-+complex_syllable_tail = (halant_group.cn)* medial_group halant_or_matra_group syllable_tail;
- 
- consonant_syllable =	(Repha|CS)? cn complex_syllable_tail;
- vowel_syllable =	reph? V.n? (ZWJ | complex_syllable_tail);
- standalone_cluster =	((Repha|CS)? PLACEHOLDER | reph? DOTTEDCIRCLE).n? complex_syllable_tail;
- symbol_cluster = 	symbol syllable_tail;
- broken_cluster =	reph? n? complex_syllable_tail;
- other =			any;
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.cc
-@@ -269,17 +269,21 @@ struct indic_shape_plan_t
- 
-     *pglyph = glyph;
-     return glyph != 0;
-   }
- 
-   const indic_config_t *config;
- 
-   bool is_old_spec;
-+#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
-   bool uniscribe_bug_compatible;
-+#else
-+  static constexpr bool uniscribe_bug_compatible = false;
-+#endif
-   mutable hb_atomic_int_t virama_glyph;
- 
-   would_substitute_feature_t rphf;
-   would_substitute_feature_t pref;
-   would_substitute_feature_t blwf;
-   would_substitute_feature_t pstf;
- 
-   hb_mask_t mask_array[INDIC_NUM_FEATURES];
-@@ -295,17 +299,19 @@ data_create_indic (const hb_ot_shape_pla
-   indic_plan->config = &indic_configs[0];
-   for (unsigned int i = 1; i < ARRAY_LENGTH (indic_configs); i++)
-     if (plan->props.script == indic_configs[i].script) {
-       indic_plan->config = &indic_configs[i];
-       break;
-     }
- 
-   indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
-+#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
-   indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
-+#endif
-   indic_plan->virama_glyph.set_relaxed (-1);
- 
-   /* Use zero-context would_substitute() matching for new-spec of the main
-    * Indic scripts, and scripts with one spec only, but not for old-specs.
-    * The new-spec for all dual-spec scripts says zero-context matching happens.
-    *
-    * However, testing with Malayalam shows that old and new spec both allow
-    * context.  Testing with Bengali new-spec however shows that it doesn't.
-@@ -640,17 +646,17 @@ initial_reordering_consonant_syllable (c
-    *
-    * We don't need to do this: the normalize() routine already did this for us.
-    */
- 
- 
-   /* Reorder characters */
- 
-   for (unsigned int i = start; i < base; i++)
--    info[i].indic_position() = MIN (POS_PRE_C, (indic_position_t) info[i].indic_position());
-+    info[i].indic_position() = hb_min (POS_PRE_C, (indic_position_t) info[i].indic_position());
- 
-   if (base < end)
-     info[base].indic_position() = POS_BASE_C;
- 
-   /* Mark final consonants.  A final consonant is one appearing after a matra.
-    * Happens in Sinhala. */
-   for (unsigned int i = base + 1; i < end; i++)
-     if (info[i].indic_category() == OT_M) {
-@@ -796,17 +802,17 @@ initial_reordering_consonant_syllable (c
-       /* Note!  syllable() is a one-byte field. */
-       for (unsigned int i = base; i < end; i++)
-         if (info[i].syllable() != 255)
- 	{
- 	  unsigned int max = i;
- 	  unsigned int j = start + info[i].syllable();
- 	  while (j != i)
- 	  {
--	    max = MAX (max, j);
-+	    max = hb_max (max, j);
- 	    unsigned int next = start + info[j].syllable();
- 	    info[j].syllable() = 255; /* So we don't process j later again. */
- 	    j = next;
- 	  }
- 	  if (i != max)
- 	    buffer->merge_clusters (i, max + 1);
- 	}
-     }
-@@ -913,21 +919,20 @@ initial_reordering_consonant_syllable (c
- }
- 
- static void
- initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
- 				       hb_face_t *face,
- 				       hb_buffer_t *buffer,
- 				       unsigned int start, unsigned int end)
- {
--  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
--
-   /* We treat placeholder/dotted-circle as if they are consonants, so we
-    * should just chain.  Only if not in compatibility mode that is... */
- 
-+  const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
-   if (indic_plan->uniscribe_bug_compatible)
-   {
-     /* For dotted-circle, this is what Uniscribe does:
-      * If dotted-circle is the last glyph, it just does nothing.
-      * Ie. It doesn't form Reph. */
-     if (buffer->info[end - 1].indic_category() == OT_DOTTEDCIRCLE)
-       return;
-   }
-@@ -1003,17 +1008,16 @@ insert_dotted_circles (const hb_ot_shape
-     if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
-     {
-       last_syllable = syllable;
- 
-       hb_glyph_info_t ginfo = dottedcircle;
-       ginfo.cluster = buffer->cur().cluster;
-       ginfo.mask = buffer->cur().mask;
-       ginfo.syllable() = buffer->cur().syllable();
--      /* TODO Set glyph_props? */
- 
-       /* Insert dottedcircle after possible Repha. */
-       while (buffer->idx < buffer->len && buffer->successful &&
- 	     last_syllable == buffer->cur().syllable() &&
- 	     buffer->cur().indic_category() == OT_Repha)
-         buffer->next_glyph ();
- 
-       buffer->output_info (ginfo);
-@@ -1227,24 +1231,24 @@ final_reordering_syllable (const hb_ot_s
- 	    base--;
- 
- 	  hb_glyph_info_t tmp = info[old_pos];
- 	  memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
- 	  info[new_pos] = tmp;
- 
- 	  /* Note: this merge_clusters() is intentionally *after* the reordering.
- 	   * Indic matra reordering is special and tricky... */
--	  buffer->merge_clusters (new_pos, MIN (end, base + 1));
-+	  buffer->merge_clusters (new_pos, hb_min (end, base + 1));
- 
- 	  new_pos--;
- 	}
-     } else {
-       for (unsigned int i = start; i < base; i++)
- 	if (info[i].indic_position () == POS_PRE_M) {
--	  buffer->merge_clusters (i, MIN (end, base + 1));
-+	  buffer->merge_clusters (i, hb_min (end, base + 1));
- 	  break;
- 	}
-     }
-   }
- 
- 
-   /*   o Reorder reph:
-    *
-@@ -1367,23 +1371,25 @@ final_reordering_syllable (const hb_ot_s
-       /*
-        * If the Reph is to be ending up after a Matra,Halant sequence,
-        * position it before that Halant so it can interact with the Matra.
-        * However, if it's a plain Consonant,Halant we shouldn't do that.
-        * Uniscribe doesn't do this.
-        * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
-        */
-       if (!indic_plan->uniscribe_bug_compatible &&
--	  unlikely (is_halant (info[new_reph_pos]))) {
-+	  unlikely (is_halant (info[new_reph_pos])))
-+      {
- 	for (unsigned int i = base + 1; i < new_reph_pos; i++)
- 	  if (info[i].indic_category() == OT_M) {
- 	    /* Ok, got it. */
- 	    new_reph_pos--;
- 	  }
-       }
-+
-       goto reph_move;
-     }
- 
-     reph_move:
-     {
-       /* Move */
-       buffer->merge_clusters (start, new_reph_pos + 1);
-       hb_glyph_info_t reph = info[start];
-@@ -1586,21 +1592,20 @@ decompose_indic (const hb_ot_shape_norma
-      * Argh...
-      *
-      * The Uniscribe behavior is now documented in the newly published Sinhala
-      * spec in 2012:
-      *
-      *   https://docs.microsoft.com/en-us/typography/script-development/sinhala#shaping
-      */
- 
-+
-     const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;
--
-     hb_codepoint_t glyph;
--
--    if (hb_options ().uniscribe_bug_compatible ||
-+    if (indic_plan->uniscribe_bug_compatible ||
- 	(c->font->get_nominal_glyph (ab, &glyph) &&
- 	 indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
-     {
-       /* Ok, safe to use Uniscribe-style decomposition. */
-       *a = 0x0DD9u;
-       *b = ab;
-       return true;
-     }
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
-@@ -273,17 +273,17 @@ static inline indic_position_t
- matra_position_indic (hb_codepoint_t u, indic_position_t side)
- {
-   switch ((int) side)
-   {
-     case POS_PRE_C:	return MATRA_POS_LEFT (u);
-     case POS_POST_C:	return MATRA_POS_RIGHT (u);
-     case POS_ABOVE_C:	return MATRA_POS_TOP (u);
-     case POS_BELOW_C:	return MATRA_POS_BOTTOM (u);
--  };
-+  }
-   return side;
- }
- 
- /* XXX
-  * This is a hack for now.  We should move this data into the main Indic table.
-  * Or completely remove it and just check in the tables.
-  */
- static const hb_codepoint_t ra_chars[] = {
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.cc
-@@ -363,17 +363,18 @@ initial_reordering_syllable (const hb_ot
- static inline void
- insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
- 		       hb_font_t *font,
- 		       hb_buffer_t *buffer)
- {
-   if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
-     return;
- 
--  /* Note: This loop is extra overhead, but should not be measurable. */
-+  /* Note: This loop is extra overhead, but should not be measurable.
-+   * TODO Use a buffer scratch flag to remove the loop. */
-   bool has_broken_syllables = false;
-   unsigned int count = buffer->len;
-   hb_glyph_info_t *info = buffer->info;
-   for (unsigned int i = 0; i < count; i++)
-     if ((info[i].syllable() & 0x0F) == broken_cluster)
-     {
-       has_broken_syllables = true;
-       break;
-@@ -402,17 +403,16 @@ insert_dotted_circles (const hb_ot_shape
-     if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
-     {
-       last_syllable = syllable;
- 
-       hb_glyph_info_t ginfo = dottedcircle;
-       ginfo.cluster = buffer->cur().cluster;
-       ginfo.mask = buffer->cur().mask;
-       ginfo.syllable() = buffer->cur().syllable();
--      /* TODO Set glyph_props? */
- 
-       /* Insert dottedcircle after possible Repha. */
-       while (buffer->idx < buffer->len && buffer->successful &&
- 	     last_syllable == buffer->cur().syllable() &&
- 	     buffer->cur().khmer_category() == OT_Repha)
-         buffer->next_glyph ();
- 
-       buffer->output_info (ginfo);
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-khmer.hh
-@@ -100,15 +100,15 @@ set_khmer_properties (hb_glyph_info_t &i
-   if (cat == (khmer_category_t) OT_M)
-     switch ((int) pos)
-     {
-       case POS_PRE_C:	cat = OT_VPre; break;
-       case POS_BELOW_C:	cat = OT_VBlw; break;
-       case POS_ABOVE_C:	cat = OT_VAbv; break;
-       case POS_POST_C:	cat = OT_VPst; break;
-       default: assert (0);
--    };
-+    }
- 
-   info.khmer_category() = cat;
- }
- 
- 
- #endif /* HB_OT_SHAPE_COMPLEX_KHMER_HH */
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
-@@ -33,37 +33,39 @@
- 
- 
- #line 36 "hb-ot-shape-complex-myanmar-machine.hh"
- static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
- 	1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 
- 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 
- 	3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 
- 	5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 
--	3u, 29u, 3u, 30u, 3u, 29u, 1u, 32u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
--	3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 32u, 8u, 8u, 
--	0
-+	3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
-+	3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 1u, 32u, 
-+	1u, 32u, 8u, 8u, 0
- };
- 
- static const char _myanmar_syllable_machine_key_spans[] = {
- 	32, 28, 25, 4, 25, 23, 21, 21, 
- 	27, 27, 27, 27, 16, 27, 27, 27, 
- 	27, 27, 28, 27, 27, 27, 27, 25, 
- 	4, 25, 23, 21, 21, 27, 27, 27, 
--	27, 28, 27, 32, 27, 27, 27, 27, 
--	27, 28, 27, 27, 27, 27, 32, 1
-+	27, 16, 28, 27, 27, 27, 27, 27, 
-+	28, 27, 27, 27, 27, 28, 27, 32, 
-+	32, 1
- };
- 
- static const short _myanmar_syllable_machine_index_offsets[] = {
- 	0, 33, 62, 88, 93, 119, 143, 165, 
- 	187, 215, 243, 271, 299, 316, 344, 372, 
- 	400, 428, 456, 485, 513, 541, 569, 597, 
- 	623, 628, 654, 678, 700, 722, 750, 778, 
--	806, 834, 863, 891, 924, 952, 980, 1008, 
--	1036, 1064, 1093, 1121, 1149, 1177, 1205, 1238
-+	806, 834, 851, 880, 908, 936, 964, 992, 
-+	1020, 1049, 1077, 1105, 1133, 1161, 1190, 1218, 
-+	1251, 1284
- };
- 
- static const char _myanmar_syllable_machine_indicies[] = {
- 	1, 1, 2, 3, 4, 4, 0, 5, 
- 	0, 6, 1, 0, 0, 0, 0, 7, 
- 	0, 8, 9, 0, 10, 11, 12, 13, 
- 	14, 15, 16, 17, 18, 19, 20, 1, 
- 	0, 22, 23, 24, 24, 21, 25, 21, 
-@@ -131,145 +133,155 @@ static const char _myanmar_syllable_mach
- 	43, 21, 21, 28, 21, 21, 21, 32, 
- 	33, 34, 35, 36, 21, 22, 21, 24, 
- 	24, 21, 25, 21, 26, 21, 21, 21, 
- 	21, 21, 21, 21, 43, 21, 21, 28, 
- 	29, 30, 21, 32, 33, 34, 35, 36, 
- 	21, 22, 23, 24, 24, 21, 25, 21, 
- 	26, 21, 21, 21, 21, 21, 21, 21, 
- 	27, 21, 21, 28, 29, 30, 31, 32, 
--	33, 34, 35, 36, 21, 3, 3, 44, 
-+	33, 34, 35, 36, 21, 45, 45, 44, 
- 	5, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 45, 44, 44, 44, 44, 44, 
--	44, 14, 44, 44, 44, 18, 44, 3, 
--	3, 44, 5, 44, 3, 3, 44, 5, 
-+	44, 44, 46, 44, 44, 44, 44, 44, 
-+	44, 14, 44, 44, 44, 18, 44, 45, 
-+	45, 44, 5, 44, 45, 45, 44, 5, 
- 	44, 44, 44, 44, 44, 44, 44, 44, 
- 	44, 44, 44, 44, 44, 44, 44, 44, 
--	14, 44, 44, 44, 18, 44, 46, 44, 
--	3, 3, 44, 5, 44, 14, 44, 44, 
--	44, 44, 44, 44, 44, 47, 44, 44, 
--	44, 44, 44, 44, 14, 44, 3, 3, 
-+	14, 44, 44, 44, 18, 44, 47, 44, 
-+	45, 45, 44, 5, 44, 14, 44, 44, 
-+	44, 44, 44, 44, 44, 48, 44, 44, 
-+	44, 44, 44, 44, 14, 44, 45, 45, 
- 	44, 5, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 47, 44, 44, 44, 44, 
--	44, 44, 14, 44, 3, 3, 44, 5, 
-+	44, 44, 44, 48, 44, 44, 44, 44, 
-+	44, 44, 14, 44, 45, 45, 44, 5, 
- 	44, 44, 44, 44, 44, 44, 44, 44, 
- 	44, 44, 44, 44, 44, 44, 44, 44, 
--	14, 44, 2, 44, 3, 3, 44, 5, 
-+	14, 44, 2, 44, 45, 45, 44, 5, 
- 	44, 6, 44, 44, 44, 44, 44, 44, 
--	44, 48, 44, 44, 48, 44, 44, 44, 
--	14, 49, 44, 44, 18, 44, 2, 44, 
--	3, 3, 44, 5, 44, 6, 44, 44, 
-+	44, 49, 44, 44, 49, 44, 44, 44, 
-+	14, 50, 44, 44, 18, 44, 2, 44, 
-+	45, 45, 44, 5, 44, 6, 44, 44, 
- 	44, 44, 44, 44, 44, 44, 44, 44, 
- 	44, 44, 44, 44, 14, 44, 44, 44, 
--	18, 44, 2, 44, 3, 3, 44, 5, 
-+	18, 44, 2, 44, 45, 45, 44, 5, 
- 	44, 6, 44, 44, 44, 44, 44, 44, 
--	44, 48, 44, 44, 44, 44, 44, 44, 
--	14, 49, 44, 44, 18, 44, 2, 44, 
--	3, 3, 44, 5, 44, 6, 44, 44, 
-+	44, 49, 44, 44, 44, 44, 44, 44, 
-+	14, 50, 44, 44, 18, 44, 2, 44, 
-+	45, 45, 44, 5, 44, 6, 44, 44, 
-+	44, 44, 44, 44, 44, 44, 44, 44, 
-+	44, 44, 44, 44, 14, 50, 44, 44, 
-+	18, 44, 51, 51, 44, 44, 44, 44, 
- 	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 14, 49, 44, 44, 
--	18, 44, 22, 23, 24, 24, 21, 25, 
--	21, 26, 21, 21, 21, 21, 21, 21, 
--	21, 50, 21, 21, 28, 29, 30, 31, 
--	32, 33, 34, 35, 36, 37, 21, 22, 
--	51, 24, 24, 21, 25, 21, 26, 21, 
--	21, 21, 21, 21, 21, 21, 27, 21, 
--	21, 28, 29, 30, 31, 32, 33, 34, 
--	35, 36, 21, 1, 1, 2, 3, 3, 
--	3, 44, 5, 44, 6, 1, 44, 44, 
--	44, 44, 1, 44, 8, 44, 44, 10, 
--	11, 12, 13, 14, 15, 16, 17, 18, 
--	19, 44, 1, 44, 2, 44, 3, 3, 
-+	44, 51, 44, 2, 3, 45, 45, 44, 
-+	5, 44, 6, 44, 44, 44, 44, 44, 
-+	44, 44, 8, 44, 44, 10, 11, 12, 
-+	13, 14, 15, 16, 17, 18, 19, 44, 
-+	2, 44, 45, 45, 44, 5, 44, 6, 
-+	44, 44, 44, 44, 44, 44, 44, 8, 
-+	44, 44, 10, 11, 12, 13, 14, 15, 
-+	16, 17, 18, 44, 2, 44, 45, 45, 
- 	44, 5, 44, 6, 44, 44, 44, 44, 
--	44, 44, 44, 8, 44, 44, 10, 11, 
--	12, 13, 14, 15, 16, 17, 18, 44, 
--	2, 44, 3, 3, 44, 5, 44, 6, 
--	44, 44, 44, 44, 44, 44, 44, 52, 
-+	44, 44, 44, 52, 44, 44, 44, 44, 
-+	44, 44, 14, 15, 16, 17, 18, 44, 
-+	2, 44, 45, 45, 44, 5, 44, 6, 
-+	44, 44, 44, 44, 44, 44, 44, 44, 
- 	44, 44, 44, 44, 44, 44, 14, 15, 
--	16, 17, 18, 44, 2, 44, 3, 3, 
-+	16, 17, 18, 44, 2, 44, 45, 45, 
-+	44, 5, 44, 6, 44, 44, 44, 44, 
-+	44, 44, 44, 44, 44, 44, 44, 44, 
-+	44, 44, 14, 15, 16, 44, 18, 44, 
-+	2, 44, 45, 45, 44, 5, 44, 6, 
-+	44, 44, 44, 44, 44, 44, 44, 44, 
-+	44, 44, 44, 44, 44, 44, 14, 44, 
-+	16, 44, 18, 44, 2, 44, 45, 45, 
- 	44, 5, 44, 6, 44, 44, 44, 44, 
- 	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 14, 15, 16, 17, 18, 44, 
--	2, 44, 3, 3, 44, 5, 44, 6, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 14, 15, 
--	16, 44, 18, 44, 2, 44, 3, 3, 
--	44, 5, 44, 6, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 14, 44, 16, 44, 18, 44, 
--	2, 44, 3, 3, 44, 5, 44, 6, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 14, 15, 
--	16, 17, 18, 52, 44, 2, 44, 3, 
--	3, 44, 5, 44, 6, 44, 44, 44, 
-+	44, 44, 14, 15, 16, 17, 18, 52, 
-+	44, 2, 44, 45, 45, 44, 5, 44, 
-+	6, 44, 44, 44, 44, 44, 44, 44, 
-+	52, 44, 44, 10, 44, 12, 44, 14, 
-+	15, 16, 17, 18, 44, 2, 44, 45, 
-+	45, 44, 5, 44, 6, 44, 44, 44, 
- 	44, 44, 44, 44, 52, 44, 44, 10, 
--	44, 12, 44, 14, 15, 16, 17, 18, 
--	44, 2, 44, 3, 3, 44, 5, 44, 
-+	44, 44, 44, 14, 15, 16, 17, 18, 
-+	44, 2, 44, 45, 45, 44, 5, 44, 
- 	6, 44, 44, 44, 44, 44, 44, 44, 
--	52, 44, 44, 10, 44, 44, 44, 14, 
--	15, 16, 17, 18, 44, 2, 44, 3, 
--	3, 44, 5, 44, 6, 44, 44, 44, 
--	44, 44, 44, 44, 52, 44, 44, 10, 
--	11, 12, 44, 14, 15, 16, 17, 18, 
--	44, 2, 3, 3, 3, 44, 5, 44, 
--	6, 44, 44, 44, 44, 44, 44, 44, 
--	8, 44, 44, 10, 11, 12, 13, 14, 
--	15, 16, 17, 18, 44, 1, 1, 53, 
--	53, 53, 53, 53, 53, 53, 53, 1, 
--	53, 53, 53, 53, 1, 53, 53, 53, 
--	53, 53, 53, 53, 53, 53, 53, 53, 
--	53, 53, 53, 53, 1, 53, 54, 53, 
-+	52, 44, 44, 10, 11, 12, 44, 14, 
-+	15, 16, 17, 18, 44, 2, 3, 45, 
-+	45, 44, 5, 44, 6, 44, 44, 44, 
-+	44, 44, 44, 44, 8, 44, 44, 10, 
-+	11, 12, 13, 14, 15, 16, 17, 18, 
-+	44, 22, 23, 24, 24, 21, 25, 21, 
-+	26, 21, 21, 21, 21, 21, 21, 21, 
-+	53, 21, 21, 28, 29, 30, 31, 32, 
-+	33, 34, 35, 36, 37, 21, 22, 54, 
-+	24, 24, 21, 25, 21, 26, 21, 21, 
-+	21, 21, 21, 21, 21, 27, 21, 21, 
-+	28, 29, 30, 31, 32, 33, 34, 35, 
-+	36, 21, 1, 1, 2, 3, 45, 45, 
-+	44, 5, 44, 6, 1, 44, 44, 44, 
-+	44, 1, 44, 8, 44, 44, 10, 11, 
-+	12, 13, 14, 15, 16, 17, 18, 19, 
-+	44, 1, 44, 1, 1, 55, 55, 55, 
-+	55, 55, 55, 55, 55, 1, 55, 55, 
-+	55, 55, 1, 55, 55, 55, 55, 55, 
-+	55, 55, 55, 55, 55, 55, 55, 55, 
-+	55, 55, 1, 55, 56, 55, 0
-+};
-+
-+static const char _myanmar_syllable_machine_trans_targs[] = {
-+	0, 1, 23, 33, 0, 24, 30, 45, 
-+	35, 48, 36, 41, 42, 43, 26, 38, 
-+	39, 40, 29, 44, 49, 0, 2, 12, 
-+	0, 3, 9, 13, 14, 19, 20, 21, 
-+	5, 16, 17, 18, 8, 22, 4, 6, 
-+	7, 10, 11, 15, 0, 0, 25, 27, 
-+	28, 31, 32, 34, 37, 46, 47, 0, 
- 	0
- };
- 
--static const char _myanmar_syllable_machine_trans_targs[] = {
--	0, 1, 23, 0, 0, 24, 30, 33, 
--	36, 46, 37, 42, 43, 44, 26, 39, 
--	40, 41, 29, 45, 47, 0, 2, 12, 
--	0, 3, 9, 13, 14, 19, 20, 21, 
--	5, 16, 17, 18, 8, 22, 4, 6, 
--	7, 10, 11, 15, 0, 25, 27, 28, 
--	31, 32, 34, 35, 38, 0, 0
--};
--
- static const char _myanmar_syllable_machine_trans_actions[] = {
--	3, 0, 0, 4, 5, 0, 0, 0, 
-+	3, 0, 0, 0, 4, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 6, 0, 0, 
--	7, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 5, 0, 0, 
-+	6, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 8, 0, 0, 0, 
--	0, 0, 0, 0, 0, 9, 10
-+	0, 0, 0, 0, 7, 8, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 9, 
-+	10
- };
- 
- static const char _myanmar_syllable_machine_to_state_actions[] = {
- 	1, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0
- };
- 
- static const char _myanmar_syllable_machine_from_state_actions[] = {
- 	2, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 0
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0
- };
- 
- static const short _myanmar_syllable_machine_eof_trans[] = {
- 	0, 22, 22, 22, 22, 22, 22, 22, 
- 	22, 22, 22, 22, 22, 22, 22, 22, 
- 	22, 22, 22, 22, 22, 22, 22, 45, 
- 	45, 45, 45, 45, 45, 45, 45, 45, 
--	45, 22, 22, 45, 45, 45, 45, 45, 
--	45, 45, 45, 45, 45, 45, 54, 54
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 22, 22, 45, 
-+	56, 56
- };
- 
- static const int myanmar_syllable_machine_start = 0;
- static const int myanmar_syllable_machine_first_final = 0;
- static const int myanmar_syllable_machine_error = -1;
- 
- static const int myanmar_syllable_machine_en_main = 0;
- 
-@@ -292,47 +304,47 @@ static const int myanmar_syllable_machin
- 
- static void
- find_syllables (hb_buffer_t *buffer)
- {
-   unsigned int p, pe, eof, ts, te, act HB_UNUSED;
-   int cs;
-   hb_glyph_info_t *info = buffer->info;
-   
--#line 301 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 313 "hb-ot-shape-complex-myanmar-machine.hh"
- 	{
- 	cs = myanmar_syllable_machine_start;
- 	ts = 0;
- 	te = 0;
- 	act = 0;
- 	}
- 
- #line 114 "hb-ot-shape-complex-myanmar-machine.rl"
- 
- 
-   p = 0;
-   pe = eof = buffer->len;
- 
-   unsigned int syllable_serial = 1;
-   
--#line 317 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 329 "hb-ot-shape-complex-myanmar-machine.hh"
- 	{
- 	int _slen;
- 	int _trans;
- 	const unsigned char *_keys;
- 	const char *_inds;
- 	if ( p == pe )
- 		goto _test_eof;
- _resume:
- 	switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
- 	case 2:
- #line 1 "NONE"
- 	{ts = p;}
- 	break;
--#line 331 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 343 "hb-ot-shape-complex-myanmar-machine.hh"
- 	}
- 
- 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
- 	_inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
- 
- 	_slen = _myanmar_syllable_machine_key_spans[cs];
- 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
- 		( info[p].myanmar_category()) <= _keys[1] ?
-@@ -340,58 +352,58 @@ find_syllables (hb_buffer_t *buffer)
- 
- _eof_trans:
- 	cs = _myanmar_syllable_machine_trans_targs[_trans];
- 
- 	if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
- 		goto _again;
- 
- 	switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
--	case 7:
-+	case 6:
- #line 86 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p+1;{ found_syllable (consonant_syllable); }}
- 	break;
--	case 5:
-+	case 4:
- #line 87 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
- 	break;
- 	case 10:
- #line 88 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p+1;{ found_syllable (punctuation_cluster); }}
- 	break;
--	case 4:
-+	case 8:
- #line 89 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p+1;{ found_syllable (broken_cluster); }}
- 	break;
- 	case 3:
- #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p+1;{ found_syllable (non_myanmar_cluster); }}
- 	break;
--	case 6:
-+	case 5:
- #line 86 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p;p--;{ found_syllable (consonant_syllable); }}
- 	break;
--	case 8:
-+	case 7:
- #line 89 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p;p--;{ found_syllable (broken_cluster); }}
- 	break;
- 	case 9:
- #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
- 	break;
--#line 381 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 393 "hb-ot-shape-complex-myanmar-machine.hh"
- 	}
- 
- _again:
- 	switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
- 	case 1:
- #line 1 "NONE"
- 	{ts = 0;}
- 	break;
--#line 390 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 402 "hb-ot-shape-complex-myanmar-machine.hh"
- 	}
- 
- 	if ( ++p != pe )
- 		goto _resume;
- 	_test_eof: {}
- 	if ( p == eof )
- 	{
- 	if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
-@@ -70,19 +70,19 @@ k = (Ra As H);			# Kinzi
- c = C|Ra;			# is_consonant
- 
- medial_group = MY? MR? MW? MH? As?;
- main_vowel_group = (VPre.VS?)* VAbv* VBlw* A* (DB As?)?;
- post_vowel_group = VPst MH? As* VAbv* A* (DB As?)?;
- pwo_tone_group = PT A* DB? As?;
- 
- complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_tone_group* V* j?;
--syllable_tail = (H | complex_syllable_tail);
-+syllable_tail = (H (c|IV).VS?)* (H | complex_syllable_tail);
- 
--consonant_syllable =	(k|CS)? (c|IV|D|GB).VS? (H (c|IV).VS?)* syllable_tail;
-+consonant_syllable =	(k|CS)? (c|IV|D|GB).VS? syllable_tail;
- punctuation_cluster = 	P V;
- broken_cluster =	k? VS? syllable_tail;
- other =			any;
- 
- main := |*
- 	consonant_syllable	=> { found_syllable (consonant_syllable); };
- 	j			=> { found_syllable (non_myanmar_cluster); };
- 	punctuation_cluster	=> { found_syllable (punctuation_cluster); };
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
-@@ -296,17 +296,18 @@ initial_reordering_syllable (const hb_ot
- static inline void
- insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
- 		       hb_font_t *font,
- 		       hb_buffer_t *buffer)
- {
-   if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
-     return;
- 
--  /* Note: This loop is extra overhead, but should not be measurable. */
-+  /* Note: This loop is extra overhead, but should not be measurable.
-+   * TODO Use a buffer scratch flag to remove the loop. */
-   bool has_broken_syllables = false;
-   unsigned int count = buffer->len;
-   hb_glyph_info_t *info = buffer->info;
-   for (unsigned int i = 0; i < count; i++)
-     if ((info[i].syllable() & 0x0F) == broken_cluster)
-     {
-       has_broken_syllables = true;
-       break;
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
-@@ -141,17 +141,17 @@ set_myanmar_properties (hb_glyph_info_t 
-       cat = OT_SM;
-       break;
- 
-     case 0x104Au: case 0x104Bu:
-       cat = OT_P;
-       break;
- 
-     case 0xAA74u: case 0xAA75u: case 0xAA76u:
--      /* https://github.com/roozbehp/unicode-data/issues/3 */
-+      /* https://github.com/harfbuzz/harfbuzz/issues/218 */
-       cat = OT_C;
-       break;
-   }
- 
-   if (cat == OT_M)
-   {
-     switch ((int) pos)
-     {
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-thai.cc
-@@ -213,16 +213,20 @@ static const struct thai_below_state_mac
- };
- 
- 
- static void
- do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED,
- 		     hb_buffer_t              *buffer,
- 		     hb_font_t                *font)
- {
-+#ifdef HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
-+  return;
-+#endif
-+
-   thai_above_state_t above_state = thai_above_start_state[NOT_CONSONANT];
-   thai_below_state_t below_state = thai_below_start_state[NOT_CONSONANT];
-   unsigned int base = 0;
- 
-   hb_glyph_info_t *info = buffer->info;
-   unsigned int count = buffer->len;
-   for (unsigned int i = 0; i < count; i++)
-   {
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
-@@ -31,336 +31,354 @@
- #ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
- #define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
- 
- #include "hb.hh"
- 
- 
- #line 38 "hb-ot-shape-complex-use-machine.hh"
- static const unsigned char _use_syllable_machine_trans_keys[] = {
--	12u, 44u, 1u, 15u, 1u, 1u, 12u, 44u, 0u, 44u, 21u, 21u, 8u, 44u, 8u, 44u,
--	1u, 15u, 1u, 1u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u,
--	8u, 39u, 8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
--	8u, 44u, 8u, 44u, 8u, 44u, 1u, 39u, 8u, 44u, 13u, 21u, 4u, 4u, 13u, 13u,
--	8u, 44u, 8u, 44u, 8u, 44u, 8u, 39u, 8u, 26u, 8u, 26u, 8u, 26u, 8u, 39u,
--	8u, 39u, 8u, 39u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u, 8u, 44u,
--	8u, 44u, 8u, 44u, 1u, 39u, 1u, 15u, 12u, 44u, 1u, 44u, 8u, 44u, 21u, 42u,
--	41u, 42u, 42u, 42u, 1u, 5u, 0
-+	12u, 48u, 1u, 15u, 1u, 1u, 12u, 48u, 1u, 1u, 0u, 48u, 21u, 21u, 11u, 48u, 
-+	11u, 48u, 1u, 15u, 1u, 1u, 11u, 48u, 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 
-+	26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 
-+	23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 11u, 48u, 
-+	1u, 48u, 11u, 48u, 13u, 21u, 4u, 4u, 13u, 13u, 11u, 48u, 11u, 48u, 41u, 42u, 
-+	42u, 42u, 11u, 48u, 11u, 48u, 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 
-+	45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 24u, 48u, 23u, 48u, 23u, 48u, 
-+	23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, 11u, 48u, 1u, 48u, 1u, 15u, 
-+	4u, 4u, 13u, 21u, 13u, 13u, 12u, 48u, 1u, 48u, 11u, 48u, 41u, 42u, 42u, 42u, 
-+	21u, 42u, 1u, 5u, 0
- };
- 
- static const char _use_syllable_machine_key_spans[] = {
--	33, 15, 1, 33, 45, 1, 37, 37,
--	15, 1, 37, 37, 32, 19, 19, 19,
--	32, 32, 32, 37, 37, 37, 37, 37,
--	37, 37, 37, 39, 37, 9, 1, 1,
--	37, 37, 37, 32, 19, 19, 19, 32,
--	32, 32, 37, 37, 37, 37, 37, 37,
--	37, 37, 39, 15, 33, 44, 37, 22,
--	2, 1, 5
-+	37, 15, 1, 37, 1, 49, 1, 38, 
-+	38, 15, 1, 38, 27, 26, 24, 23, 
-+	22, 2, 1, 25, 25, 25, 1, 25, 
-+	26, 26, 26, 27, 27, 27, 27, 38, 
-+	48, 38, 9, 1, 1, 38, 38, 2, 
-+	1, 38, 38, 27, 26, 24, 23, 22, 
-+	2, 1, 25, 25, 25, 25, 26, 26, 
-+	26, 27, 27, 27, 27, 38, 48, 15, 
-+	1, 9, 1, 37, 48, 38, 2, 1, 
-+	22, 5
- };
- 
- static const short _use_syllable_machine_index_offsets[] = {
--	0, 34, 50, 52, 86, 132, 134, 172,
--	210, 226, 228, 266, 304, 337, 357, 377,
--	397, 430, 463, 496, 534, 572, 610, 648,
--	686, 724, 762, 800, 840, 878, 888, 890,
--	892, 930, 968, 1006, 1039, 1059, 1079, 1099,
--	1132, 1165, 1198, 1236, 1274, 1312, 1350, 1388,
--	1426, 1464, 1502, 1542, 1558, 1592, 1637, 1675,
--	1698, 1701, 1703
-+	0, 38, 54, 56, 94, 96, 146, 148, 
-+	187, 226, 242, 244, 283, 311, 338, 363, 
-+	387, 410, 413, 415, 441, 467, 493, 495, 
-+	521, 548, 575, 602, 630, 658, 686, 714, 
-+	753, 802, 841, 851, 853, 855, 894, 933, 
-+	936, 938, 977, 1016, 1044, 1071, 1096, 1120, 
-+	1143, 1146, 1148, 1174, 1200, 1226, 1252, 1279, 
-+	1306, 1333, 1361, 1389, 1417, 1445, 1484, 1533, 
-+	1549, 1551, 1561, 1563, 1601, 1650, 1689, 1692, 
-+	1694, 1717
- };
- 
- static const char _use_syllable_machine_indicies[] = {
--	1, 0, 0, 0, 0, 0, 0, 0,
--	0, 0, 0, 0, 0, 0, 0, 0,
--	0, 0, 0, 0, 0, 0, 0, 0,
--	0, 0, 0, 0, 0, 0, 0, 0,
--	1, 0, 3, 2, 2, 2, 2, 2, 
-+	1, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	1, 0, 0, 0, 1, 0, 3, 2, 
- 	2, 2, 2, 2, 2, 2, 2, 2, 
--	4, 2, 3, 2, 6, 5, 5, 5,
--	5, 5, 5, 5, 5, 5, 5, 5,
--	5, 5, 5, 5, 5, 5, 5, 5,
--	5, 5, 5, 5, 5, 5, 5, 5,
--	5, 5, 5, 5, 6, 5, 7, 8,
--	9, 7, 10, 8, 9, 9, 11, 9, 
--	9, 3, 12, 9, 9, 13, 7, 7, 
--	14, 15, 9, 9, 16, 17, 18, 19, 
--	20, 21, 22, 16, 23, 24, 25, 26, 
--	27, 28, 9, 29, 30, 31, 9, 9, 
--	9, 32, 33, 9, 35, 34, 37, 36,
--	36, 38, 1, 36, 36, 39, 36, 36,
--	36, 36, 36, 40, 41, 42, 43, 44,
--	45, 46, 47, 41, 48, 40, 49, 50,
--	51, 52, 36, 53, 54, 55, 36, 36,
--	36, 36, 56, 36, 37, 36, 36, 38,
--	1, 36, 36, 39, 36, 36, 36, 36,
--	36, 57, 41, 42, 43, 44, 45, 46,
--	47, 41, 48, 49, 49, 50, 51, 52,
--	36, 53, 54, 55, 36, 36, 36, 36,
--	56, 36, 38, 58, 58, 58, 58, 58,
--	58, 58, 58, 58, 58, 58, 58, 58,
--	59, 58, 38, 58, 37, 36, 36, 38,
--	1, 36, 36, 39, 36, 36, 36, 36,
--	36, 36, 41, 42, 43, 44, 45, 46,
--	47, 41, 48, 49, 49, 50, 51, 52,
--	36, 53, 54, 55, 36, 36, 36, 36,
--	56, 36, 37, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	41, 42, 43, 44, 45, 36, 36, 36,
--	36, 36, 36, 50, 51, 52, 36, 53,
--	54, 55, 36, 36, 36, 36, 42, 36,
--	37, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 42,
--	43, 44, 45, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 53, 54, 55,
--	36, 37, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 43, 44, 45, 36, 37, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 44, 45,
--	36, 37, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 45, 36, 37, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 43, 44, 45,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 53, 54, 55, 36, 37, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 43, 44,
--	45, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 54, 55, 36, 37,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 43,
--	44, 45, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 55, 36,
--	37, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 42,
--	43, 44, 45, 36, 36, 36, 36, 36,
--	36, 50, 51, 52, 36, 53, 54, 55,
--	36, 36, 36, 36, 42, 36, 37, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 42, 43, 44,
--	45, 36, 36, 36, 36, 36, 36, 36,
--	51, 52, 36, 53, 54, 55, 36, 36,
--	36, 36, 42, 36, 37, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 42, 43, 44, 45, 36,
--	36, 36, 36, 36, 36, 36, 36, 52,
--	36, 53, 54, 55, 36, 36, 36, 36,
--	42, 36, 37, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	41, 42, 43, 44, 45, 36, 47, 41,
--	36, 36, 36, 50, 51, 52, 36, 53,
--	54, 55, 36, 36, 36, 36, 42, 36,
--	37, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 41, 42,
--	43, 44, 45, 36, 60, 41, 36, 36,
--	36, 50, 51, 52, 36, 53, 54, 55,
--	36, 36, 36, 36, 42, 36, 37, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 36, 36, 41, 42, 43, 44,
--	45, 36, 36, 41, 36, 36, 36, 50,
--	51, 52, 36, 53, 54, 55, 36, 36,
--	36, 36, 42, 36, 37, 36, 36, 36,
--	36, 36, 36, 36, 36, 36, 36, 36,
--	36, 36, 41, 42, 43, 44, 45, 46,
--	47, 41, 36, 36, 36, 50, 51, 52,
--	36, 53, 54, 55, 36, 36, 36, 36,
--	42, 36, 37, 36, 36, 38, 1, 36,
--	36, 39, 36, 36, 36, 36, 36, 36,
--	41, 42, 43, 44, 45, 46, 47, 41,
--	48, 36, 49, 50, 51, 52, 36, 53,
--	54, 55, 36, 36, 36, 36, 56, 36,
--	38, 58, 58, 58, 58, 58, 58, 37,
--	58, 58, 58, 58, 58, 58, 59, 58,
--	58, 58, 58, 58, 58, 58, 42, 43,
--	44, 45, 58, 58, 58, 58, 58, 58,
--	58, 58, 58, 58, 53, 54, 55, 58,
--	37, 36, 36, 38, 1, 36, 36, 39,
--	36, 36, 36, 36, 36, 36, 41, 42,
--	43, 44, 45, 46, 47, 41, 48, 40,
--	49, 50, 51, 52, 36, 53, 54, 55,
--	36, 36, 36, 36, 56, 36, 62, 61,
--	61, 61, 61, 61, 61, 61, 63, 61,
--	10, 64, 62, 61, 11, 65, 65, 3,
--	6, 65, 65, 66, 65, 65, 65, 65,
--	65, 67, 16, 17, 18, 19, 20, 21,
--	22, 16, 23, 25, 25, 26, 27, 28,
--	65, 29, 30, 31, 65, 65, 65, 65,
--	33, 65, 11, 65, 65, 3, 6, 65,
--	65, 66, 65, 65, 65, 65, 65, 65,
--	16, 17, 18, 19, 20, 21, 22, 16, 
--	23, 25, 25, 26, 27, 28, 65, 29,
--	30, 31, 65, 65, 65, 65, 33, 65,
--	11, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 16, 17,
--	18, 19, 20, 65, 65, 65, 65, 65,
--	65, 26, 27, 28, 65, 29, 30, 31,
--	65, 65, 65, 65, 17, 65, 11, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 17, 18, 19,
--	20, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 29, 30, 31, 65, 11,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 18,
--	19, 20, 65, 11, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 19, 20, 65, 11,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 20, 65, 11, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 18, 19, 20, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	29, 30, 31, 65, 11, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 18, 19, 20, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 30, 31, 65, 11, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 18, 19, 20,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 31, 65, 11, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 17, 18, 19,
--	20, 65, 65, 65, 65, 65, 65, 26,
--	27, 28, 65, 29, 30, 31, 65, 65,
--	65, 65, 17, 65, 11, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 17, 18, 19, 20, 65,
--	65, 65, 65, 65, 65, 65, 27, 28,
--	65, 29, 30, 31, 65, 65, 65, 65,
--	17, 65, 11, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 17, 18, 19, 20, 65, 65, 65,
--	65, 65, 65, 65, 65, 28, 65, 29,
--	30, 31, 65, 65, 65, 65, 17, 65,
--	11, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 16, 17,
--	18, 19, 20, 65, 22, 16, 65, 65,
--	65, 26, 27, 28, 65, 29, 30, 31,
--	65, 65, 65, 65, 17, 65, 11, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 16, 17, 18, 19,
--	20, 65, 68, 16, 65, 65, 65, 26,
--	27, 28, 65, 29, 30, 31, 65, 65,
--	65, 65, 17, 65, 11, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 16, 17, 18, 19, 20, 65,
--	65, 16, 65, 65, 65, 26, 27, 28,
--	65, 29, 30, 31, 65, 65, 65, 65,
--	17, 65, 11, 65, 65, 65, 65, 65,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	16, 17, 18, 19, 20, 21, 22, 16,
--	65, 65, 65, 26, 27, 28, 65, 29,
--	30, 31, 65, 65, 65, 65, 17, 65,
--	11, 65, 65, 3, 6, 65, 65, 66,
--	65, 65, 65, 65, 65, 65, 16, 17,
--	18, 19, 20, 21, 22, 16, 23, 65,
--	25, 26, 27, 28, 65, 29, 30, 31,
--	65, 65, 65, 65, 33, 65, 3, 65,
--	65, 65, 65, 65, 65, 11, 65, 65,
--	65, 65, 65, 65, 4, 65, 65, 65,
--	65, 65, 65, 65, 17, 18, 19, 20,
--	65, 65, 65, 65, 65, 65, 65, 65,
--	65, 65, 29, 30, 31, 65, 3, 69,
--	69, 69, 69, 69, 69, 69, 69, 69,
--	69, 69, 69, 69, 4, 69, 6, 69,
--	69, 69, 69, 69, 69, 69, 69, 69,
--	69, 69, 69, 69, 69, 69, 69, 69,
--	69, 69, 69, 69, 69, 69, 69, 69,
--	69, 69, 69, 69, 69, 69, 6, 69,
--	8, 65, 65, 65, 8, 65, 65, 11,
--	65, 65, 3, 6, 65, 65, 66, 65,
--	65, 65, 65, 65, 65, 16, 17, 18,
--	19, 20, 21, 22, 16, 23, 24, 25, 
--	26, 27, 28, 65, 29, 30, 31, 65,
--	65, 65, 65, 33, 65, 11, 65, 65,
--	3, 6, 65, 65, 66, 65, 65, 65,
--	65, 65, 65, 16, 17, 18, 19, 20,
--	21, 22, 16, 23, 24, 25, 26, 27,
--	28, 65, 29, 30, 31, 65, 65, 65,
--	65, 33, 65, 71, 70, 70, 70, 70,
--	70, 70, 70, 70, 70, 70, 70, 70,
--	70, 70, 70, 70, 70, 70, 70, 71,
--	72, 70, 71, 72, 70, 72, 70, 8,
--	69, 69, 69, 8, 69, 0
-+	2, 2, 2, 2, 4, 2, 3, 2, 
-+	6, 5, 5, 5, 5, 5, 5, 5, 
-+	5, 5, 5, 5, 5, 5, 5, 5, 
-+	5, 5, 5, 5, 5, 5, 5, 5, 
-+	5, 5, 5, 5, 5, 5, 5, 5, 
-+	6, 5, 5, 5, 6, 5, 7, 5, 
-+	8, 9, 10, 8, 11, 12, 10, 10, 
-+	10, 10, 10, 3, 13, 14, 10, 15, 
-+	8, 8, 16, 17, 10, 10, 18, 19, 
-+	20, 21, 22, 23, 24, 18, 25, 26, 
-+	27, 28, 29, 30, 10, 31, 32, 33, 
-+	10, 34, 35, 36, 37, 38, 39, 40, 
-+	13, 10, 42, 41, 44, 1, 43, 43, 
-+	45, 43, 43, 43, 43, 43, 46, 47, 
-+	48, 49, 50, 51, 52, 53, 47, 54, 
-+	46, 55, 56, 57, 58, 43, 59, 60, 
-+	61, 43, 43, 43, 43, 62, 63, 64, 
-+	65, 1, 43, 44, 1, 43, 43, 45, 
-+	43, 43, 43, 43, 43, 66, 47, 48, 
-+	49, 50, 51, 52, 53, 47, 54, 55, 
-+	55, 56, 57, 58, 43, 59, 60, 61, 
-+	43, 43, 43, 43, 62, 63, 64, 65, 
-+	1, 43, 44, 67, 67, 67, 67, 67, 
-+	67, 67, 67, 67, 67, 67, 67, 67, 
-+	68, 67, 44, 67, 44, 1, 43, 43, 
-+	45, 43, 43, 43, 43, 43, 43, 47, 
-+	48, 49, 50, 51, 52, 53, 47, 54, 
-+	55, 55, 56, 57, 58, 43, 59, 60, 
-+	61, 43, 43, 43, 43, 62, 63, 64, 
-+	65, 1, 43, 47, 48, 49, 50, 51, 
-+	43, 43, 43, 43, 43, 43, 56, 57, 
-+	58, 43, 59, 60, 61, 43, 43, 43, 
-+	43, 48, 63, 64, 65, 69, 43, 48, 
-+	49, 50, 51, 43, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 59, 60, 61, 
-+	43, 43, 43, 43, 43, 63, 64, 65, 
-+	69, 43, 49, 50, 51, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 43, 63, 
-+	64, 65, 43, 50, 51, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 43, 63, 
-+	64, 65, 43, 51, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 63, 64, 
-+	65, 43, 63, 64, 43, 64, 43, 49, 
-+	50, 51, 43, 43, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 59, 60, 61, 43, 
-+	43, 43, 43, 43, 63, 64, 65, 69, 
-+	43, 49, 50, 51, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 43, 60, 
-+	61, 43, 43, 43, 43, 43, 63, 64, 
-+	65, 69, 43, 49, 50, 51, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 43, 43, 
-+	43, 43, 61, 43, 43, 43, 43, 43, 
-+	63, 64, 65, 69, 43, 71, 70, 49, 
-+	50, 51, 43, 43, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 43, 43, 43, 43, 
-+	43, 43, 43, 43, 63, 64, 65, 69, 
-+	43, 48, 49, 50, 51, 43, 43, 43, 
-+	43, 43, 43, 56, 57, 58, 43, 59, 
-+	60, 61, 43, 43, 43, 43, 48, 63, 
-+	64, 65, 69, 43, 48, 49, 50, 51, 
-+	43, 43, 43, 43, 43, 43, 43, 57, 
-+	58, 43, 59, 60, 61, 43, 43, 43, 
-+	43, 48, 63, 64, 65, 69, 43, 48, 
-+	49, 50, 51, 43, 43, 43, 43, 43, 
-+	43, 43, 43, 58, 43, 59, 60, 61, 
-+	43, 43, 43, 43, 48, 63, 64, 65, 
-+	69, 43, 47, 48, 49, 50, 51, 43, 
-+	53, 47, 43, 43, 43, 56, 57, 58, 
-+	43, 59, 60, 61, 43, 43, 43, 43, 
-+	48, 63, 64, 65, 69, 43, 47, 48, 
-+	49, 50, 51, 43, 72, 47, 43, 43, 
-+	43, 56, 57, 58, 43, 59, 60, 61, 
-+	43, 43, 43, 43, 48, 63, 64, 65, 
-+	69, 43, 47, 48, 49, 50, 51, 43, 
-+	43, 47, 43, 43, 43, 56, 57, 58, 
-+	43, 59, 60, 61, 43, 43, 43, 43, 
-+	48, 63, 64, 65, 69, 43, 47, 48, 
-+	49, 50, 51, 52, 53, 47, 43, 43, 
-+	43, 56, 57, 58, 43, 59, 60, 61, 
-+	43, 43, 43, 43, 48, 63, 64, 65, 
-+	69, 43, 44, 1, 43, 43, 45, 43, 
-+	43, 43, 43, 43, 43, 47, 48, 49, 
-+	50, 51, 52, 53, 47, 54, 43, 55, 
-+	56, 57, 58, 43, 59, 60, 61, 43, 
-+	43, 43, 43, 62, 63, 64, 65, 1, 
-+	43, 44, 67, 67, 67, 67, 67, 67, 
-+	67, 67, 67, 67, 67, 67, 67, 68, 
-+	67, 67, 67, 67, 67, 67, 67, 48, 
-+	49, 50, 51, 67, 67, 67, 67, 67, 
-+	67, 67, 67, 67, 67, 59, 60, 61, 
-+	67, 67, 67, 67, 67, 63, 64, 65, 
-+	69, 67, 44, 1, 43, 43, 45, 43, 
-+	43, 43, 43, 43, 43, 47, 48, 49, 
-+	50, 51, 52, 53, 47, 54, 46, 55, 
-+	56, 57, 58, 43, 59, 60, 61, 43, 
-+	43, 43, 43, 62, 63, 64, 65, 1, 
-+	43, 74, 73, 73, 73, 73, 73, 73, 
-+	73, 75, 73, 11, 76, 74, 73, 44, 
-+	1, 43, 43, 45, 43, 43, 43, 43, 
-+	43, 77, 47, 48, 49, 50, 51, 52, 
-+	53, 47, 54, 46, 55, 56, 57, 58, 
-+	43, 59, 60, 61, 43, 78, 79, 43, 
-+	62, 63, 64, 65, 1, 43, 44, 1, 
-+	43, 43, 45, 43, 43, 43, 43, 43, 
-+	43, 47, 48, 49, 50, 51, 52, 53, 
-+	47, 54, 46, 55, 56, 57, 58, 43, 
-+	59, 60, 61, 43, 78, 79, 43, 62, 
-+	63, 64, 65, 1, 43, 78, 79, 80, 
-+	79, 80, 3, 6, 81, 81, 82, 81, 
-+	81, 81, 81, 81, 83, 18, 19, 20, 
-+	21, 22, 23, 24, 18, 25, 27, 27, 
-+	28, 29, 30, 81, 31, 32, 33, 81, 
-+	81, 81, 81, 37, 38, 39, 40, 6, 
-+	81, 3, 6, 81, 81, 82, 81, 81, 
-+	81, 81, 81, 81, 18, 19, 20, 21, 
-+	22, 23, 24, 18, 25, 27, 27, 28, 
-+	29, 30, 81, 31, 32, 33, 81, 81, 
-+	81, 81, 37, 38, 39, 40, 6, 81, 
-+	18, 19, 20, 21, 22, 81, 81, 81, 
-+	81, 81, 81, 28, 29, 30, 81, 31, 
-+	32, 33, 81, 81, 81, 81, 19, 38, 
-+	39, 40, 84, 81, 19, 20, 21, 22, 
-+	81, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 31, 32, 33, 81, 81, 81, 
-+	81, 81, 38, 39, 40, 84, 81, 20, 
-+	21, 22, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 81, 38, 39, 40, 81, 
-+	21, 22, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 81, 38, 39, 40, 81, 
-+	22, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 38, 39, 40, 81, 38, 
-+	39, 81, 39, 81, 20, 21, 22, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 31, 32, 33, 81, 81, 81, 81, 
-+	81, 38, 39, 40, 84, 81, 20, 21, 
-+	22, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 81, 32, 33, 81, 81, 
-+	81, 81, 81, 38, 39, 40, 84, 81, 
-+	20, 21, 22, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 33, 
-+	81, 81, 81, 81, 81, 38, 39, 40, 
-+	84, 81, 20, 21, 22, 81, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 38, 
-+	39, 40, 84, 81, 19, 20, 21, 22, 
-+	81, 81, 81, 81, 81, 81, 28, 29, 
-+	30, 81, 31, 32, 33, 81, 81, 81, 
-+	81, 19, 38, 39, 40, 84, 81, 19, 
-+	20, 21, 22, 81, 81, 81, 81, 81, 
-+	81, 81, 29, 30, 81, 31, 32, 33, 
-+	81, 81, 81, 81, 19, 38, 39, 40, 
-+	84, 81, 19, 20, 21, 22, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 30, 81, 
-+	31, 32, 33, 81, 81, 81, 81, 19, 
-+	38, 39, 40, 84, 81, 18, 19, 20, 
-+	21, 22, 81, 24, 18, 81, 81, 81, 
-+	28, 29, 30, 81, 31, 32, 33, 81, 
-+	81, 81, 81, 19, 38, 39, 40, 84, 
-+	81, 18, 19, 20, 21, 22, 81, 85, 
-+	18, 81, 81, 81, 28, 29, 30, 81, 
-+	31, 32, 33, 81, 81, 81, 81, 19, 
-+	38, 39, 40, 84, 81, 18, 19, 20, 
-+	21, 22, 81, 81, 18, 81, 81, 81, 
-+	28, 29, 30, 81, 31, 32, 33, 81, 
-+	81, 81, 81, 19, 38, 39, 40, 84, 
-+	81, 18, 19, 20, 21, 22, 23, 24, 
-+	18, 81, 81, 81, 28, 29, 30, 81, 
-+	31, 32, 33, 81, 81, 81, 81, 19, 
-+	38, 39, 40, 84, 81, 3, 6, 81, 
-+	81, 82, 81, 81, 81, 81, 81, 81, 
-+	18, 19, 20, 21, 22, 23, 24, 18, 
-+	25, 81, 27, 28, 29, 30, 81, 31, 
-+	32, 33, 81, 81, 81, 81, 37, 38, 
-+	39, 40, 6, 81, 3, 81, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 81, 
-+	81, 81, 4, 81, 81, 81, 81, 81, 
-+	81, 81, 19, 20, 21, 22, 81, 81, 
-+	81, 81, 81, 81, 81, 81, 81, 81, 
-+	31, 32, 33, 81, 81, 81, 81, 81, 
-+	38, 39, 40, 84, 81, 3, 86, 86, 
-+	86, 86, 86, 86, 86, 86, 86, 86, 
-+	86, 86, 86, 4, 86, 87, 81, 14, 
-+	81, 81, 81, 81, 81, 81, 81, 88, 
-+	81, 14, 81, 6, 86, 86, 86, 86, 
-+	86, 86, 86, 86, 86, 86, 86, 86, 
-+	86, 86, 86, 86, 86, 86, 86, 86, 
-+	86, 86, 86, 86, 86, 86, 86, 86, 
-+	86, 86, 86, 6, 86, 86, 86, 6, 
-+	86, 9, 81, 81, 81, 9, 81, 81, 
-+	81, 81, 81, 3, 6, 14, 81, 82, 
-+	81, 81, 81, 81, 81, 81, 18, 19, 
-+	20, 21, 22, 23, 24, 18, 25, 26, 
-+	27, 28, 29, 30, 81, 31, 32, 33, 
-+	81, 34, 35, 81, 37, 38, 39, 40, 
-+	6, 81, 3, 6, 81, 81, 82, 81, 
-+	81, 81, 81, 81, 81, 18, 19, 20, 
-+	21, 22, 23, 24, 18, 25, 26, 27, 
-+	28, 29, 30, 81, 31, 32, 33, 81, 
-+	81, 81, 81, 37, 38, 39, 40, 6, 
-+	81, 34, 35, 81, 35, 81, 78, 80, 
-+	80, 80, 80, 80, 80, 80, 80, 80, 
-+	80, 80, 80, 80, 80, 80, 80, 80, 
-+	80, 80, 78, 79, 80, 9, 86, 86, 
-+	86, 9, 86, 0
- };
- 
- static const char _use_syllable_machine_trans_targs[] = {
--	4, 8, 4, 32, 2, 4, 1, 5,
--	6, 4, 29, 4, 51, 52, 53, 55,
--	34, 35, 36, 37, 38, 45, 46, 48,
--	54, 49, 42, 43, 44, 39, 40, 41,
--	58, 50, 4, 4, 4, 4, 7, 0,
--	28, 11, 12, 13, 14, 15, 22, 23,
--	25, 26, 19, 20, 21, 16, 17, 18,
--	27, 10, 4, 9, 24, 4, 30, 31,
--	4, 4, 3, 33, 47, 4, 4, 56,
--	57
-+	5, 9, 5, 41, 2, 5, 1, 53, 
-+	6, 7, 5, 34, 37, 63, 64, 67, 
-+	68, 72, 43, 44, 45, 46, 47, 57, 
-+	58, 60, 69, 61, 54, 55, 56, 50, 
-+	51, 52, 70, 71, 73, 62, 48, 49, 
-+	5, 5, 5, 5, 8, 0, 33, 12, 
-+	13, 14, 15, 16, 27, 28, 30, 31, 
-+	24, 25, 26, 19, 20, 21, 32, 17, 
-+	18, 5, 11, 5, 10, 22, 5, 23, 
-+	29, 5, 35, 36, 5, 38, 39, 40, 
-+	5, 5, 3, 42, 4, 59, 5, 65, 
-+	66
- };
- 
- static const char _use_syllable_machine_trans_actions[] = {
--	1, 0, 2, 3, 0, 4, 0, 0, 
--	7, 8, 0, 9, 10, 10, 3, 0, 
-+	1, 0, 2, 3, 0, 4, 0, 5, 
-+	0, 5, 8, 0, 5, 9, 0, 9, 
-+	3, 0, 5, 5, 0, 0, 0, 5, 
-+	5, 5, 3, 3, 5, 5, 5, 5, 
-+	5, 5, 0, 0, 0, 3, 0, 0, 
-+	10, 11, 12, 13, 5, 0, 5, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 5, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	3, 3, 0, 0, 0, 0, 0, 0, 
--	0, 3, 11, 12, 13, 14, 7, 0,
--	7, 0, 0, 0, 0, 0, 0, 0,
--	0, 7, 0, 0, 0, 0, 0, 0,
--	0, 7, 15, 0, 0, 16, 0, 0,
--	17, 18, 0, 3, 0, 19, 20, 0,
-+	0, 14, 5, 15, 0, 0, 16, 0, 
-+	0, 17, 0, 0, 18, 5, 0, 0, 
-+	19, 20, 0, 3, 0, 5, 21, 0, 
- 	0
- };
- 
- static const char _use_syllable_machine_to_state_actions[] = {
--	0, 0, 0, 0, 5, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 6, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0
- };
- 
- static const char _use_syllable_machine_from_state_actions[] = {
--	0, 0, 0, 0, 6, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 7, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0
-+	0, 0
- };
- 
- static const short _use_syllable_machine_eof_trans[] = {
--	1, 3, 3, 6, 0, 35, 37, 37,
--	59, 59, 37, 37, 37, 37, 37, 37,
--	37, 37, 37, 37, 37, 37, 37, 37,
--	37, 37, 37, 59, 37, 62, 65, 62,
--	66, 66, 66, 66, 66, 66, 66, 66,
--	66, 66, 66, 66, 66, 66, 66, 66,
--	66, 66, 66, 70, 70, 66, 66, 71,
--	71, 71, 70
-+	1, 3, 3, 6, 6, 0, 42, 44, 
-+	44, 68, 68, 44, 44, 44, 44, 44, 
-+	44, 44, 44, 44, 44, 44, 71, 44, 
-+	44, 44, 44, 44, 44, 44, 44, 44, 
-+	68, 44, 74, 77, 74, 44, 44, 81, 
-+	81, 82, 82, 82, 82, 82, 82, 82, 
-+	82, 82, 82, 82, 82, 82, 82, 82, 
-+	82, 82, 82, 82, 82, 82, 82, 87, 
-+	82, 82, 82, 87, 82, 82, 82, 82, 
-+	81, 87
- };
- 
--static const int use_syllable_machine_start = 4;
--static const int use_syllable_machine_first_final = 4;
-+static const int use_syllable_machine_start = 5;
-+static const int use_syllable_machine_first_final = 5;
- static const int use_syllable_machine_error = -1;
- 
--static const int use_syllable_machine_en_main = 4;
-+static const int use_syllable_machine_en_main = 5;
- 
- 
- #line 38 "hb-ot-shape-complex-use-machine.rl"
- 
- 
- 
--#line 143 "hb-ot-shape-complex-use-machine.rl"
-+#line 162 "hb-ot-shape-complex-use-machine.rl"
- 
- 
- #define found_syllable(syllable_type) \
-   HB_STMT_START { \
-     if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
-     for (unsigned int i = ts; i < te; i++) \
-       info[i].syllable() = (syllable_serial << 4) | syllable_type; \
-     syllable_serial++; \
-@@ -369,47 +387,47 @@ static const int use_syllable_machine_en
- 
- static void
- find_syllables (hb_buffer_t *buffer)
- {
-   unsigned int p, pe, eof, ts, te, act;
-   int cs;
-   hb_glyph_info_t *info = buffer->info;
-   
--#line 378 "hb-ot-shape-complex-use-machine.hh"
-+#line 396 "hb-ot-shape-complex-use-machine.hh"
- 	{
- 	cs = use_syllable_machine_start;
- 	ts = 0;
- 	te = 0;
- 	act = 0;
- 	}
- 
--#line 163 "hb-ot-shape-complex-use-machine.rl"
-+#line 182 "hb-ot-shape-complex-use-machine.rl"
- 
- 
-   p = 0;
-   pe = eof = buffer->len;
- 
-   unsigned int syllable_serial = 1;
-   
--#line 394 "hb-ot-shape-complex-use-machine.hh"
-+#line 412 "hb-ot-shape-complex-use-machine.hh"
- 	{
- 	int _slen;
- 	int _trans;
- 	const unsigned char *_keys;
- 	const char *_inds;
- 	if ( p == pe )
- 		goto _test_eof;
- _resume:
- 	switch ( _use_syllable_machine_from_state_actions[cs] ) {
--	case 6:
-+	case 7:
- #line 1 "NONE"
- 	{ts = p;}
- 	break;
--#line 408 "hb-ot-shape-complex-use-machine.hh"
-+#line 426 "hb-ot-shape-complex-use-machine.hh"
- 	}
- 
- 	_keys = _use_syllable_machine_trans_keys + (cs<<1);
- 	_inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
- 
- 	_slen = _use_syllable_machine_key_spans[cs];
- 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].use_category()) &&
- 		( info[p].use_category()) <= _keys[1] ?
-@@ -417,124 +435,128 @@ find_syllables (hb_buffer_t *buffer)
- 
- _eof_trans:
- 	cs = _use_syllable_machine_trans_targs[_trans];
- 
- 	if ( _use_syllable_machine_trans_actions[_trans] == 0 )
- 		goto _again;
- 
- 	switch ( _use_syllable_machine_trans_actions[_trans] ) {
--	case 7:
-+	case 5:
- #line 1 "NONE"
- 	{te = p+1;}
- 	break;
- 	case 12:
--#line 132 "hb-ot-shape-complex-use-machine.rl"
-+#line 150 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p+1;{ found_syllable (independent_cluster); }}
- 	break;
- 	case 14:
--#line 134 "hb-ot-shape-complex-use-machine.rl"
-+#line 153 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p+1;{ found_syllable (standard_cluster); }}
- 	break;
--	case 9:
--#line 138 "hb-ot-shape-complex-use-machine.rl"
-+	case 10:
-+#line 157 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p+1;{ found_syllable (broken_cluster); }}
- 	break;
- 	case 8:
--#line 139 "hb-ot-shape-complex-use-machine.rl"
-+#line 158 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p+1;{ found_syllable (non_cluster); }}
- 	break;
- 	case 11:
--#line 132 "hb-ot-shape-complex-use-machine.rl"
-+#line 150 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p;p--;{ found_syllable (independent_cluster); }}
- 	break;
- 	case 15:
--#line 133 "hb-ot-shape-complex-use-machine.rl"
-+#line 151 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p;p--;{ found_syllable (virama_terminated_cluster); }}
- 	break;
--	case 13:
--#line 134 "hb-ot-shape-complex-use-machine.rl"
--	{te = p;p--;{ found_syllable (standard_cluster); }}
--	break;
--	case 17:
--#line 135 "hb-ot-shape-complex-use-machine.rl"
--	{te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
--	break;
- 	case 16:
--#line 136 "hb-ot-shape-complex-use-machine.rl"
-+#line 152 "hb-ot-shape-complex-use-machine.rl"
-+	{te = p;p--;{ found_syllable (sakot_terminated_cluster); }}
-+	break;
-+	case 13:
-+#line 153 "hb-ot-shape-complex-use-machine.rl"
-+	{te = p;p--;{ found_syllable (standard_cluster); }}
-+	break;
-+	case 18:
-+#line 154 "hb-ot-shape-complex-use-machine.rl"
-+	{te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }}
-+	break;
-+	case 17:
-+#line 155 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p;p--;{ found_syllable (numeral_cluster); }}
- 	break;
--	case 20:
--#line 137 "hb-ot-shape-complex-use-machine.rl"
-+	case 19:
-+#line 156 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p;p--;{ found_syllable (symbol_cluster); }}
- 	break;
--	case 18:
--#line 138 "hb-ot-shape-complex-use-machine.rl"
-+	case 20:
-+#line 157 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p;p--;{ found_syllable (broken_cluster); }}
- 	break;
--	case 19:
--#line 139 "hb-ot-shape-complex-use-machine.rl"
-+	case 21:
-+#line 158 "hb-ot-shape-complex-use-machine.rl"
- 	{te = p;p--;{ found_syllable (non_cluster); }}
- 	break;
- 	case 1:
--#line 134 "hb-ot-shape-complex-use-machine.rl"
-+#line 153 "hb-ot-shape-complex-use-machine.rl"
- 	{{p = ((te))-1;}{ found_syllable (standard_cluster); }}
- 	break;
- 	case 4:
--#line 138 "hb-ot-shape-complex-use-machine.rl"
-+#line 157 "hb-ot-shape-complex-use-machine.rl"
- 	{{p = ((te))-1;}{ found_syllable (broken_cluster); }}
- 	break;
- 	case 2:
- #line 1 "NONE"
- 	{	switch( act ) {
--	case 7:
-+	case 8:
- 	{{p = ((te))-1;} found_syllable (broken_cluster); }
- 	break;
--	case 8:
-+	case 9:
- 	{{p = ((te))-1;} found_syllable (non_cluster); }
- 	break;
- 	}
- 	}
- 	break;
- 	case 3:
- #line 1 "NONE"
- 	{te = p+1;}
--#line 138 "hb-ot-shape-complex-use-machine.rl"
--	{act = 7;}
-+#line 157 "hb-ot-shape-complex-use-machine.rl"
-+	{act = 8;}
- 	break;
--	case 10:
-+	case 9:
- #line 1 "NONE"
- 	{te = p+1;}
--#line 139 "hb-ot-shape-complex-use-machine.rl"
--	{act = 8;}
-+#line 158 "hb-ot-shape-complex-use-machine.rl"
-+	{act = 9;}
- 	break;
--#line 510 "hb-ot-shape-complex-use-machine.hh"
-+#line 532 "hb-ot-shape-complex-use-machine.hh"
- 	}
- 
- _again:
- 	switch ( _use_syllable_machine_to_state_actions[cs] ) {
--	case 5:
-+	case 6:
- #line 1 "NONE"
- 	{ts = 0;}
- 	break;
--#line 519 "hb-ot-shape-complex-use-machine.hh"
-+#line 541 "hb-ot-shape-complex-use-machine.hh"
- 	}
- 
- 	if ( ++p != pe )
- 		goto _resume;
- 	_test_eof: {}
- 	if ( p == eof )
- 	{
- 	if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
- 		_trans = _use_syllable_machine_eof_trans[cs] - 1;
- 		goto _eof_trans;
- 	}
- 	}
- 
- 	}
- 
--#line 171 "hb-ot-shape-complex-use-machine.rl"
-+#line 190 "hb-ot-shape-complex-use-machine.rl"
- 
- }
- 
- #undef found_syllable
- 
- #endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-machine.rl
-@@ -44,33 +44,36 @@
- O	= 0; # OTHER
- 
- B	= 1; # BASE
- IND	= 3; # BASE_IND
- N	= 4; # BASE_NUM
- GB	= 5; # BASE_OTHER
- CGJ	= 6; # CGJ
- #F	= 7; # CONS_FINAL
--FM	= 8; # CONS_FINAL_MOD
-+#FM	= 8; # CONS_FINAL_MOD
- #M	= 9; # CONS_MED
- #CM	= 10; # CONS_MOD
- SUB	= 11; # CONS_SUB
- H	= 12; # HALANT
- 
- HN	= 13; # HALANT_NUM
- ZWNJ	= 14; # Zero width non-joiner
- ZWJ	= 15; # Zero width joiner
- WJ	= 16; # Word joiner
- Rsv	= 17; # Reserved characters
- R	= 18; # REPHA
- S	= 19; # SYM
- #SM	= 20; # SYM_MOD
- VS	= 21; # VARIATION_SELECTOR
- #V	= 36; # VOWEL
- #VM	= 40; # VOWEL_MOD
-+CS	= 43; # CONS_WITH_STACKER
-+HVM	= 44; # HALANT_OR_VOWEL_MODIFIER
-+Sk	= 48; # SAKOT
- 
- FAbv	= 24; # CONS_FINAL_ABOVE
- FBlw	= 25; # CONS_FINAL_BELOW
- FPst	= 26; # CONS_FINAL_POST
- MAbv	= 27; # CONS_MED_ABOVE
- MBlw	= 28; # CONS_MED_BELOW
- MPst	= 29; # CONS_MED_POST
- MPre	= 30; # CONS_MED_PRE
-@@ -81,61 +84,77 @@ VBlw	= 34; # VOWEL_BELOW / VOWEL_BELOW_P
- VPst	= 35; # VOWEL_POST	UIPC = Right
- VPre	= 22; # VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST
- VMAbv	= 37; # VOWEL_MOD_ABOVE
- VMBlw	= 38; # VOWEL_MOD_BELOW
- VMPst	= 39; # VOWEL_MOD_POST
- VMPre	= 23; # VOWEL_MOD_PRE
- SMAbv	= 41; # SYM_MOD_ABOVE
- SMBlw	= 42; # SYM_MOD_BELOW
--CS	= 43; # CONS_WITH_STACKER
-+FMAbv	= 45; # CONS_FINAL_MOD	UIPC = Top
-+FMBlw	= 46; # CONS_FINAL_MOD	UIPC = Bottom
-+FMPst	= 47; # CONS_FINAL_MOD	UIPC = Not_Applicable
- 
--HVM	= 44; # HALANT_OR_VOWEL_MODIFIER
--
--h = H | HVM; # https://github.com/harfbuzz/harfbuzz/issues/1102
-+h = H | HVM | Sk;
- 
- # Override: Adhoc ZWJ placement. https://github.com/harfbuzz/harfbuzz/issues/542#issuecomment-353169729
- consonant_modifiers = CMAbv* CMBlw* ((ZWJ?.h.ZWJ? B | SUB) VS? CMAbv? CMBlw*)*;
- # Override: Allow two MBlw. https://github.com/harfbuzz/harfbuzz/issues/376
- medial_consonants = MPre? MAbv? MBlw?.MBlw? MPst?;
- dependent_vowels = VPre* VAbv* VBlw* VPst*;
- vowel_modifiers = HVM? VMPre* VMAbv* VMBlw* VMPst*;
--final_consonants = FAbv* FBlw* FPst* FM?;
-+final_consonants = FAbv* FBlw* FPst*;
-+final_modifiers = FMAbv* FMBlw* | FMPst?;
- 
--complex_syllable_tail =
-+complex_syllable_start = (R | CS)? (B | GB) VS?;
-+complex_syllable_middle =
- 	consonant_modifiers
- 	medial_consonants
- 	dependent_vowels
- 	vowel_modifiers
-+	(Sk B)*
-+;
-+complex_syllable_tail =
-+	complex_syllable_middle
- 	final_consonants
-+	final_modifiers
- ;
-+number_joiner_terminated_cluster_tail = (HN N VS?)* HN;
-+numeral_cluster_tail = (HN N VS?)+;
-+symbol_cluster_tail = SMAbv+ SMBlw* | SMBlw+;
- 
- virama_terminated_cluster =
--	(R|CS)? (B | GB) VS?
-+	complex_syllable_start
- 	consonant_modifiers
- 	ZWJ?.h.ZWJ?
- ;
-+sakot_terminated_cluster =
-+	complex_syllable_start
-+	complex_syllable_middle
-+	Sk
-+;
- standard_cluster =
--	(R|CS)? (B | GB) VS?
-+	complex_syllable_start
- 	complex_syllable_tail
- ;
- broken_cluster =
- 	R?
--	complex_syllable_tail
-+	(complex_syllable_tail | number_joiner_terminated_cluster_tail | numeral_cluster_tail | symbol_cluster_tail)
- ;
- 
--number_joiner_terminated_cluster = N VS? (HN N VS?)* HN;
--numeral_cluster = N VS? (HN N VS?)*;
--symbol_cluster = S VS? SMAbv* SMBlw*;
-+number_joiner_terminated_cluster = N VS? number_joiner_terminated_cluster_tail;
-+numeral_cluster = N VS? numeral_cluster_tail?;
-+symbol_cluster = (S | GB) VS? symbol_cluster_tail?;
- independent_cluster = (IND | O | Rsv | WJ) VS?;
- other = any;
- 
- main := |*
- 	independent_cluster			=> { found_syllable (independent_cluster); };
- 	virama_terminated_cluster		=> { found_syllable (virama_terminated_cluster); };
-+	sakot_terminated_cluster		=> { found_syllable (sakot_terminated_cluster); };
- 	standard_cluster			=> { found_syllable (standard_cluster); };
- 	number_joiner_terminated_cluster	=> { found_syllable (number_joiner_terminated_cluster); };
- 	numeral_cluster				=> { found_syllable (numeral_cluster); };
- 	symbol_cluster				=> { found_syllable (symbol_cluster); };
- 	broken_cluster				=> { found_syllable (broken_cluster); };
- 	other					=> { found_syllable (non_cluster); };
- *|;
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use-table.cc
-@@ -17,37 +17,40 @@
- 
- #include "hb-ot-shape-complex-use.hh"
- 
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-macros"
- #define B	USE_B	/* BASE */
- #define CGJ	USE_CGJ	/* CGJ */
- #define CS	USE_CS	/* CONS_WITH_STACKER */
--#define FM	USE_FM	/* CONS_FINAL_MOD */
- #define GB	USE_GB	/* BASE_OTHER */
- #define H	USE_H	/* HALANT */
- #define HN	USE_HN	/* HALANT_NUM */
- #define HVM	USE_HVM	/* HALANT_OR_VOWEL_MODIFIER */
- #define IND	USE_IND	/* BASE_IND */
- #define N	USE_N	/* BASE_NUM */
- #define O	USE_O	/* OTHER */
- #define R	USE_R	/* REPHA */
- #define Rsv	USE_Rsv	/* Reserved */
- #define S	USE_S	/* SYM */
- #define SUB	USE_SUB	/* CONS_SUB */
-+#define Sk	USE_Sk	/* SAKOT */
- #define VS	USE_VS	/* VARIATION_SELECTOR */
- #define WJ	USE_WJ	/* Word_Joiner */
- #define ZWJ	USE_ZWJ	/* ZWJ */
- #define ZWNJ	USE_ZWNJ	/* ZWNJ */
- #define CMBlw	USE_CMBlw
- #define CMAbv	USE_CMAbv
- #define FBlw	USE_FBlw
- #define FPst	USE_FPst
- #define FAbv	USE_FAbv
-+#define FMBlw	USE_FMBlw
-+#define FMPst	USE_FMPst
-+#define FMAbv	USE_FMAbv
- #define MPre	USE_MPre
- #define MBlw	USE_MBlw
- #define MPst	USE_MPst
- #define MAbv	USE_MAbv
- #define SMBlw	USE_SMBlw
- #define SMAbv	USE_SMAbv
- #define VPre	USE_VPre
- #define VBlw	USE_VBlw
-@@ -70,17 +73,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
-   /* 0030 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
- 
- #define use_offset_0x00a0u 24
- 
- 
-   /* Latin-1 Supplement */
- 
-   /* 00A0 */    GB,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
--  /* 00B0 */     O,     O,    FM,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-+  /* 00B0 */     O,     O, FMPst, FMPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-   /* 00C0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-   /* 00D0 */     O,     O,     O,     O,     O,     O,     O,    GB,
- 
- #define use_offset_0x0348u 80
- 
- 
-   /* Combining Diacritical Marks */
-                                                                          O,     O,     O,     O,     O,     O,     O,   CGJ,
-@@ -103,17 +106,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
- 
-   /* 0980 */    GB, VMAbv, VMPst, VMPst,     O,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     B,
-   /* 0990 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 09A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-   /* 09B0 */     B,     O,     B,     O,     O,     O,     B,     B,     B,     B,     O,     O, CMBlw,     B,  VPst,  VPre,
-   /* 09C0 */  VPst,  VBlw,  VBlw,  VBlw,  VBlw,     O,     O,  VPre,  VPre,     O,     O,  VPst,  VPst,     H,   IND,     O,
-   /* 09D0 */     O,     O,     O,     O,     O,     O,     O,  VPst,     O,     O,     O,     O,     B,     B,     O,     B,
-   /* 09E0 */     B,     B,  VBlw,  VBlw,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
--  /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O,    FM,     O,
-+  /* 09F0 */     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     B,     O, FMAbv,     O,
- 
-   /* Gurmukhi */
- 
-   /* 0A00 */     O, VMAbv, VMAbv, VMPst,     O,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     B,
-   /* 0A10 */     B,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 0A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,
-   /* 0A30 */     B,     O,     B,     B,     O,     B,     B,     O,     B,     B,     O,     O, CMBlw,     O,  VPst,  VPre,
-   /* 0A40 */  VPst,  VBlw,  VBlw,     O,     O,     O,     O,  VAbv,  VAbv,     O,     O,  VAbv,  VAbv,     H,     O,     O,
-@@ -199,26 +202,26 @@ static const USE_TABLE_ELEMENT_TYPE use_
-   /* 0DF0 */     O,     O,  VPst,  VPst,     O,     O,     O,     O,
- 
- #define use_offset_0x0f18u 1360
- 
- 
-   /* Tibetan */
-                                                                       VBlw,  VBlw,     O,     O,     O,     O,     O,     O,
-   /* 0F20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
--  /* 0F30 */     B,     B,     B,     B,     O,    FM,     O,    FM,     O, CMAbv,     O,     O,     O,     O,  VPst,  VPre,
-+  /* 0F30 */     B,     B,     B,     B,     O, FMBlw,     O, FMBlw,     O, CMAbv,     O,     O,     O,     O,  VPst,  VPre,
-   /* 0F40 */     B,     B,     B,     B,     B,     B,     B,     B,     O,     B,     B,     B,     B,     B,     B,     B,
-   /* 0F50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 0F60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,
-   /* 0F70 */     O,  VBlw,  VBlw,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw, VMAbv, VMPst,
-   /* 0F80 */  VBlw,  VAbv, VMAbv, VMAbv,  VBlw,   IND, VMAbv, VMAbv,     B,     B,     B,     B,     B,   SUB,   SUB,   SUB,
-   /* 0F90 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
-   /* 0FA0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,
-   /* 0FB0 */   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,   SUB,     O,     O,     O,
--  /* 0FC0 */     O,     O,     O,     O,     O,     O,    FM,     O,
-+  /* 0FC0 */     O,     O,     O,     O,     O,     O, FMBlw,     O,
- 
- #define use_offset_0x1000u 1536
- 
- 
-   /* Myanmar */
- 
-   /* 1000 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1010 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-@@ -255,29 +258,29 @@ static const USE_TABLE_ELEMENT_TYPE use_
-   /* 1770 */     B,     O,  VAbv,  VBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Khmer */
- 
-   /* 1780 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1790 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 17A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 17B0 */     B,     B,     B,     B,     O,     O,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VPst,  VPst,
--  /* 17C0 */  VPst,  VPre,  VPre,  VPre,  VPst,  VPst, VMAbv, VMPst,  VPst, VMAbv, VMAbv,    FM,  FAbv, CMAbv,    FM,    FM,
--  /* 17D0 */    FM,  VAbv,     H,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     B,    FM,     O,     O,
-+  /* 17C0 */  VPst,  VPre,  VPre,  VPre,  VPst,  VPst, VMAbv, VMPst,  VPst, VMAbv, VMAbv, FMAbv,  FAbv, CMAbv, FMAbv, FMAbv,
-+  /* 17D0 */ FMAbv,  VAbv,     H, FMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     B, FMAbv,     O,     O,
-   /* 17E0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
- 
- #define use_offset_0x1900u 1936
- 
- 
-   /* Limbu */
- 
-   /* 1900 */    GB,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1910 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,
-   /* 1920 */  VAbv,  VAbv,  VBlw,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,   SUB,   SUB,   SUB,     O,     O,     O,     O,
--  /* 1930 */  FPst,  FPst, VMBlw,  FPst,  FPst,  FPst,  FPst,  FPst,  FPst,  FBlw,  VAbv,    FM,     O,     O,     O,     O,
-+  /* 1930 */  FPst,  FPst, VMBlw,  FPst,  FPst,  FPst,  FPst,  FPst,  FPst,  FBlw,  VAbv, FMBlw,     O,     O,     O,     O,
-   /* 1940 */     O,     O,     O,     O,     O,     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
- 
-   /* Tai Le */
- 
-   /* 1950 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1960 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,
-   /* 1970 */     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-@@ -297,34 +300,34 @@ static const USE_TABLE_ELEMENT_TYPE use_
-   /* 1A00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1A10 */     B,     B,     B,     B,     B,     B,     B,  VAbv,  VBlw,  VPre,  VPst,  VAbv,     O,     O,     O,     O,
- 
-   /* Tai Tham */
- 
-   /* 1A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1A30 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1A40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
--  /* 1A50 */     B,     B,     B,     B,     B,  MPre,  MBlw,   SUB,  FAbv,  FAbv,  FAbv,   SUB,   SUB,   SUB,   SUB,     O,
--  /* 1A60 */     H,  VPst,  VAbv,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VAbv,  VBlw,  VPst,  VPre,  VPre,
--  /* 1A70 */  VPre,  VPre,  VPre,  VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,  VAbv,    FM,    FM,     O,     O,  FBlw,
-+  /* 1A50 */     B,     B,     B,     B,     B,  MPre,  MBlw,   SUB,  FAbv,  FAbv,  MAbv,   SUB,   SUB,   SUB,   SUB,     O,
-+  /* 1A60 */    Sk,  VPst,  VAbv,  VPst,  VPst,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,  VBlw,  VAbv,  VBlw,  VPst,  VPre,  VPre,
-+  /* 1A70 */  VPre,  VPre,  VPre,  VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,  VAbv, FMAbv, FMAbv,     O,     O, FMBlw,
-   /* 1A80 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
-   /* 1A90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
- 
- #define use_offset_0x1b00u 2352
- 
- 
-   /* Balinese */
- 
-   /* 1B00 */ VMAbv, VMAbv, VMAbv,  FAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1B10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1B20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1B30 */     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VPre,  VPre,
-   /* 1B40 */  VPst,  VPst,  VAbv,  VAbv,     H,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,
--  /* 1B50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
--  /* 1B60 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
-+  /* 1B50 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,    GB,    GB,     O,     O,    GB,
-+  /* 1B60 */     O,     S,    GB,     S,     S,     S,     S,     S,    GB,     S,     S, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
-   /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Sundanese */
- 
-   /* 1B80 */ VMAbv,  FAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1B90 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1BA0 */     B,   SUB,   SUB,   SUB,  VAbv,  VBlw,  VPre,  VPst,  VAbv,  VAbv,  VPst,     H,   SUB,   SUB,     B,     B,
-   /* 1BB0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-@@ -336,49 +339,49 @@ static const USE_TABLE_ELEMENT_TYPE use_
-   /* 1BE0 */     B,     B,     B,     B,     B,     B, CMAbv,  VPst,  VAbv,  VAbv,  VPst,  VPst,  VPst,  VAbv,  VPst,  VAbv,
-   /* 1BF0 */  FAbv,  FAbv, CMBlw, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Lepcha */
- 
-   /* 1C00 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1C10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 1C20 */     B,     B,     B,     B,   SUB,   SUB,  VPst,  VPre,  VPre,  VPst,  VPst,  VPst,  VBlw,  FAbv,  FAbv,  FAbv,
--  /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre,    FM, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
-+  /* 1C30 */  FAbv,  FAbv,  FAbv,  FAbv, VMPre, VMPre, FMAbv, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,
-   /* 1C40 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     B,     B,     B,
- 
- #define use_offset_0x1cd0u 2688
- 
- 
-   /* Vedic Extensions */
- 
-   /* 1CD0 */ VMAbv, VMAbv, VMAbv,     O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
-   /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,     O,     O,     O,     O, VMBlw,     O,     O,
-   /* 1CF0 */     O,     O,   IND,   IND, VMAbv,    CS,    CS, VMPst, VMAbv, VMAbv,    GB,     O,     O,     O,     O,     O,
- 
- #define use_offset_0x1df8u 2736
- 
- 
-   /* Combining Diacritical Marks Supplement */
--                                                                         O,     O,     O,    FM,     O,     O,     O,     O,
-+                                                                         O,     O,     O, FMAbv,     O,     O,     O,     O,
- 
- #define use_offset_0x2008u 2744
- 
- 
-   /* General Punctuation */
-                                                                          O,     O,     O,     O,  ZWNJ,   ZWJ,     O,     O,
-   /* 2010 */    GB,    GB,    GB,    GB,    GB,     O,     O,     O,
- 
- #define use_offset_0x2060u 2760
- 
-   /* 2060 */    WJ,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Superscripts and Subscripts */
- 
--  /* 2070 */     O,     O,     O,     O,    FM,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
--  /* 2080 */     O,     O,    FM,    FM,    FM,     O,     O,     O,
-+  /* 2070 */     O,     O,     O,     O, FMPst,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-+  /* 2080 */     O,     O, FMPst, FMPst, FMPst,     O,     O,     O,
- 
- #define use_offset_0x20f0u 2800
- 
- 
-   /* Combining Diacritical Marks for Symbols */
- 
-   /* 20F0 */ VMAbv,     O,     O,     O,     O,     O,     O,     O,
- 
-@@ -542,17 +545,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
-   /* 11170 */     B,     B,     B, CMBlw,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Sharada */
- 
-   /* 11180 */ VMAbv, VMAbv, VMPst,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 11190 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 111A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 111B0 */     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,
--  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,    GB,  FBlw, CMBlw,  VAbv,  VBlw,     O,     O,     O,
-+  /* 111C0 */     H,     B,     R,     R,     O,     O,     O,     O,    GB, FMBlw, CMBlw,  VAbv,  VBlw,     O,     O,     O,
-   /* 111D0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,
- 
-   /* Sinhala Archaic Numbers */
- 
-   /* 111E0 */     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 111F0 */     B,     B,     B,     B,     B,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Khojki */
-@@ -595,17 +598,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
- 
-   /* Newa */
- 
-   /* 11400 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 11410 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 11420 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 11430 */     B,     B,     B,     B,     B,  VPst,  VPre,  VPst,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VBlw,  VAbv,  VAbv,
-   /* 11440 */  VPst,  VPst,     H, VMAbv, VMAbv, VMPst, CMBlw,     B,     O,     O,     O,     O,     O,     O,     O,     O,
--  /* 11450 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O,    FM,     B,
-+  /* 11450 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     O,     O,     O,     O, FMAbv,     B,
-   /* 11460 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-   /* 11470 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Tirhuta */
- 
-   /* 11480 */     O,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 11490 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 114A0 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-@@ -678,17 +681,17 @@ static const USE_TABLE_ELEMENT_TYPE use_
-   /* 119E0 */     H,     B,     O,     O,  VPre,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
-   /* 119F0 */     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Zanabazar Square */
- 
-   /* 11A00 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VAbv,  VBlw,     B,     B,     B,     B,     B,
-   /* 11A10 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 11A20 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
--  /* 11A30 */     B,     B,     B,    FM,  VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst,     R,  MBlw,  MBlw,  MBlw,  MBlw,    GB,
-+  /* 11A30 */     B,     B,     B, FMBlw,  VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst,     R,  MBlw,  MBlw,  MBlw,  MBlw,    GB,
-   /* 11A40 */     O,     O,     O,     O,     O,    GB,     O,     H,     O,     O,     O,     O,     O,     O,     O,     O,
- 
-   /* Soyombo */
- 
-   /* 11A50 */     B,  VAbv,  VBlw,  VBlw,  VAbv,  VAbv,  VAbv,  VPst,  VPst,  VBlw,  VBlw,  VBlw,     B,     B,     B,     B,
-   /* 11A60 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 11A70 */     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,     B,
-   /* 11A80 */     B,     B,     B,     B,     R,     R,     R,     R,     R,     R,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,  FBlw,
-@@ -804,37 +807,40 @@ hb_use_get_category (hb_codepoint_t u)
-       break;
-   }
-   return USE_O;
- }
- 
- #undef B
- #undef CGJ
- #undef CS
--#undef FM
- #undef GB
- #undef H
- #undef HN
- #undef HVM
- #undef IND
- #undef N
- #undef O
- #undef R
- #undef Rsv
- #undef S
- #undef SUB
-+#undef Sk
- #undef VS
- #undef WJ
- #undef ZWJ
- #undef ZWNJ
- #undef CMBlw
- #undef CMAbv
- #undef FBlw
- #undef FPst
- #undef FAbv
-+#undef FMBlw
-+#undef FMPst
-+#undef FMAbv
- #undef MPre
- #undef MBlw
- #undef MPst
- #undef MAbv
- #undef SMBlw
- #undef SMAbv
- #undef VPre
- #undef VBlw
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use.cc
-@@ -241,16 +241,17 @@ data_destroy_use (void *data)
-     data_destroy_arabic (use_plan->arabic_plan);
- 
-   free (data);
- }
- 
- enum syllable_type_t {
-   independent_cluster,
-   virama_terminated_cluster,
-+  sakot_terminated_cluster,
-   standard_cluster,
-   number_joiner_terminated_cluster,
-   numeral_cluster,
-   symbol_cluster,
-   broken_cluster,
-   non_cluster,
- };
- 
-@@ -289,17 +290,17 @@ setup_rphf_mask (const hb_ot_shape_plan_
- 
-   hb_mask_t mask = use_plan->rphf_mask;
-   if (!mask) return;
- 
-   hb_glyph_info_t *info = buffer->info;
- 
-   foreach_syllable (buffer, start, end)
-   {
--    unsigned int limit = info[start].use_category() == USE_R ? 1 : MIN (3u, end - start);
-+    unsigned int limit = info[start].use_category() == USE_R ? 1 : hb_min (3u, end - start);
-     for (unsigned int i = start; i < start + limit; i++)
-       info[i].mask |= mask;
-   }
- }
- 
- static void
- setup_topographical_masks (const hb_ot_shape_plan_t *plan,
- 			   hb_buffer_t *buffer)
-@@ -332,16 +333,17 @@ setup_topographical_masks (const hb_ot_s
-       case independent_cluster:
-       case symbol_cluster:
-       case non_cluster:
- 	/* These don't join.  Nothing to do. */
- 	last_form = _NONE;
- 	break;
- 
-       case virama_terminated_cluster:
-+      case sakot_terminated_cluster:
-       case standard_cluster:
-       case number_joiner_terminated_cluster:
-       case numeral_cluster:
-       case broken_cluster:
- 
- 	bool join = last_form == FINA || last_form == ISOL;
- 
- 	if (join)
-@@ -438,16 +440,17 @@ is_halant (const hb_glyph_info_t &info)
- 
- static void
- reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
- {
-   syllable_type_t syllable_type = (syllable_type_t) (buffer->info[start].syllable() & 0x0F);
-   /* Only a few syllable types need reordering. */
-   if (unlikely (!(FLAG_UNSAFE (syllable_type) &
- 		  (FLAG (virama_terminated_cluster) |
-+		   FLAG (sakot_terminated_cluster) |
- 		   FLAG (standard_cluster) |
- 		   FLAG (broken_cluster) |
- 		   0))))
-     return;
- 
-   hb_glyph_info_t *info = buffer->info;
- 
- #define POST_BASE_FLAGS64 (FLAG64 (USE_FM) | \
-@@ -521,17 +524,18 @@ reorder_syllable (hb_buffer_t *buffer, u
- static inline void
- insert_dotted_circles (const hb_ot_shape_plan_t *plan HB_UNUSED,
- 		       hb_font_t *font,
- 		       hb_buffer_t *buffer)
- {
-   if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
-     return;
- 
--  /* Note: This loop is extra overhead, but should not be measurable. */
-+  /* Note: This loop is extra overhead, but should not be measurable.
-+   * TODO Use a buffer scratch flag to remove the loop. */
-   bool has_broken_syllables = false;
-   unsigned int count = buffer->len;
-   hb_glyph_info_t *info = buffer->info;
-   for (unsigned int i = 0; i < count; i++)
-     if ((info[i].syllable() & 0x0F) == broken_cluster)
-     {
-       has_broken_syllables = true;
-       break;
-@@ -555,17 +559,16 @@ insert_dotted_circles (const hb_ot_shape
-     if (unlikely (last_syllable != syllable && syllable_type == broken_cluster))
-     {
-       last_syllable = syllable;
- 
-       hb_glyph_info_t ginfo = dottedcircle;
-       ginfo.cluster = buffer->cur().cluster;
-       ginfo.mask = buffer->cur().mask;
-       ginfo.syllable() = buffer->cur().syllable();
--      /* TODO Set glyph_props? */
- 
-       /* Insert dottedcircle after possible Repha. */
-       while (buffer->idx < buffer->len && buffer->successful &&
- 	     last_syllable == buffer->cur().syllable() &&
- 	     buffer->cur().use_category() == USE_R)
-         buffer->next_glyph ();
- 
-       buffer->output_info (ginfo);
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-use.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-use.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-use.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-use.hh
-@@ -63,16 +63,22 @@ enum use_category_t {
-   USE_WJ	= 16,	/* Word joiner */
-   USE_Rsv	= 17,	/* Reserved characters */
-   USE_R		= 18,	/* REPHA */
-   USE_S		= 19,	/* SYM */
- //  USE_SM	= 20,	/* SYM_MOD */
-   USE_VS	= 21,	/* VARIATION_SELECTOR */
- //  USE_V	= 36,	/* VOWEL */
- //  USE_VM	= 40,	/* VOWEL_MOD */
-+  USE_CS	= 43,	/* CONS_WITH_STACKER */
-+
-+  /* https://github.com/harfbuzz/harfbuzz/issues/1102 */
-+  USE_HVM	= 44,	/* HALANT_OR_VOWEL_MODIFIER */
-+
-+  USE_Sk	= 48,	/* SAKOT */
- 
-   USE_FAbv	= 24,	/* CONS_FINAL_ABOVE */
-   USE_FBlw	= 25,	/* CONS_FINAL_BELOW */
-   USE_FPst	= 26,	/* CONS_FINAL_POST */
-   USE_MAbv	= 27,	/* CONS_MED_ABOVE */
-   USE_MBlw	= 28,	/* CONS_MED_BELOW */
-   USE_MPst	= 29,	/* CONS_MED_POST */
-   USE_MPre	= 30,	/* CONS_MED_PRE */
-@@ -83,18 +89,17 @@ enum use_category_t {
-   USE_VPst	= 35,	/* VOWEL_POST	UIPC = Right */
-   USE_VPre	= 22,	/* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */
-   USE_VMAbv	= 37,	/* VOWEL_MOD_ABOVE */
-   USE_VMBlw	= 38,	/* VOWEL_MOD_BELOW */
-   USE_VMPst	= 39,	/* VOWEL_MOD_POST */
-   USE_VMPre	= 23,	/* VOWEL_MOD_PRE */
-   USE_SMAbv	= 41,	/* SYM_MOD_ABOVE */
-   USE_SMBlw	= 42,	/* SYM_MOD_BELOW */
--  USE_CS	= 43,	/* CONS_WITH_STACKER */
--
--  /* https://github.com/harfbuzz/harfbuzz/issues/1102 */
--  USE_HVM	= 44,	/* HALANT_OR_VOWEL_MODIFIER */
-+  USE_FMAbv	= 45,	/* CONS_FINAL_MOD	UIPC = Top */
-+  USE_FMBlw	= 46,	/* CONS_FINAL_MOD	UIPC = Bottom */
-+  USE_FMPst	= 47,	/* CONS_FINAL_MOD	UIPC = Not_Applicable */
- };
- 
- HB_INTERNAL USE_TABLE_ELEMENT_TYPE
- hb_use_get_category (hb_codepoint_t u);
- 
- #endif /* HB_OT_SHAPE_COMPLEX_USE_HH */
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc b/gfx/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
-@@ -29,16 +29,19 @@ static void
-   buffer->next_glyph ();
- }
- 
- void
- _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
- 				       hb_buffer_t              *buffer,
- 				       hb_font_t                *font HB_UNUSED)
- {
-+#ifdef HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
-+  return;
-+#endif
-   if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)
-     return;
- 
-   /* UGLY UGLY UGLY business of adding dotted-circle in the middle of
-    * vowel-sequences that look like another vowel.  Data for each script
-    * collected from the USE script development spec.
-    *
-    * https://github.com/harfbuzz/harfbuzz/issues/1019
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc
---- a/gfx/harfbuzz/src/hb-ot-shape-fallback.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc
-@@ -161,16 +161,20 @@ recategorize_combining_class (hb_codepoi
-   return klass;
- }
- 
- void
- _hb_ot_shape_fallback_mark_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
- 						        hb_font_t *font HB_UNUSED,
- 						        hb_buffer_t  *buffer)
- {
-+#ifdef HB_NO_OT_SHAPE_FALLBACK
-+  return;
-+#endif
-+
-   unsigned int count = buffer->len;
-   hb_glyph_info_t *info = buffer->info;
-   for (unsigned int i = 0; i < count; i++)
-     if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
-       unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&info[i]);
-       combining_class = recategorize_combining_class (info[i].codepoint, combining_class);
-       _hb_glyph_info_set_modified_combining_class (&info[i], combining_class);
-     }
-@@ -429,30 +433,35 @@ position_cluster (const hb_ot_shape_plan
- }
- 
- void
- _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan,
- 				     hb_font_t *font,
- 				     hb_buffer_t  *buffer,
- 				     bool adjust_offsets_when_zeroing)
- {
-+#ifdef HB_NO_OT_SHAPE_FALLBACK
-+  return;
-+#endif
-+
-   _hb_buffer_assert_gsubgpos_vars (buffer);
- 
-   unsigned int start = 0;
-   unsigned int count = buffer->len;
-   hb_glyph_info_t *info = buffer->info;
-   for (unsigned int i = 1; i < count; i++)
-     if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])))) {
-       position_cluster (plan, font, buffer, start, i, adjust_offsets_when_zeroing);
-       start = i;
-     }
-   position_cluster (plan, font, buffer, start, count, adjust_offsets_when_zeroing);
- }
- 
- 
-+#ifndef HB_DISABLE_DEPRECATED
- struct hb_ot_shape_fallback_kern_driver_t
- {
-   hb_ot_shape_fallback_kern_driver_t (hb_font_t   *font_,
- 				      hb_buffer_t *buffer) :
-     font (font_), direction (buffer->props.direction) {}
- 
-   hb_position_t get_kerning (hb_codepoint_t first, hb_codepoint_t second) const
-   {
-@@ -461,39 +470,46 @@ struct hb_ot_shape_fallback_kern_driver_
- 					   direction,
- 					   &kern, &kern);
-     return kern;
-   }
- 
-   hb_font_t *font;
-   hb_direction_t direction;
- };
-+#endif
- 
- /* Performs font-assisted kerning. */
- void
- _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
- 			    hb_font_t *font,
- 			    hb_buffer_t *buffer)
- {
-+#ifdef HB_NO_OT_SHAPE_FALLBACK
-+  return;
-+#endif
-+
-+#ifndef HB_DISABLE_DEPRECATED
-   if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
-       !font->has_glyph_h_kerning_func () :
-       !font->has_glyph_v_kerning_func ())
-     return;
- 
-   bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
- 
-   if (reverse)
-     buffer->reverse ();
- 
-   hb_ot_shape_fallback_kern_driver_t driver (font, buffer);
-   OT::hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t> machine (driver);
-   machine.kern (font, buffer, plan->kern_mask, false);
- 
-   if (reverse)
-     buffer->reverse ();
-+#endif
- }
- 
- 
- /* Adjusts width of various spaces. */
- void
- _hb_ot_shape_fallback_spaces (const hb_ot_shape_plan_t *plan HB_UNUSED,
- 			      hb_font_t *font,
- 			      hb_buffer_t  *buffer)
-diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc
---- a/gfx/harfbuzz/src/hb-ot-shape.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
-@@ -50,38 +50,42 @@
-  **/
- 
- 
- static void
- hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
- 			      const hb_feature_t             *user_features,
- 			      unsigned int                    num_user_features);
- 
--static bool
-+#ifndef HB_NO_SHAPE_AAT
-+static inline bool
- _hb_apply_morx (hb_face_t *face)
- {
-   if (hb_options ().aat &&
-       hb_aat_layout_has_substitution (face))
-     return true;
- 
-   /* Ignore empty GSUB tables. */
-   return (!hb_ot_layout_has_substitution (face) ||
- 	  !hb_ot_layout_table_get_script_tags (face,
- 					       HB_OT_TAG_GSUB,
- 					       0, nullptr, nullptr)) &&
- 	 hb_aat_layout_has_substitution (face);
- }
-+#endif
- 
- hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t                     *face,
- 					      const hb_segment_properties_t *props) :
- 						face (face),
- 						props (*props),
- 						map (face, props),
--						aat_map (face, props),
--						apply_morx (_hb_apply_morx (face))
-+						aat_map (face, props)
-+#ifndef HB_NO_SHAPE_AAT
-+						, apply_morx (_hb_apply_morx (face))
-+#endif
- {
-   shaper = hb_ot_shape_complex_categorize (this);
- 
-   script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
-   script_fallback_mark_positioning = shaper->fallback_position;
- 
-   if (apply_morx)
-     shaper = &_hb_ot_complex_shaper_default;
-@@ -119,52 +123,66 @@ hb_ot_shape_planner_t::compile (hb_ot_sh
- 
-   if (!hb_ot_layout_has_glyph_classes (face))
-     plan.fallback_glyph_classes = true;
- 
-   /*
-    * Decide who does substitutions. GSUB, morx, or fallback.
-    */
- 
-+#ifndef HB_NO_SHAPE_AAT
-   plan.apply_morx = apply_morx;
-+#endif
- 
-   /*
-    * Decide who does positioning. GPOS, kerx, kern, or fallback.
-    */
- 
--  if (hb_options ().aat && hb_aat_layout_has_positioning (face))
-+  if (0)
-+    ;
-+#ifndef HB_NO_SHAPE_AAT
-+  else if (hb_options ().aat && hb_aat_layout_has_positioning (face))
-     plan.apply_kerx = true;
-+#endif
-   else if (!apply_morx && !disable_gpos && hb_ot_layout_has_positioning (face))
-     plan.apply_gpos = true;
-+#ifndef HB_NO_SHAPE_AAT
-   else if (hb_aat_layout_has_positioning (face))
-     plan.apply_kerx = true;
-+#endif
- 
-   if (!plan.apply_kerx && !has_gpos_kern)
-   {
-     /* Apparently Apple applies kerx if GPOS kern was not applied. */
--    if (hb_aat_layout_has_positioning (face))
-+    if (0)
-+      ;
-+#ifndef HB_NO_SHAPE_AAT
-+    else if (hb_aat_layout_has_positioning (face))
-       plan.apply_kerx = true;
-+#endif
-     else if (hb_ot_layout_has_kerning (face))
-       plan.apply_kern = true;
-   }
- 
-   plan.zero_marks = script_zero_marks &&
- 		    !plan.apply_kerx &&
- 		    (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face));
-   plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
- 
-   plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
- 					      !plan.apply_kerx &&
- 					      (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face));
- 
-   plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
- 				   script_fallback_mark_positioning;
- 
-+#ifndef HB_NO_SHAPE_AAT
-   /* Currently we always apply trak. */
-   plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
-+#endif
- }
- 
- bool
- hb_ot_shape_plan_t::init0 (hb_face_t                     *face,
- 			   const hb_shape_plan_key_t     *key)
- {
-   map.init ();
-   aat_map.init ();
-@@ -957,22 +975,22 @@ hb_propagate_flags (hb_buffer_t *buffer)
- 
- static void
- hb_ot_shape_internal (hb_ot_shape_context_t *c)
- {
-   c->buffer->deallocate_var_all ();
-   c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-   if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
-   {
--    c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
-+    c->buffer->max_len = hb_max (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
- 			      (unsigned) HB_BUFFER_MAX_LEN_MIN);
-   }
-   if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
-   {
--    c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
-+    c->buffer->max_ops = hb_max (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
- 			      (unsigned) HB_BUFFER_MAX_OPS_MIN);
-   }
- 
-   /* Save the original direction, we use it later. */
-   c->target_direction = c->buffer->props.direction;
- 
-   _hb_buffer_allocate_unicode_vars (c->buffer);
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-shape.hh b/gfx/harfbuzz/src/hb-ot-shape.hh
---- a/gfx/harfbuzz/src/hb-ot-shape.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape.hh
-@@ -75,20 +75,26 @@ struct hb_ot_shape_plan_t
-   bool has_frac : 1;
-   bool has_gpos_mark : 1;
-   bool zero_marks : 1;
-   bool fallback_glyph_classes : 1;
-   bool fallback_mark_positioning : 1;
-   bool adjust_mark_positioning_when_zeroing : 1;
- 
-   bool apply_gpos : 1;
-+  bool apply_kern : 1;
-+#ifndef HB_NO_SHAPE_AAT
-   bool apply_kerx : 1;
--  bool apply_kern : 1;
-   bool apply_morx : 1;
-   bool apply_trak : 1;
-+#else
-+  static constexpr bool apply_kerx = false;
-+  static constexpr bool apply_morx = false;
-+  static constexpr bool apply_trak = false;
-+#endif
- 
-   void collect_lookups (hb_tag_t table_tag, hb_set_t *lookups) const
-   {
-     unsigned int table_index;
-     switch (table_tag) {
-       case HB_OT_TAG_GSUB: table_index = 0; break;
-       case HB_OT_TAG_GPOS: table_index = 1; break;
-       default: return;
-@@ -108,17 +114,21 @@ struct hb_shape_plan_t;
- 
- struct hb_ot_shape_planner_t
- {
-   /* In the order that they are filled in. */
-   hb_face_t *face;
-   hb_segment_properties_t props;
-   hb_ot_map_builder_t map;
-   hb_aat_map_builder_t aat_map;
-+#ifndef HB_NO_SHAPE_AAT
-   bool apply_morx : 1;
-+#else
-+  static constexpr bool apply_morx = false;
-+#endif
-   bool script_zero_marks : 1;
-   bool script_fallback_mark_positioning : 1;
-   const struct hb_ot_complex_shaper_t *shaper;
- 
-   HB_INTERNAL hb_ot_shape_planner_t (hb_face_t                     *face,
- 				     const hb_segment_properties_t *props);
- 
-   HB_INTERNAL void compile (hb_ot_shape_plan_t           &plan,
-diff --git a/gfx/harfbuzz/src/hb-ot-stat-table.hh b/gfx/harfbuzz/src/hb-ot-stat-table.hh
---- a/gfx/harfbuzz/src/hb-ot-stat-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-stat-table.hh
-@@ -60,16 +60,18 @@ enum
- struct AxisValueFormat1
- {
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
-+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-+
-   protected:
-   HBUINT16	format;		/* Format identifier — set to 1. */
-   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
- 				 * identifying the axis of design variation
- 				 * to which the axis value record applies.
- 				 * Must be less than designAxisCount. */
-   HBUINT16	flags;		/* Flags — see below for details. */
-   NameID	valueNameID;	/* The name ID for entries in the 'name' table
-@@ -83,16 +85,18 @@ struct AxisValueFormat1
- struct AxisValueFormat2
- {
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
-+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-+
-   protected:
-   HBUINT16	format;		/* Format identifier — set to 2. */
-   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
- 				 * identifying the axis of design variation
- 				 * to which the axis value record applies.
- 				 * Must be less than designAxisCount. */
-   HBUINT16	flags;		/* Flags — see below for details. */
-   NameID	valueNameID;	/* The name ID for entries in the 'name' table
-@@ -110,16 +114,18 @@ struct AxisValueFormat2
- struct AxisValueFormat3
- {
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
-+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-+
-   protected:
-   HBUINT16	format;		/* Format identifier — set to 3. */
-   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
- 				 * identifying the axis of design variation
- 				 * to which the axis value record applies.
- 				 * Must be less than designAxisCount. */
-   HBUINT16	flags;		/* Flags — see below for details. */
-   NameID	valueNameID;	/* The name ID for entries in the 'name' table
-@@ -152,16 +158,18 @@ struct AxisValueRecord
- struct AxisValueFormat4
- {
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
-+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-+
-   protected:
-   HBUINT16	format;		/* Format identifier — set to 4. */
-   HBUINT16	axisCount;	/* The total number of axes contributing to
- 				 * this axis-values combination. */
-   HBUINT16	flags;		/* Flags — see below for details. */
-   NameID	valueNameID;	/* The name ID for entries in the 'name' table
- 				 * that provide a display string for this
- 				 * attribute value. */
-@@ -173,29 +181,41 @@ struct AxisValueFormat4
-   DEFINE_SIZE_ARRAY (8, axisValues);
- };
- 
- struct AxisValue
- {
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
--    if (unlikely (c->check_struct (this)))
-+    if (unlikely (!c->check_struct (this)))
-       return_trace (false);
- 
-     switch (u.format)
-     {
-     case 1:  return_trace (likely (u.format1.sanitize (c)));
-     case 2:  return_trace (likely (u.format2.sanitize (c)));
-     case 3:  return_trace (likely (u.format3.sanitize (c)));
-     case 4:  return_trace (likely (u.format4.sanitize (c)));
-     default: return_trace (true);
-     }
-   }
- 
-+  hb_ot_name_id_t get_value_name_id () const
-+  {
-+    switch (u.format)
-+    {
-+      case 1: return u.format1.get_value_name_id ();
-+      case 2: return u.format2.get_value_name_id ();
-+      case 3: return u.format3.get_value_name_id ();
-+      case 4: return u.format4.get_value_name_id ();
-+      default: return HB_OT_NAME_ID_INVALID;
-+    }
-+  }
-+
-   protected:
-   union
-   {
-   HBUINT16		format;
-   AxisValueFormat1	format1;
-   AxisValueFormat2	format2;
-   AxisValueFormat3	format3;
-   AxisValueFormat4	format4;
-@@ -207,16 +227,18 @@ struct AxisValue
- struct StatAxisRecord
- {
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
-+  hb_ot_name_id_t get_name_id () const { return nameID; }
-+
-   protected:
-   Tag		tag;		/* A tag identifying the axis of design variation. */
-   NameID	nameID;		/* The name ID for entries in the 'name' table that
- 				 * provide a display string for this axis. */
-   HBUINT16	ordering;	/* A value that applications can use to determine
- 				 * primary sorting of face names, or for ordering
- 				 * of descriptors when composing family or face names. */
-   public:
-@@ -226,43 +248,85 @@ struct StatAxisRecord
- struct STAT
- {
-   static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this) &&
--			  majorVersion == 1 &&
--			  minorVersion > 0 &&
-+			  version.major == 1 &&
-+                          version.minor > 0 &&
- 			  designAxesOffset.sanitize (c, this, designAxisCount) &&
- 			  offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
-   }
- 
-+  bool has_data () const { return version.to_int (); }
-+
-+  unsigned get_design_axis_count () const { return designAxisCount; }
-+
-+  hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const
-+  {
-+    if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID;
-+    const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index];
-+    return axis_record.get_name_id ();
-+  }
-+
-+  unsigned get_axis_value_count () const { return axisValueCount; }
-+
-+  hb_ot_name_id_t get_axis_value_name_id (unsigned axis_value_index) const
-+  {
-+    if (unlikely (axis_value_index >= axisValueCount)) return HB_OT_NAME_ID_INVALID;
-+    const AxisValue &axis_value = (this + get_axis_value_offsets ()[axis_value_index]);
-+    return axis_value.get_value_name_id ();
-+  }
-+
-+  void collect_name_ids (hb_set_t *nameids_to_retain) const
-+  {
-+    if (!has_data ()) return;
-+
-+    + get_design_axes ()
-+    | hb_map (&StatAxisRecord::get_name_id)
-+    | hb_sink (nameids_to_retain)
-+    ;
-+
-+    + get_axis_value_offsets ()
-+    | hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
-+    | hb_map (&AxisValue::get_value_name_id)
-+    | hb_sink (nameids_to_retain)
-+    ;
-+  }
-+
-   protected:
--  HBUINT16	majorVersion;	/* Major version number of the style attributes
--				 * table — set to 1. */
--  HBUINT16	minorVersion;	/* Minor version number of the style attributes
--				 * table — set to 2. */
-+  hb_array_t<const StatAxisRecord> const get_design_axes () const
-+  { return (this+designAxesOffset).as_array (designAxisCount); }
-+
-+  hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const
-+  { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); }
-+
-+
-+  protected:
-+  FixedVersion<>version;        /* Version of the stat table
-+                                 * initially set to 0x00010002u */
-   HBUINT16	designAxisSize;	/* The size in bytes of each axis record. */
-   HBUINT16	designAxisCount;/* The number of design axis records. In a
- 				 * font with an 'fvar' table, this value must be
- 				 * greater than or equal to the axisCount value
- 				 * in the 'fvar' table. In all fonts, must
- 				 * be greater than zero if axisValueCount
- 				 * is greater than zero. */
--  LNNOffsetTo<UnsizedArrayOf<StatAxisRecord> >
-+  LNNOffsetTo<UnsizedArrayOf<StatAxisRecord>>
- 		designAxesOffset;
- 				/* Offset in bytes from the beginning of
- 				 * the STAT table to the start of the design
- 				 * axes array. If designAxisCount is zero,
- 				 * set to zero; if designAxisCount is greater
- 				 * than zero, must be greater than zero. */
-   HBUINT16	axisValueCount;	/* The number of axis value tables. */
--  LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue> > >
-+  LNNOffsetTo<UnsizedArrayOf<OffsetTo<AxisValue>>>
- 		offsetToAxisValueOffsets;
- 				/* Offset in bytes from the beginning of
- 				 * the STAT table to the start of the design
- 				 * axes value offsets array. If axisValueCount
- 				 * is zero, set to zero; if axisValueCount is
- 				 * greater than zero, must be greater than zero. */
-   NameID	elidedFallbackNameID;
- 				/* Name ID used as fallback when projection of
-diff --git a/gfx/harfbuzz/src/hb-ot-tag-table.hh b/gfx/harfbuzz/src/hb-ot-tag-table.hh
---- a/gfx/harfbuzz/src/hb-ot-tag-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-tag-table.hh
-@@ -2,1064 +2,1062 @@
- /*
-  * The following table is generated by running:
-  *
-  *   ./gen-tag-table.py languagetags language-subtag-registry
-  *
-  * on files with these headers:
-  *
-  * <meta name="updated_at" content="2018-11-18 05:25 AM" />
-- * File-Date: 2019-02-20
-+ * File-Date: 2019-04-03
-  */
- 
- #ifndef HB_OT_TAG_TABLE_HH
- #define HB_OT_TAG_TABLE_HH
- 
- static const LangTag ot_languages[] = {
--  {"aa",	{HB_TAG('A','F','R',' ')}},	/* Afar */
--  {"aae",	{HB_TAG('S','Q','I',' ')}},	/* Arbëreshë Albanian -> Albanian */
--  {"aao",	{HB_TAG('A','R','A',' ')}},	/* Algerian Saharan Arabic -> Arabic */
--  {"aat",	{HB_TAG('S','Q','I',' ')}},	/* Arvanitika Albanian -> Albanian */
--  {"ab",	{HB_TAG('A','B','K',' ')}},	/* Abkhazian */
--  {"abh",	{HB_TAG('A','R','A',' ')}},	/* Tajiki Arabic -> Arabic */
--  {"abq",	{HB_TAG('A','B','A',' ')}},	/* Abaza */
--  {"abv",	{HB_TAG('A','R','A',' ')}},	/* Baharna Arabic -> Arabic */
--  {"acf",	{HB_TAG('F','A','N',' ')}},	/* Saint Lucian Creole French -> French Antillean */
--  {"ach",	{HB_TAG('A','C','H',' ')}},	/* Acoli -> Acholi */
--  {"acm",	{HB_TAG('A','R','A',' ')}},	/* Mesopotamian Arabic -> Arabic */
--  {"acq",	{HB_TAG('A','R','A',' ')}},	/* Ta'izzi-Adeni Arabic -> Arabic */
--  {"acr",	{HB_TAG('A','C','R',' ')}},	/* Achi */
--  {"acw",	{HB_TAG('A','R','A',' ')}},	/* Hijazi Arabic -> Arabic */
--  {"acx",	{HB_TAG('A','R','A',' ')}},	/* Omani Arabic -> Arabic */
--  {"acy",	{HB_TAG('A','R','A',' ')}},	/* Cypriot Arabic -> Arabic */
--  {"ada",	{HB_TAG('D','N','G',' ')}},	/* Adangme -> Dangme */
--  {"adf",	{HB_TAG('A','R','A',' ')}},	/* Dhofari Arabic -> Arabic */
--  {"adp",	{HB_TAG('D','Z','N',' ')}},	/* Adap (retired code) -> Dzongkha */
--  {"ady",	{HB_TAG('A','D','Y',' ')}},	/* Adyghe */
--  {"aeb",	{HB_TAG('A','R','A',' ')}},	/* Tunisian Arabic -> Arabic */
--  {"aec",	{HB_TAG('A','R','A',' ')}},	/* Saidi Arabic -> Arabic */
--  {"af",	{HB_TAG('A','F','K',' ')}},	/* Afrikaans */
--  {"afb",	{HB_TAG('A','R','A',' ')}},	/* Gulf Arabic -> Arabic */
--  {"ahg",	{HB_TAG('A','G','W',' ')}},	/* Qimant -> Agaw */
--  {"aht",	{HB_TAG('A','T','H',' ')}},	/* Ahtena -> Athapaskan */
--  {"aii",	{HB_TAG('S','W','A',' '),	/* Assyrian Neo-Aramaic -> Swadaya Aramaic */
--		 HB_TAG('S','Y','R',' ')}},	/* Assyrian Neo-Aramaic -> Syriac */
--  {"aio",	{HB_TAG('A','I','O',' ')}},	/* Aiton */
--  {"aiw",	{HB_TAG('A','R','I',' ')}},	/* Aari */
--  {"ajp",	{HB_TAG('A','R','A',' ')}},	/* South Levantine Arabic -> Arabic */
--  {"ak",	{HB_TAG('A','K','A',' '),	/* Akan [macrolanguage] */
--		 HB_TAG('T','W','I',' ')}},	/* Akan [macrolanguage] -> Twi */
--  {"aln",	{HB_TAG('S','Q','I',' ')}},	/* Gheg Albanian -> Albanian */
--  {"als",	{HB_TAG('S','Q','I',' ')}},	/* Tosk Albanian -> Albanian */
--  {"alt",	{HB_TAG('A','L','T',' ')}},	/* Southern Altai -> Altai */
--  {"am",	{HB_TAG('A','M','H',' ')}},	/* Amharic */
--  {"amf",	{HB_TAG('H','B','N',' ')}},	/* Hamer-Banna -> Hammer-Banna */
--  {"amw",	{HB_TAG('S','Y','R',' ')}},	/* Western Neo-Aramaic -> Syriac */
--  {"an",	{HB_TAG('A','R','G',' ')}},	/* Aragonese */
--  {"ang",	{HB_TAG('A','N','G',' ')}},	/* Old English (ca. 450-1100) -> Anglo-Saxon */
--  {"apc",	{HB_TAG('A','R','A',' ')}},	/* North Levantine Arabic -> Arabic */
--  {"apd",	{HB_TAG('A','R','A',' ')}},	/* Sudanese Arabic -> Arabic */
--  {"apj",	{HB_TAG('A','T','H',' ')}},	/* Jicarilla Apache -> Athapaskan */
--  {"apk",	{HB_TAG('A','T','H',' ')}},	/* Kiowa Apache -> Athapaskan */
--  {"apl",	{HB_TAG('A','T','H',' ')}},	/* Lipan Apache -> Athapaskan */
--  {"apm",	{HB_TAG('A','T','H',' ')}},	/* Mescalero-Chiricahua Apache -> Athapaskan */
--  {"apw",	{HB_TAG('A','T','H',' ')}},	/* Western Apache -> Athapaskan */
--  {"ar",	{HB_TAG('A','R','A',' ')}},	/* Arabic [macrolanguage] */
--  {"arb",	{HB_TAG('A','R','A',' ')}},	/* Standard Arabic -> Arabic */
--  {"arn",	{HB_TAG('M','A','P',' ')}},	/* Mapudungun */
--  {"arq",	{HB_TAG('A','R','A',' ')}},	/* Algerian Arabic -> Arabic */
--  {"ars",	{HB_TAG('A','R','A',' ')}},	/* Najdi Arabic -> Arabic */
--  {"ary",	{HB_TAG('M','O','R',' ')}},	/* Moroccan Arabic -> Moroccan */
--  {"arz",	{HB_TAG('A','R','A',' ')}},	/* Egyptian Arabic -> Arabic */
--  {"as",	{HB_TAG('A','S','M',' ')}},	/* Assamese */
--  {"ast",	{HB_TAG('A','S','T',' ')}},	/* Asturian */
--  {"ath",	{HB_TAG('A','T','H',' ')}},	/* Athapascan [family] -> Athapaskan */
--  {"atj",	{HB_TAG('R','C','R',' ')}},	/* Atikamekw -> R-Cree */
--  {"atv",	{HB_TAG('A','L','T',' ')}},	/* Northern Altai -> Altai */
--  {"auz",	{HB_TAG('A','R','A',' ')}},	/* Uzbeki Arabic -> Arabic */
--  {"av",	{HB_TAG('A','V','R',' ')}},	/* Avaric -> Avar */
--  {"avl",	{HB_TAG('A','R','A',' ')}},	/* Eastern Egyptian Bedawi Arabic -> Arabic */
--  {"awa",	{HB_TAG('A','W','A',' ')}},	/* Awadhi */
--  {"ay",	{HB_TAG('A','Y','M',' ')}},	/* Aymara [macrolanguage] */
--  {"ayc",	{HB_TAG('A','Y','M',' ')}},	/* Southern Aymara -> Aymara */
--  {"ayh",	{HB_TAG('A','R','A',' ')}},	/* Hadrami Arabic -> Arabic */
--  {"ayl",	{HB_TAG('A','R','A',' ')}},	/* Libyan Arabic -> Arabic */
--  {"ayn",	{HB_TAG('A','R','A',' ')}},	/* Sanaani Arabic -> Arabic */
--  {"ayp",	{HB_TAG('A','R','A',' ')}},	/* North Mesopotamian Arabic -> Arabic */
--  {"ayr",	{HB_TAG('A','Y','M',' ')}},	/* Central Aymara -> Aymara */
--  {"az",	{HB_TAG('A','Z','E',' ')}},	/* Azerbaijani [macrolanguage] */
--  {"azb",	{HB_TAG('A','Z','B',' ')}},	/* South Azerbaijani -> Torki */
--  {"azj",	{HB_TAG('A','Z','E',' ')}},	/* North Azerbaijani -> Azerbaijani */
--  {"ba",	{HB_TAG('B','S','H',' ')}},	/* Bashkir */
--  {"bad",	{HB_TAG('B','A','D','0')}},	/* Banda [family] */
--  {"bai",	{HB_TAG('B','M','L',' ')}},	/* Bamileke [family] */
--  {"bal",	{HB_TAG('B','L','I',' ')}},	/* Baluchi [macrolanguage] */
--  {"ban",	{HB_TAG('B','A','N',' ')}},	/* Balinese */
--  {"bar",	{HB_TAG('B','A','R',' ')}},	/* Bavarian */
--  {"bbc",	{HB_TAG('B','B','C',' ')}},	/* Batak Toba */
--  {"bbz",	{HB_TAG('A','R','A',' ')}},	/* Babalia Creole Arabic -> Arabic */
--  {"bcc",	{HB_TAG('B','L','I',' ')}},	/* Southern Balochi -> Baluchi */
--  {"bci",	{HB_TAG('B','A','U',' ')}},	/* Baoulé -> Baulé */
--  {"bcl",	{HB_TAG('B','I','K',' ')}},	/* Central Bikol -> Bikol */
--  {"bcq",	{HB_TAG('B','C','H',' ')}},	/* Bench */
--  {"bcr",	{HB_TAG('A','T','H',' ')}},	/* Babine -> Athapaskan */
--  {"bdy",	{HB_TAG('B','D','Y',' ')}},	/* Bandjalang */
--  {"be",	{HB_TAG('B','E','L',' ')}},	/* Belarusian -> Belarussian */
--  {"bea",	{HB_TAG('A','T','H',' ')}},	/* Beaver -> Athapaskan */
--  {"beb",	{HB_TAG('B','T','I',' ')}},	/* Bebele -> Beti */
--  {"bem",	{HB_TAG('B','E','M',' ')}},	/* Bemba (Zambia) */
--  {"ber",	{HB_TAG('B','B','R',' ')}},	/* Berber [family] */
--  {"bfq",	{HB_TAG('B','A','D',' ')}},	/* Badaga */
--  {"bft",	{HB_TAG('B','L','T',' ')}},	/* Balti */
--  {"bfu",	{HB_TAG('L','A','H',' ')}},	/* Gahri -> Lahuli */
--  {"bfy",	{HB_TAG('B','A','G',' ')}},	/* Bagheli -> Baghelkhandi */
--  {"bg",	{HB_TAG('B','G','R',' ')}},	/* Bulgarian */
--  {"bgc",	{HB_TAG('B','G','C',' ')}},	/* Haryanvi */
--  {"bgn",	{HB_TAG('B','L','I',' ')}},	/* Western Balochi -> Baluchi */
--  {"bgp",	{HB_TAG('B','L','I',' ')}},	/* Eastern Balochi -> Baluchi */
--  {"bgq",	{HB_TAG('B','G','Q',' ')}},	/* Bagri */
--  {"bgr",	{HB_TAG('Q','I','N',' ')}},	/* Bawm Chin -> Chin */
--  {"bhb",	{HB_TAG('B','H','I',' ')}},	/* Bhili */
--  {"bhi",	{HB_TAG('B','H','I',' ')}},	/* Bhilali -> Bhili */
--  {"bhk",	{HB_TAG('B','I','K',' ')}},	/* Albay Bicolano (retired code) -> Bikol */
--  {"bho",	{HB_TAG('B','H','O',' ')}},	/* Bhojpuri */
--  {"bhr",	{HB_TAG('M','L','G',' ')}},	/* Bara Malagasy -> Malagasy */
--  {"bi",	{HB_TAG('B','I','S',' ')}},	/* Bislama */
--  {"bik",	{HB_TAG('B','I','K',' ')}},	/* Bikol [macrolanguage] */
--  {"bin",	{HB_TAG('E','D','O',' ')}},	/* Edo */
--  {"bjj",	{HB_TAG('B','J','J',' ')}},	/* Kanauji */
--  {"bjn",	{HB_TAG('M','L','Y',' ')}},	/* Banjar -> Malay */
--  {"bjq",	{HB_TAG('M','L','G',' ')}},	/* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
--  {"bjt",	{HB_TAG('B','L','N',' ')}},	/* Balanta-Ganja -> Balante */
--  {"bla",	{HB_TAG('B','K','F',' ')}},	/* Siksika -> Blackfoot */
--  {"ble",	{HB_TAG('B','L','N',' ')}},	/* Balanta-Kentohe -> Balante */
--  {"blk",	{HB_TAG('B','L','K',' ')}},	/* Pa’o Karen */
--  {"bln",	{HB_TAG('B','I','K',' ')}},	/* Southern Catanduanes Bikol -> Bikol */
--  {"bm",	{HB_TAG('B','M','B',' ')}},	/* Bambara (Bamanankan) */
--  {"bmm",	{HB_TAG('M','L','G',' ')}},	/* Northern Betsimisaraka Malagasy -> Malagasy */
--  {"bn",	{HB_TAG('B','E','N',' ')}},	/* Bengali */
--  {"bo",	{HB_TAG('T','I','B',' ')}},	/* Tibetan */
--  {"bpy",	{HB_TAG('B','P','Y',' ')}},	/* Bishnupriya -> Bishnupriya Manipuri */
--  {"bqi",	{HB_TAG('L','R','C',' ')}},	/* Bakhtiari -> Luri */
--  {"br",	{HB_TAG('B','R','E',' ')}},	/* Breton */
--  {"bra",	{HB_TAG('B','R','I',' ')}},	/* Braj -> Braj Bhasha */
--  {"brh",	{HB_TAG('B','R','H',' ')}},	/* Brahui */
--  {"brx",	{HB_TAG('B','R','X',' ')}},	/* Bodo (India) */
--  {"bs",	{HB_TAG('B','O','S',' ')}},	/* Bosnian */
--  {"bsk",	{HB_TAG('B','S','K',' ')}},	/* Burushaski */
--  {"btb",	{HB_TAG('B','T','I',' ')}},	/* Beti (Cameroon) (retired code) */
--  {"btj",	{HB_TAG('M','L','Y',' ')}},	/* Bacanese Malay -> Malay */
--  {"bto",	{HB_TAG('B','I','K',' ')}},	/* Rinconada Bikol -> Bikol */
--  {"bts",	{HB_TAG('B','T','S',' ')}},	/* Batak Simalungun */
--  {"bug",	{HB_TAG('B','U','G',' ')}},	/* Buginese -> Bugis */
--  {"bum",	{HB_TAG('B','T','I',' ')}},	/* Bulu (Cameroon) -> Beti */
--  {"bve",	{HB_TAG('M','L','Y',' ')}},	/* Berau Malay -> Malay */
--  {"bvu",	{HB_TAG('M','L','Y',' ')}},	/* Bukit Malay -> Malay */
--  {"bxk",	{HB_TAG('L','U','H',' ')}},	/* Bukusu -> Luyia */
--  {"bxp",	{HB_TAG('B','T','I',' ')}},	/* Bebil -> Beti */
--  {"bxr",	{HB_TAG('R','B','U',' ')}},	/* Russia Buriat -> Russian Buriat */
--  {"byn",	{HB_TAG('B','I','L',' ')}},	/* Bilin -> Bilen */
--  {"byv",	{HB_TAG('B','Y','V',' ')}},	/* Medumba */
--  {"bzc",	{HB_TAG('M','L','G',' ')}},	/* Southern Betsimisaraka Malagasy -> Malagasy */
--  {"ca",	{HB_TAG('C','A','T',' ')}},	/* Catalan */
--  {"caf",	{HB_TAG('C','R','R',' '),	/* Southern Carrier -> Carrier */
--		 HB_TAG('A','T','H',' ')}},	/* Southern Carrier -> Athapaskan */
--  {"cak",	{HB_TAG('C','A','K',' ')}},	/* Kaqchikel */
--  {"cbk",	{HB_TAG('C','B','K',' ')}},	/* Chavacano -> Zamboanga Chavacano */
--  {"cbl",	{HB_TAG('Q','I','N',' ')}},	/* Bualkhaw Chin -> Chin */
--  {"cco",	{HB_TAG('C','C','H','N')}},	/* Comaltepec Chinantec -> Chinantec */
--  {"ccq",	{HB_TAG('A','R','K',' ')}},	/* Chaungtha (retired code) -> Rakhine */
--  {"cdo",	{HB_TAG('Z','H','S',' ')}},	/* Min Dong Chinese -> Chinese Simplified */
--  {"ce",	{HB_TAG('C','H','E',' ')}},	/* Chechen */
--  {"ceb",	{HB_TAG('C','E','B',' ')}},	/* Cebuano */
--  {"cfm",	{HB_TAG('H','A','L',' ')}},	/* Halam (Falam Chin) */
--  {"cgg",	{HB_TAG('C','G','G',' ')}},	/* Chiga */
--  {"ch",	{HB_TAG('C','H','A',' ')}},	/* Chamorro */
--  {"chj",	{HB_TAG('C','C','H','N')}},	/* Ojitlán Chinantec -> Chinantec */
--  {"chk",	{HB_TAG('C','H','K','0')}},	/* Chuukese */
--  {"cho",	{HB_TAG('C','H','O',' ')}},	/* Choctaw */
--  {"chp",	{HB_TAG('C','H','P',' '),	/* Chipewyan */
--		 HB_TAG('S','A','Y',' '),	/* Chipewyan -> Sayisi */
--		 HB_TAG('A','T','H',' ')}},	/* Chipewyan -> Athapaskan */
--  {"chq",	{HB_TAG('C','C','H','N')}},	/* Quiotepec Chinantec -> Chinantec */
--  {"chr",	{HB_TAG('C','H','R',' ')}},	/* Cherokee */
--  {"chy",	{HB_TAG('C','H','Y',' ')}},	/* Cheyenne */
--  {"chz",	{HB_TAG('C','C','H','N')}},	/* Ozumacín Chinantec -> Chinantec */
--  {"ciw",	{HB_TAG('O','J','B',' ')}},	/* Chippewa -> Ojibway */
--  {"cja",	{HB_TAG('C','J','A',' ')}},	/* Western Cham */
--  {"cjm",	{HB_TAG('C','J','M',' ')}},	/* Eastern Cham */
--  {"cjy",	{HB_TAG('Z','H','S',' ')}},	/* Jinyu Chinese -> Chinese Simplified */
--  {"cka",	{HB_TAG('Q','I','N',' ')}},	/* Khumi Awa Chin (retired code) -> Chin */
--  {"ckb",	{HB_TAG('K','U','R',' ')}},	/* Central Kurdish -> Kurdish */
--  {"ckt",	{HB_TAG('C','H','K',' ')}},	/* Chukot -> Chukchi */
--  {"clc",	{HB_TAG('A','T','H',' ')}},	/* Chilcotin -> Athapaskan */
--  {"cld",	{HB_TAG('S','Y','R',' ')}},	/* Chaldean Neo-Aramaic -> Syriac */
--  {"cle",	{HB_TAG('C','C','H','N')}},	/* Lealao Chinantec -> Chinantec */
--  {"cmn",	{HB_TAG('Z','H','S',' ')}},	/* Mandarin Chinese -> Chinese Simplified */
--  {"cmr",	{HB_TAG('Q','I','N',' ')}},	/* Mro-Khimi Chin -> Chin */
--  {"cnb",	{HB_TAG('Q','I','N',' ')}},	/* Chinbon Chin -> Chin */
--  {"cnh",	{HB_TAG('Q','I','N',' ')}},	/* Hakha Chin -> Chin */
--  {"cnk",	{HB_TAG('Q','I','N',' ')}},	/* Khumi Chin -> Chin */
--  {"cnl",	{HB_TAG('C','C','H','N')}},	/* Lalana Chinantec -> Chinantec */
--  {"cnt",	{HB_TAG('C','C','H','N')}},	/* Tepetotutla Chinantec -> Chinantec */
--  {"cnw",	{HB_TAG('Q','I','N',' ')}},	/* Ngawn Chin -> Chin */
--  {"co",	{HB_TAG('C','O','S',' ')}},	/* Corsican */
--  {"coa",	{HB_TAG('M','L','Y',' ')}},	/* Cocos Islands Malay -> Malay */
--  {"cop",	{HB_TAG('C','O','P',' ')}},	/* Coptic */
--  {"coq",	{HB_TAG('A','T','H',' ')}},	/* Coquille -> Athapaskan */
--  {"cpa",	{HB_TAG('C','C','H','N')}},	/* Palantla Chinantec -> Chinantec */
--  {"cpe",	{HB_TAG('C','P','P',' ')}},	/* English-based creoles and pidgins [family] -> Creoles */
--  {"cpf",	{HB_TAG('C','P','P',' ')}},	/* French-based creoles and pidgins [family] -> Creoles */
--  {"cpp",	{HB_TAG('C','P','P',' ')}},	/* Portuguese-based creoles and pidgins [family] -> Creoles */
--  {"cpx",	{HB_TAG('Z','H','S',' ')}},	/* Pu-Xian Chinese -> Chinese Simplified */
--  {"cqd",	{HB_TAG('H','M','N',' ')}},	/* Chuanqiandian Cluster Miao -> Hmong */
--  {"cqu",	{HB_TAG('Q','U','H',' ')}},	/* Chilean Quechua (retired code) -> Quechua (Bolivia) */
--  {"cr",	{HB_TAG('C','R','E',' '),	/* Cree [macrolanguage] */
--		 HB_TAG('Y','C','R',' ')}},	/* Cree [macrolanguage] -> Y-Cree */
--  {"crh",	{HB_TAG('C','R','T',' ')}},	/* Crimean Tatar */
--  {"crj",	{HB_TAG('E','C','R',' ')}},	/* Southern East Cree -> Eastern Cree */
--  {"crk",	{HB_TAG('W','C','R',' ')}},	/* Plains Cree -> West-Cree */
--  {"crl",	{HB_TAG('E','C','R',' ')}},	/* Northern East Cree -> Eastern Cree */
--  {"crm",	{HB_TAG('M','C','R',' '),	/* Moose Cree */
--		 HB_TAG('L','C','R',' ')}},	/* Moose Cree -> L-Cree */
--  {"crp",	{HB_TAG('C','P','P',' ')}},	/* Creoles and pidgins [family] -> Creoles */
--  {"crx",	{HB_TAG('C','R','R',' '),	/* Carrier */
--		 HB_TAG('A','T','H',' ')}},	/* Carrier -> Athapaskan */
--  {"cs",	{HB_TAG('C','S','Y',' ')}},	/* Czech */
--  {"csa",	{HB_TAG('C','C','H','N')}},	/* Chiltepec Chinantec -> Chinantec */
--  {"csb",	{HB_TAG('C','S','B',' ')}},	/* Kashubian */
--  {"csh",	{HB_TAG('Q','I','N',' ')}},	/* Asho Chin -> Chin */
--  {"cso",	{HB_TAG('C','C','H','N')}},	/* Sochiapam Chinantec -> Chinantec */
--  {"csw",	{HB_TAG('N','C','R',' '),	/* Swampy Cree -> N-Cree */
--		 HB_TAG('N','H','C',' ')}},	/* Swampy Cree -> Norway House Cree */
--  {"csy",	{HB_TAG('Q','I','N',' ')}},	/* Siyin Chin -> Chin */
--  {"ctc",	{HB_TAG('A','T','H',' ')}},	/* Chetco -> Athapaskan */
--  {"ctd",	{HB_TAG('Q','I','N',' ')}},	/* Tedim Chin -> Chin */
--  {"cte",	{HB_TAG('C','C','H','N')}},	/* Tepinapa Chinantec -> Chinantec */
--  {"ctg",	{HB_TAG('C','T','G',' ')}},	/* Chittagonian */
--  {"ctl",	{HB_TAG('C','C','H','N')}},	/* Tlacoatzintepec Chinantec -> Chinantec */
--  {"cts",	{HB_TAG('B','I','K',' ')}},	/* Northern Catanduanes Bikol -> Bikol */
--  {"cu",	{HB_TAG('C','S','L',' ')}},	/* Church Slavonic */
--  {"cuc",	{HB_TAG('C','C','H','N')}},	/* Usila Chinantec -> Chinantec */
--  {"cuk",	{HB_TAG('C','U','K',' ')}},	/* San Blas Kuna */
--  {"cv",	{HB_TAG('C','H','U',' ')}},	/* Chuvash */
--  {"cvn",	{HB_TAG('C','C','H','N')}},	/* Valle Nacional Chinantec -> Chinantec */
--  {"cwd",	{HB_TAG('D','C','R',' '),	/* Woods Cree */
--		 HB_TAG('T','C','R',' ')}},	/* Woods Cree -> TH-Cree */
--  {"cy",	{HB_TAG('W','E','L',' ')}},	/* Welsh */
--  {"czh",	{HB_TAG('Z','H','S',' ')}},	/* Huizhou Chinese -> Chinese Simplified */
--  {"czo",	{HB_TAG('Z','H','S',' ')}},	/* Min Zhong Chinese -> Chinese Simplified */
--  {"czt",	{HB_TAG('Q','I','N',' ')}},	/* Zotung Chin -> Chin */
--  {"da",	{HB_TAG('D','A','N',' ')}},	/* Danish */
--  {"dao",	{HB_TAG('Q','I','N',' ')}},	/* Daai Chin -> Chin */
--  {"dap",	{HB_TAG('N','I','S',' ')}},	/* Nisi (India) (retired code) */
--  {"dar",	{HB_TAG('D','A','R',' ')}},	/* Dargwa */
--  {"dax",	{HB_TAG('D','A','X',' ')}},	/* Dayi */
--  {"de",	{HB_TAG('D','E','U',' ')}},	/* German */
--  {"den",	{HB_TAG('S','L','A',' '),	/* Slave (Athapascan) [macrolanguage] -> Slavey */
--		 HB_TAG('A','T','H',' ')}},	/* Slave (Athapascan) [macrolanguage] -> Athapaskan */
--  {"dgo",	{HB_TAG('D','G','O',' ')}},	/* Dogri */
--  {"dgr",	{HB_TAG('A','T','H',' ')}},	/* Dogrib -> Athapaskan */
--  {"dhd",	{HB_TAG('M','A','W',' ')}},	/* Dhundari -> Marwari */
--  {"dhg",	{HB_TAG('D','H','G',' ')}},	/* Dhangu */
--  {"dib",	{HB_TAG('D','N','K',' ')}},	/* South Central Dinka -> Dinka */
--  {"dik",	{HB_TAG('D','N','K',' ')}},	/* Southwestern Dinka -> Dinka */
--  {"din",	{HB_TAG('D','N','K',' ')}},	/* Dinka [macrolanguage] */
--  {"dip",	{HB_TAG('D','N','K',' ')}},	/* Northeastern Dinka -> Dinka */
--  {"diq",	{HB_TAG('D','I','Q',' ')}},	/* Dimli */
--  {"diw",	{HB_TAG('D','N','K',' ')}},	/* Northwestern Dinka -> Dinka */
--  {"dje",	{HB_TAG('D','J','R',' ')}},	/* Zarma */
--  {"djr",	{HB_TAG('D','J','R','0')}},	/* Djambarrpuyngu */
--  {"dks",	{HB_TAG('D','N','K',' ')}},	/* Southeastern Dinka -> Dinka */
--  {"dng",	{HB_TAG('D','U','N',' ')}},	/* Dungan */
--  {"dnj",	{HB_TAG('D','N','J',' ')}},	/* Dan */
--  {"doi",	{HB_TAG('D','G','R',' ')}},	/* Dogri [macrolanguage] */
--  {"drh",	{HB_TAG('M','N','G',' ')}},	/* Darkhat (retired code) -> Mongolian */
--  {"drw",	{HB_TAG('D','R','I',' ')}},	/* Darwazi (retired code) -> Dari */
--  {"dsb",	{HB_TAG('L','S','B',' ')}},	/* Lower Sorbian */
--  {"dty",	{HB_TAG('N','E','P',' ')}},	/* Dotyali -> Nepali */
--  {"duj",	{HB_TAG('D','U','J',' ')}},	/* Dhuwal (retired code) */
--  {"dup",	{HB_TAG('M','L','Y',' ')}},	/* Duano -> Malay */
--  {"dv",	{HB_TAG('D','I','V',' '),	/* Divehi (Dhivehi, Maldivian) */
--		 HB_TAG('D','H','V',' ')}},	/* Divehi (Dhivehi, Maldivian) (deprecated) */
--  {"dwu",	{HB_TAG('D','U','J',' ')}},	/* Dhuwal */
--  {"dwy",	{HB_TAG('D','U','J',' ')}},	/* Dhuwaya -> Dhuwal */
--  {"dyu",	{HB_TAG('J','U','L',' ')}},	/* Dyula -> Jula */
--  {"dz",	{HB_TAG('D','Z','N',' ')}},	/* Dzongkha */
--  {"ee",	{HB_TAG('E','W','E',' ')}},	/* Ewe */
--  {"efi",	{HB_TAG('E','F','I',' ')}},	/* Efik */
--  {"ekk",	{HB_TAG('E','T','I',' ')}},	/* Standard Estonian -> Estonian */
--  {"el",	{HB_TAG('E','L','L',' ')}},	/* Modern Greek (1453-) -> Greek */
--  {"emk",	{HB_TAG('E','M','K',' '),	/* Eastern Maninkakan */
--		 HB_TAG('M','N','K',' ')}},	/* Eastern Maninkakan -> Maninka */
--  {"en",	{HB_TAG('E','N','G',' ')}},	/* English */
--  {"enb",	{HB_TAG('K','A','L',' ')}},	/* Markweeta -> Kalenjin */
--  {"enf",	{HB_TAG('F','N','E',' ')}},	/* Forest Enets -> Forest Nenets */
--  {"enh",	{HB_TAG('T','N','E',' ')}},	/* Tundra Enets -> Tundra Nenets */
--  {"eo",	{HB_TAG('N','T','O',' ')}},	/* Esperanto */
--  {"es",	{HB_TAG('E','S','P',' ')}},	/* Spanish */
--  {"esg",	{HB_TAG('G','O','N',' ')}},	/* Aheri Gondi -> Gondi */
--  {"esi",	{HB_TAG('I','P','K',' ')}},	/* North Alaskan Inupiatun -> Inupiat */
--  {"esk",	{HB_TAG('I','P','K',' ')}},	/* Northwest Alaska Inupiatun -> Inupiat */
--  {"esu",	{HB_TAG('E','S','U',' ')}},	/* Central Yupik */
--  {"et",	{HB_TAG('E','T','I',' ')}},	/* Estonian [macrolanguage] */
--  {"eto",	{HB_TAG('B','T','I',' ')}},	/* Eton (Cameroon) -> Beti */
--  {"eu",	{HB_TAG('E','U','Q',' ')}},	/* Basque */
--  {"eve",	{HB_TAG('E','V','N',' ')}},	/* Even */
--  {"evn",	{HB_TAG('E','V','K',' ')}},	/* Evenki */
--  {"ewo",	{HB_TAG('B','T','I',' ')}},	/* Ewondo -> Beti */
--  {"eyo",	{HB_TAG('K','A','L',' ')}},	/* Keiyo -> Kalenjin */
--  {"fa",	{HB_TAG('F','A','R',' ')}},	/* Persian [macrolanguage] */
--  {"fan",	{HB_TAG('F','A','N','0')}},	/* Fang (Equatorial Guinea) */
--  {"fat",	{HB_TAG('F','A','T',' ')}},	/* Fanti */
--  {"fbl",	{HB_TAG('B','I','K',' ')}},	/* West Albay Bikol -> Bikol */
--  {"ff",	{HB_TAG('F','U','L',' ')}},	/* Fulah [macrolanguage] */
--  {"ffm",	{HB_TAG('F','U','L',' ')}},	/* Maasina Fulfulde -> Fulah */
--  {"fi",	{HB_TAG('F','I','N',' ')}},	/* Finnish */
--  {"fil",	{HB_TAG('P','I','L',' ')}},	/* Filipino */
--  {"fj",	{HB_TAG('F','J','I',' ')}},	/* Fijian */
--  {"flm",	{HB_TAG('H','A','L',' '),	/* Halam (Falam Chin) (retired code) */
--		 HB_TAG('Q','I','N',' ')}},	/* Falam Chin (retired code) -> Chin */
--  {"fmp",	{HB_TAG('F','M','P',' ')}},	/* Fe’fe’ */
--  {"fo",	{HB_TAG('F','O','S',' ')}},	/* Faroese */
--  {"fon",	{HB_TAG('F','O','N',' ')}},	/* Fon */
--  {"fr",	{HB_TAG('F','R','A',' ')}},	/* French */
--  {"frc",	{HB_TAG('F','R','C',' ')}},	/* Cajun French */
--  {"frp",	{HB_TAG('F','R','P',' ')}},	/* Arpitan */
--  {"fub",	{HB_TAG('F','U','L',' ')}},	/* Adamawa Fulfulde -> Fulah */
--  {"fuc",	{HB_TAG('F','U','L',' ')}},	/* Pulaar -> Fulah */
--  {"fue",	{HB_TAG('F','U','L',' ')}},	/* Borgu Fulfulde -> Fulah */
--  {"fuf",	{HB_TAG('F','T','A',' ')}},	/* Pular -> Futa */
--  {"fuh",	{HB_TAG('F','U','L',' ')}},	/* Western Niger Fulfulde -> Fulah */
--  {"fui",	{HB_TAG('F','U','L',' ')}},	/* Bagirmi Fulfulde -> Fulah */
--  {"fuq",	{HB_TAG('F','U','L',' ')}},	/* Central-Eastern Niger Fulfulde -> Fulah */
--  {"fur",	{HB_TAG('F','R','L',' ')}},	/* Friulian */
--  {"fuv",	{HB_TAG('F','U','V',' ')}},	/* Nigerian Fulfulde */
--  {"fy",	{HB_TAG('F','R','I',' ')}},	/* Western Frisian -> Frisian */
--  {"ga",	{HB_TAG('I','R','I',' ')}},	/* Irish */
--  {"gaa",	{HB_TAG('G','A','D',' ')}},	/* Ga */
--  {"gag",	{HB_TAG('G','A','G',' ')}},	/* Gagauz */
--  {"gan",	{HB_TAG('Z','H','S',' ')}},	/* Gan Chinese -> Chinese Simplified */
--  {"gax",	{HB_TAG('O','R','O',' ')}},	/* Borana-Arsi-Guji Oromo -> Oromo */
--  {"gaz",	{HB_TAG('O','R','O',' ')}},	/* West Central Oromo -> Oromo */
--  {"gbm",	{HB_TAG('G','A','W',' ')}},	/* Garhwali */
--  {"gce",	{HB_TAG('A','T','H',' ')}},	/* Galice -> Athapaskan */
--  {"gd",	{HB_TAG('G','A','E',' ')}},	/* Scottish Gaelic (Gaelic) */
--  {"gda",	{HB_TAG('R','A','J',' ')}},	/* Gade Lohar -> Rajasthani */
--  {"gez",	{HB_TAG('G','E','Z',' ')}},	/* Geez */
--  {"ggo",	{HB_TAG('G','O','N',' ')}},	/* Southern Gondi (retired code) -> Gondi */
--  {"gih",	{HB_TAG('G','I','H',' ')}},	/* Githabul */
--  {"gil",	{HB_TAG('G','I','L','0')}},	/* Kiribati (Gilbertese) */
--  {"gju",	{HB_TAG('R','A','J',' ')}},	/* Gujari -> Rajasthani */
--  {"gkp",	{HB_TAG('G','K','P',' ')}},	/* Guinea Kpelle -> Kpelle (Guinea) */
--  {"gl",	{HB_TAG('G','A','L',' ')}},	/* Galician */
--  {"gld",	{HB_TAG('N','A','N',' ')}},	/* Nanai */
--  {"glk",	{HB_TAG('G','L','K',' ')}},	/* Gilaki */
--  {"gn",	{HB_TAG('G','U','A',' ')}},	/* Guarani [macrolanguage] */
--  {"gnn",	{HB_TAG('G','N','N',' ')}},	/* Gumatj */
--  {"gno",	{HB_TAG('G','O','N',' ')}},	/* Northern Gondi -> Gondi */
--  {"gnw",	{HB_TAG('G','U','A',' ')}},	/* Western Bolivian Guaraní -> Guarani */
--  {"gog",	{HB_TAG('G','O','G',' ')}},	/* Gogo */
--  {"gom",	{HB_TAG('K','O','K',' ')}},	/* Goan Konkani -> Konkani */
--  {"gon",	{HB_TAG('G','O','N',' ')}},	/* Gondi [macrolanguage] */
--  {"grt",	{HB_TAG('G','R','O',' ')}},	/* Garo */
--  {"gru",	{HB_TAG('S','O','G',' ')}},	/* Kistane -> Sodo Gurage */
--  {"gsw",	{HB_TAG('A','L','S',' ')}},	/* Alsatian */
--  {"gu",	{HB_TAG('G','U','J',' ')}},	/* Gujarati */
--  {"guc",	{HB_TAG('G','U','C',' ')}},	/* Wayuu */
--  {"guf",	{HB_TAG('G','U','F',' ')}},	/* Gupapuyngu */
--  {"gug",	{HB_TAG('G','U','A',' ')}},	/* Paraguayan Guaraní -> Guarani */
--  {"gui",	{HB_TAG('G','U','A',' ')}},	/* Eastern Bolivian Guaraní -> Guarani */
--  {"guk",	{HB_TAG('G','M','Z',' '),	/* Gumuz */
--		 HB_TAG('G','U','K',' ')}},	/* Gumuz (SIL fonts) */
--  {"gun",	{HB_TAG('G','U','A',' ')}},	/* Mbyá Guaraní -> Guarani */
--  {"guz",	{HB_TAG('G','U','Z',' ')}},	/* Gusii */
--  {"gv",	{HB_TAG('M','N','X',' ')}},	/* Manx */
--  {"gwi",	{HB_TAG('A','T','H',' ')}},	/* Gwichʼin -> Athapaskan */
--  {"ha",	{HB_TAG('H','A','U',' ')}},	/* Hausa */
--  {"haa",	{HB_TAG('A','T','H',' ')}},	/* Han -> Athapaskan */
--  {"hae",	{HB_TAG('O','R','O',' ')}},	/* Eastern Oromo -> Oromo */
--  {"hak",	{HB_TAG('Z','H','S',' ')}},	/* Hakka Chinese -> Chinese Simplified */
--  {"har",	{HB_TAG('H','R','I',' ')}},	/* Harari */
--  {"haw",	{HB_TAG('H','A','W',' ')}},	/* Hawaiian */
--  {"hay",	{HB_TAG('H','A','Y',' ')}},	/* Haya */
--  {"haz",	{HB_TAG('H','A','Z',' ')}},	/* Hazaragi */
--  {"he",	{HB_TAG('I','W','R',' ')}},	/* Hebrew */
--  {"hea",	{HB_TAG('H','M','N',' ')}},	/* Northern Qiandong Miao -> Hmong */
--  {"hi",	{HB_TAG('H','I','N',' ')}},	/* Hindi */
--  {"hil",	{HB_TAG('H','I','L',' ')}},	/* Hiligaynon */
--  {"hji",	{HB_TAG('M','L','Y',' ')}},	/* Haji -> Malay */
--  {"hlt",	{HB_TAG('Q','I','N',' ')}},	/* Matu Chin -> Chin */
--  {"hma",	{HB_TAG('H','M','N',' ')}},	/* Southern Mashan Hmong -> Hmong */
--  {"hmc",	{HB_TAG('H','M','N',' ')}},	/* Central Huishui Hmong -> Hmong */
--  {"hmd",	{HB_TAG('H','M','N',' ')}},	/* Large Flowery Miao -> Hmong */
--  {"hme",	{HB_TAG('H','M','N',' ')}},	/* Eastern Huishui Hmong -> Hmong */
--  {"hmg",	{HB_TAG('H','M','N',' ')}},	/* Southwestern Guiyang Hmong -> Hmong */
--  {"hmh",	{HB_TAG('H','M','N',' ')}},	/* Southwestern Huishui Hmong -> Hmong */
--  {"hmi",	{HB_TAG('H','M','N',' ')}},	/* Northern Huishui Hmong -> Hmong */
--  {"hmj",	{HB_TAG('H','M','N',' ')}},	/* Ge -> Hmong */
--  {"hml",	{HB_TAG('H','M','N',' ')}},	/* Luopohe Hmong -> Hmong */
--  {"hmm",	{HB_TAG('H','M','N',' ')}},	/* Central Mashan Hmong -> Hmong */
--  {"hmn",	{HB_TAG('H','M','N',' ')}},	/* Hmong [macrolanguage] */
--  {"hmp",	{HB_TAG('H','M','N',' ')}},	/* Northern Mashan Hmong -> Hmong */
--  {"hmq",	{HB_TAG('H','M','N',' ')}},	/* Eastern Qiandong Miao -> Hmong */
--  {"hms",	{HB_TAG('H','M','N',' ')}},	/* Southern Qiandong Miao -> Hmong */
--  {"hmw",	{HB_TAG('H','M','N',' ')}},	/* Western Mashan Hmong -> Hmong */
--  {"hmy",	{HB_TAG('H','M','N',' ')}},	/* Southern Guiyang Hmong -> Hmong */
--  {"hmz",	{HB_TAG('H','M','N',' ')}},	/* Hmong Shua -> Hmong */
--  {"hnd",	{HB_TAG('H','N','D',' ')}},	/* Southern Hindko -> Hindko */
--  {"hne",	{HB_TAG('C','H','H',' ')}},	/* Chhattisgarhi -> Chattisgarhi */
--  {"hnj",	{HB_TAG('H','M','N',' ')}},	/* Hmong Njua -> Hmong */
--  {"hno",	{HB_TAG('H','N','D',' ')}},	/* Northern Hindko -> Hindko */
--  {"ho",	{HB_TAG('H','M','O',' ')}},	/* Hiri Motu */
--  {"hoc",	{HB_TAG('H','O',' ',' ')}},	/* Ho */
--  {"hoi",	{HB_TAG('A','T','H',' ')}},	/* Holikachuk -> Athapaskan */
--  {"hoj",	{HB_TAG('H','A','R',' ')}},	/* Hadothi -> Harauti */
--  {"hr",	{HB_TAG('H','R','V',' ')}},	/* Croatian */
--  {"hrm",	{HB_TAG('H','M','N',' ')}},	/* Horned Miao -> Hmong */
--  {"hsb",	{HB_TAG('U','S','B',' ')}},	/* Upper Sorbian */
--  {"hsn",	{HB_TAG('Z','H','S',' ')}},	/* Xiang Chinese -> Chinese Simplified */
--  {"ht",	{HB_TAG('H','A','I',' ')}},	/* Haitian (Haitian Creole) */
--  {"hu",	{HB_TAG('H','U','N',' ')}},	/* Hungarian */
--  {"huj",	{HB_TAG('H','M','N',' ')}},	/* Northern Guiyang Hmong -> Hmong */
--  {"hup",	{HB_TAG('A','T','H',' ')}},	/* Hupa -> Athapaskan */
--  {"hy",	{HB_TAG('H','Y','E','0'),	/* Armenian -> Armenian East */
--		 HB_TAG('H','Y','E',' ')}},	/* Armenian */
--  {"hyw",	{HB_TAG('H','Y','E',' ')}},	/* Western Armenian -> Armenian */
--  {"hz",	{HB_TAG('H','E','R',' ')}},	/* Herero */
--  {"ia",	{HB_TAG('I','N','A',' ')}},	/* Interlingua (International Auxiliary Language Association) */
--  {"iba",	{HB_TAG('I','B','A',' ')}},	/* Iban */
--  {"ibb",	{HB_TAG('I','B','B',' ')}},	/* Ibibio */
--  {"id",	{HB_TAG('I','N','D',' ')}},	/* Indonesian */
--  {"ida",	{HB_TAG('L','U','H',' ')}},	/* Idakho-Isukha-Tiriki -> Luyia */
--  {"ie",	{HB_TAG('I','L','E',' ')}},	/* Interlingue */
--  {"ig",	{HB_TAG('I','B','O',' ')}},	/* Igbo */
--  {"igb",	{HB_TAG('E','B','I',' ')}},	/* Ebira */
--  {"ii",	{HB_TAG('Y','I','M',' ')}},	/* Sichuan Yi -> Yi Modern */
--  {"ijc",	{HB_TAG('I','J','O',' ')}},	/* Izon -> Ijo */
--  {"ijo",	{HB_TAG('I','J','O',' ')}},	/* Ijo [family] */
--  {"ik",	{HB_TAG('I','P','K',' ')}},	/* Inupiaq [macrolanguage] -> Inupiat */
--  {"ike",	{HB_TAG('I','N','U',' ')}},	/* Eastern Canadian Inuktitut -> Inuktitut */
--  {"ikt",	{HB_TAG('I','N','U',' ')}},	/* Inuinnaqtun -> Inuktitut */
--  {"ilo",	{HB_TAG('I','L','O',' ')}},	/* Iloko -> Ilokano */
--  {"in",	{HB_TAG('I','N','D',' ')}},	/* Indonesian (retired code) */
--  {"ing",	{HB_TAG('A','T','H',' ')}},	/* Degexit'an -> Athapaskan */
--  {"inh",	{HB_TAG('I','N','G',' ')}},	/* Ingush */
--  {"io",	{HB_TAG('I','D','O',' ')}},	/* Ido */
--  {"is",	{HB_TAG('I','S','L',' ')}},	/* Icelandic */
--  {"it",	{HB_TAG('I','T','A',' ')}},	/* Italian */
--  {"iu",	{HB_TAG('I','N','U',' ')}},	/* Inuktitut [macrolanguage] */
--  {"iw",	{HB_TAG('I','W','R',' ')}},	/* Hebrew (retired code) */
--  {"ja",	{HB_TAG('J','A','N',' ')}},	/* Japanese */
--  {"jak",	{HB_TAG('M','L','Y',' ')}},	/* Jakun -> Malay */
--  {"jam",	{HB_TAG('J','A','M',' ')}},	/* Jamaican Creole English -> Jamaican Creole */
--  {"jax",	{HB_TAG('M','L','Y',' ')}},	/* Jambi Malay -> Malay */
--  {"jbo",	{HB_TAG('J','B','O',' ')}},	/* Lojban */
--  {"jct",	{HB_TAG('J','C','T',' ')}},	/* Krymchak */
--  {"ji",	{HB_TAG('J','I','I',' ')}},	/* Yiddish (retired code) */
--  {"jv",	{HB_TAG('J','A','V',' ')}},	/* Javanese */
--  {"jw",	{HB_TAG('J','A','V',' ')}},	/* Javanese (retired code) */
--  {"ka",	{HB_TAG('K','A','T',' ')}},	/* Georgian */
--  {"kaa",	{HB_TAG('K','R','K',' ')}},	/* Kara-Kalpak -> Karakalpak */
--  {"kab",	{HB_TAG('K','A','B','0')}},	/* Kabyle */
--  {"kam",	{HB_TAG('K','M','B',' ')}},	/* Kamba (Kenya) */
--  {"kar",	{HB_TAG('K','R','N',' ')}},	/* Karen [family] */
--  {"kbd",	{HB_TAG('K','A','B',' ')}},	/* Kabardian */
--  {"kby",	{HB_TAG('K','N','R',' ')}},	/* Manga Kanuri -> Kanuri */
--  {"kca",	{HB_TAG('K','H','K',' '),	/* Khanty -> Khanty-Kazim */
--		 HB_TAG('K','H','S',' '),	/* Khanty -> Khanty-Shurishkar */
--		 HB_TAG('K','H','V',' ')}},	/* Khanty -> Khanty-Vakhi */
--  {"kde",	{HB_TAG('K','D','E',' ')}},	/* Makonde */
--  {"kdr",	{HB_TAG('K','R','M',' ')}},	/* Karaim */
--  {"kdt",	{HB_TAG('K','U','Y',' ')}},	/* Kuy */
--  {"kea",	{HB_TAG('K','E','A',' ')}},	/* Kabuverdianu (Crioulo) */
--  {"kek",	{HB_TAG('K','E','K',' ')}},	/* Kekchi */
--  {"kex",	{HB_TAG('K','K','N',' ')}},	/* Kukna -> Kokni */
--  {"kfa",	{HB_TAG('K','O','D',' ')}},	/* Kodava -> Kodagu */
--  {"kfr",	{HB_TAG('K','A','C',' ')}},	/* Kachhi -> Kachchi */
--  {"kfx",	{HB_TAG('K','U','L',' ')}},	/* Kullu Pahari -> Kulvi */
--  {"kfy",	{HB_TAG('K','M','N',' ')}},	/* Kumaoni */
--  {"kg",	{HB_TAG('K','O','N','0')}},	/* Kongo [macrolanguage] */
--  {"kha",	{HB_TAG('K','S','I',' ')}},	/* Khasi */
--  {"khb",	{HB_TAG('X','B','D',' ')}},	/* Lü */
--  {"khk",	{HB_TAG('M','N','G',' ')}},	/* Halh Mongolian -> Mongolian */
--  {"kht",	{HB_TAG('K','H','N',' '),	/* Khamti -> Khamti Shan (Microsoft fonts) */
--		 HB_TAG('K','H','T',' ')}},	/* Khamti -> Khamti Shan (OpenType spec and SIL fonts) */
--  {"khw",	{HB_TAG('K','H','W',' ')}},	/* Khowar */
--  {"ki",	{HB_TAG('K','I','K',' ')}},	/* Kikuyu (Gikuyu) */
--  {"kiu",	{HB_TAG('K','I','U',' ')}},	/* Kirmanjki */
--  {"kj",	{HB_TAG('K','U','A',' ')}},	/* Kuanyama */
--  {"kjd",	{HB_TAG('K','J','D',' ')}},	/* Southern Kiwai */
--  {"kjh",	{HB_TAG('K','H','A',' ')}},	/* Khakas -> Khakass */
--  {"kjp",	{HB_TAG('K','J','P',' ')}},	/* Pwo Eastern Karen -> Eastern Pwo Karen */
--  {"kjz",	{HB_TAG('K','J','Z',' ')}},	/* Bumthangkha */
--  {"kk",	{HB_TAG('K','A','Z',' ')}},	/* Kazakh */
--  {"kkz",	{HB_TAG('A','T','H',' ')}},	/* Kaska -> Athapaskan */
--  {"kl",	{HB_TAG('G','R','N',' ')}},	/* Greenlandic */
--  {"kln",	{HB_TAG('K','A','L',' ')}},	/* Kalenjin [macrolanguage] */
--  {"km",	{HB_TAG('K','H','M',' ')}},	/* Khmer */
--  {"kmb",	{HB_TAG('M','B','N',' ')}},	/* Kimbundu -> Mbundu */
--  {"kmr",	{HB_TAG('K','U','R',' ')}},	/* Northern Kurdish -> Kurdish */
--  {"kmw",	{HB_TAG('K','M','O',' ')}},	/* Komo (Democratic Republic of Congo) */
--  {"kmz",	{HB_TAG('K','M','Z',' ')}},	/* Khorasani Turkish -> Khorasani Turkic */
--  {"kn",	{HB_TAG('K','A','N',' ')}},	/* Kannada */
--  {"knc",	{HB_TAG('K','N','R',' ')}},	/* Central Kanuri -> Kanuri */
--  {"kng",	{HB_TAG('K','O','N','0')}},	/* Koongo -> Kongo */
--  {"knn",	{HB_TAG('K','O','K',' ')}},	/* Konkani */
--  {"ko",	{HB_TAG('K','O','R',' ')}},	/* Korean */
--  {"koi",	{HB_TAG('K','O','P',' ')}},	/* Komi-Permyak */
--  {"kok",	{HB_TAG('K','O','K',' ')}},	/* Konkani [macrolanguage] */
--  {"kos",	{HB_TAG('K','O','S',' ')}},	/* Kosraean */
--  {"koy",	{HB_TAG('A','T','H',' ')}},	/* Koyukon -> Athapaskan */
--  {"kpe",	{HB_TAG('K','P','L',' ')}},	/* Kpelle [macrolanguage] */
--  {"kpv",	{HB_TAG('K','O','Z',' ')}},	/* Komi-Zyrian */
--  {"kpy",	{HB_TAG('K','Y','K',' ')}},	/* Koryak */
--  {"kqs",	{HB_TAG('K','I','S',' ')}},	/* Northern Kissi -> Kisii */
--  {"kqy",	{HB_TAG('K','R','T',' ')}},	/* Koorete */
--  {"kr",	{HB_TAG('K','N','R',' ')}},	/* Kanuri [macrolanguage] */
--  {"krc",	{HB_TAG('K','A','R',' '),	/* Karachay-Balkar -> Karachay */
--		 HB_TAG('B','A','L',' ')}},	/* Karachay-Balkar -> Balkar */
--  {"kri",	{HB_TAG('K','R','I',' ')}},	/* Krio */
--  {"krl",	{HB_TAG('K','R','L',' ')}},	/* Karelian */
--  {"krt",	{HB_TAG('K','N','R',' ')}},	/* Tumari Kanuri -> Kanuri */
--  {"kru",	{HB_TAG('K','U','U',' ')}},	/* Kurukh */
--  {"ks",	{HB_TAG('K','S','H',' ')}},	/* Kashmiri */
--  {"ksh",	{HB_TAG('K','S','H','0')}},	/* Kölsch -> Ripuarian */
--  {"kss",	{HB_TAG('K','I','S',' ')}},	/* Southern Kisi -> Kisii */
--  {"ksw",	{HB_TAG('K','S','W',' ')}},	/* S’gaw Karen */
--  {"ktb",	{HB_TAG('K','E','B',' ')}},	/* Kambaata -> Kebena */
--  {"ktu",	{HB_TAG('K','O','N',' ')}},	/* Kituba (Democratic Republic of Congo) -> Kikongo */
--  {"ktw",	{HB_TAG('A','T','H',' ')}},	/* Kato -> Athapaskan */
--  {"ku",	{HB_TAG('K','U','R',' ')}},	/* Kurdish [macrolanguage] */
--  {"kum",	{HB_TAG('K','U','M',' ')}},	/* Kumyk */
--  {"kuu",	{HB_TAG('A','T','H',' ')}},	/* Upper Kuskokwim -> Athapaskan */
--  {"kv",	{HB_TAG('K','O','M',' ')}},	/* Komi [macrolanguage] */
--  {"kvb",	{HB_TAG('M','L','Y',' ')}},	/* Kubu -> Malay */
--  {"kvr",	{HB_TAG('M','L','Y',' ')}},	/* Kerinci -> Malay */
--  {"kw",	{HB_TAG('C','O','R',' ')}},	/* Cornish */
--  {"kwy",	{HB_TAG('K','O','N','0')}},	/* San Salvador Kongo -> Kongo */
--  {"kxc",	{HB_TAG('K','M','S',' ')}},	/* Konso -> Komso */
--  {"kxd",	{HB_TAG('M','L','Y',' ')}},	/* Brunei -> Malay */
--  {"kxu",	{HB_TAG('K','U','I',' ')}},	/* Kui (India) */
--  {"ky",	{HB_TAG('K','I','R',' ')}},	/* Kirghiz (Kyrgyz) */
--  {"kyu",	{HB_TAG('K','Y','U',' ')}},	/* Western Kayah */
--  {"la",	{HB_TAG('L','A','T',' ')}},	/* Latin */
--  {"lad",	{HB_TAG('J','U','D',' ')}},	/* Ladino */
--  {"lb",	{HB_TAG('L','T','Z',' ')}},	/* Luxembourgish */
--  {"lbe",	{HB_TAG('L','A','K',' ')}},	/* Lak */
--  {"lbj",	{HB_TAG('L','D','K',' ')}},	/* Ladakhi */
--  {"lbl",	{HB_TAG('B','I','K',' ')}},	/* Libon Bikol -> Bikol */
--  {"lce",	{HB_TAG('M','L','Y',' ')}},	/* Loncong -> Malay */
--  {"lcf",	{HB_TAG('M','L','Y',' ')}},	/* Lubu -> Malay */
--  {"ldi",	{HB_TAG('K','O','N','0')}},	/* Laari -> Kongo */
--  {"lez",	{HB_TAG('L','E','Z',' ')}},	/* Lezghian -> Lezgi */
--  {"lg",	{HB_TAG('L','U','G',' ')}},	/* Ganda */
--  {"li",	{HB_TAG('L','I','M',' ')}},	/* Limburgish */
--  {"lif",	{HB_TAG('L','M','B',' ')}},	/* Limbu */
--  {"lij",	{HB_TAG('L','I','J',' ')}},	/* Ligurian */
--  {"lis",	{HB_TAG('L','I','S',' ')}},	/* Lisu */
--  {"liw",	{HB_TAG('M','L','Y',' ')}},	/* Col -> Malay */
--  {"ljp",	{HB_TAG('L','J','P',' ')}},	/* Lampung Api -> Lampung */
--  {"lkb",	{HB_TAG('L','U','H',' ')}},	/* Kabras -> Luyia */
--  {"lki",	{HB_TAG('L','K','I',' ')}},	/* Laki */
--  {"lko",	{HB_TAG('L','U','H',' ')}},	/* Khayo -> Luyia */
--  {"lks",	{HB_TAG('L','U','H',' ')}},	/* Kisa -> Luyia */
--  {"lld",	{HB_TAG('L','A','D',' ')}},	/* Ladin */
--  {"lmn",	{HB_TAG('L','A','M',' ')}},	/* Lambadi -> Lambani */
--  {"lmo",	{HB_TAG('L','M','O',' ')}},	/* Lombard */
--  {"ln",	{HB_TAG('L','I','N',' ')}},	/* Lingala */
--  {"lo",	{HB_TAG('L','A','O',' ')}},	/* Lao */
--  {"lom",	{HB_TAG('L','O','M',' ')}},	/* Loma (Liberia) */
--  {"lrc",	{HB_TAG('L','R','C',' ')}},	/* Northern Luri -> Luri */
--  {"lri",	{HB_TAG('L','U','H',' ')}},	/* Marachi -> Luyia */
--  {"lrm",	{HB_TAG('L','U','H',' ')}},	/* Marama -> Luyia */
--  {"lsm",	{HB_TAG('L','U','H',' ')}},	/* Saamia -> Luyia */
--  {"lt",	{HB_TAG('L','T','H',' ')}},	/* Lithuanian */
--  {"ltg",	{HB_TAG('L','V','I',' ')}},	/* Latgalian -> Latvian */
--  {"lto",	{HB_TAG('L','U','H',' ')}},	/* Tsotso -> Luyia */
--  {"lts",	{HB_TAG('L','U','H',' ')}},	/* Tachoni -> Luyia */
--  {"lu",	{HB_TAG('L','U','B',' ')}},	/* Luba-Katanga */
--  {"lua",	{HB_TAG('L','U','A',' ')}},	/* Luba-Lulua */
--  {"luo",	{HB_TAG('L','U','O',' ')}},	/* Luo (Kenya and Tanzania) */
--  {"lus",	{HB_TAG('M','I','Z',' ')}},	/* Lushai -> Mizo */
--  {"luy",	{HB_TAG('L','U','H',' ')}},	/* Luyia [macrolanguage] */
--  {"luz",	{HB_TAG('L','R','C',' ')}},	/* Southern Luri -> Luri */
--  {"lv",	{HB_TAG('L','V','I',' ')}},	/* Latvian [macrolanguage] */
--  {"lvs",	{HB_TAG('L','V','I',' ')}},	/* Standard Latvian -> Latvian */
--  {"lwg",	{HB_TAG('L','U','H',' ')}},	/* Wanga -> Luyia */
--  {"lzh",	{HB_TAG('Z','H','T',' ')}},	/* Literary Chinese -> Chinese Traditional */
--  {"lzz",	{HB_TAG('L','A','Z',' ')}},	/* Laz */
--  {"mad",	{HB_TAG('M','A','D',' ')}},	/* Madurese -> Madura */
--  {"mag",	{HB_TAG('M','A','G',' ')}},	/* Magahi */
--  {"mai",	{HB_TAG('M','T','H',' ')}},	/* Maithili */
--  {"mak",	{HB_TAG('M','K','R',' ')}},	/* Makasar */
--  {"mam",	{HB_TAG('M','A','M',' ')}},	/* Mam */
--  {"man",	{HB_TAG('M','N','K',' ')}},	/* Mandingo [macrolanguage] -> Maninka */
--  {"max",	{HB_TAG('M','L','Y',' ')}},	/* North Moluccan Malay -> Malay */
--  {"mbo",	{HB_TAG('M','B','O',' ')}},	/* Mbo (Cameroon) */
--  {"mct",	{HB_TAG('B','T','I',' ')}},	/* Mengisa -> Beti */
--  {"mdf",	{HB_TAG('M','O','K',' ')}},	/* Moksha */
--  {"mdr",	{HB_TAG('M','D','R',' ')}},	/* Mandar */
--  {"mdy",	{HB_TAG('M','L','E',' ')}},	/* Male (Ethiopia) */
--  {"men",	{HB_TAG('M','D','E',' ')}},	/* Mende (Sierra Leone) */
--  {"meo",	{HB_TAG('M','L','Y',' ')}},	/* Kedah Malay -> Malay */
--  {"mer",	{HB_TAG('M','E','R',' ')}},	/* Meru */
--  {"mfa",	{HB_TAG('M','F','A',' ')}},	/* Pattani Malay */
--  {"mfb",	{HB_TAG('M','L','Y',' ')}},	/* Bangka -> Malay */
--  {"mfe",	{HB_TAG('M','F','E',' ')}},	/* Morisyen */
--  {"mg",	{HB_TAG('M','L','G',' ')}},	/* Malagasy [macrolanguage] */
--  {"mh",	{HB_TAG('M','A','H',' ')}},	/* Marshallese */
--  {"mhr",	{HB_TAG('L','M','A',' ')}},	/* Eastern Mari -> Low Mari */
--  {"mhv",	{HB_TAG('A','R','K',' ')}},	/* Arakanese (retired code) -> Rakhine */
--  {"mi",	{HB_TAG('M','R','I',' ')}},	/* Maori */
--  {"min",	{HB_TAG('M','I','N',' ')}},	/* Minangkabau */
--  {"mk",	{HB_TAG('M','K','D',' ')}},	/* Macedonian */
--  {"mku",	{HB_TAG('M','N','K',' ')}},	/* Konyanka Maninka -> Maninka */
--  {"mkw",	{HB_TAG('M','K','W',' ')}},	/* Kituba (Congo) */
--  {"ml",	{HB_TAG('M','A','L',' '),	/* Malayalam -> Malayalam Traditional */
--		 HB_TAG('M','L','R',' ')}},	/* Malayalam -> Malayalam Reformed */
--  {"mlq",	{HB_TAG('M','L','N',' '),	/* Western Maninkakan -> Malinke */
--		 HB_TAG('M','N','K',' ')}},	/* Western Maninkakan -> Maninka */
--  {"mmr",	{HB_TAG('H','M','N',' ')}},	/* Western Xiangxi Miao -> Hmong */
--  {"mn",	{HB_TAG('M','N','G',' ')}},	/* Mongolian [macrolanguage] */
--  {"mnc",	{HB_TAG('M','C','H',' ')}},	/* Manchu */
--  {"mni",	{HB_TAG('M','N','I',' ')}},	/* Manipuri */
--  {"mnk",	{HB_TAG('M','N','D',' '),	/* Mandinka */
--		 HB_TAG('M','N','K',' ')}},	/* Mandinka -> Maninka */
--  {"mnp",	{HB_TAG('Z','H','S',' ')}},	/* Min Bei Chinese -> Chinese Simplified */
--  {"mns",	{HB_TAG('M','A','N',' ')}},	/* Mansi */
--  {"mnw",	{HB_TAG('M','O','N',' ')}},	/* Mon */
--  {"mo",	{HB_TAG('M','O','L',' ')}},	/* Moldavian (retired code) */
--  {"moh",	{HB_TAG('M','O','H',' ')}},	/* Mohawk */
--  {"mos",	{HB_TAG('M','O','S',' ')}},	/* Mossi */
--  {"mpe",	{HB_TAG('M','A','J',' ')}},	/* Majang */
--  {"mqg",	{HB_TAG('M','L','Y',' ')}},	/* Kota Bangun Kutai Malay -> Malay */
--  {"mr",	{HB_TAG('M','A','R',' ')}},	/* Marathi */
--  {"mrh",	{HB_TAG('Q','I','N',' ')}},	/* Mara Chin -> Chin */
--  {"mrj",	{HB_TAG('H','M','A',' ')}},	/* Western Mari -> High Mari */
--  {"ms",	{HB_TAG('M','L','Y',' ')}},	/* Malay [macrolanguage] */
--  {"msc",	{HB_TAG('M','N','K',' ')}},	/* Sankaran Maninka -> Maninka */
--  {"msh",	{HB_TAG('M','L','G',' ')}},	/* Masikoro Malagasy -> Malagasy */
--  {"msi",	{HB_TAG('M','L','Y',' ')}},	/* Sabah Malay -> Malay */
--  {"mt",	{HB_TAG('M','T','S',' ')}},	/* Maltese */
--  {"mtr",	{HB_TAG('M','A','W',' ')}},	/* Mewari -> Marwari */
--  {"mui",	{HB_TAG('M','L','Y',' ')}},	/* Musi -> Malay */
--  {"mup",	{HB_TAG('R','A','J',' ')}},	/* Malvi -> Rajasthani */
--  {"muq",	{HB_TAG('H','M','N',' ')}},	/* Eastern Xiangxi Miao -> Hmong */
--  {"mus",	{HB_TAG('M','U','S',' ')}},	/* Creek -> Muscogee */
--  {"mvb",	{HB_TAG('A','T','H',' ')}},	/* Mattole -> Athapaskan */
--  {"mve",	{HB_TAG('M','A','W',' ')}},	/* Marwari (Pakistan) */
--  {"mvf",	{HB_TAG('M','N','G',' ')}},	/* Peripheral Mongolian -> Mongolian */
--  {"mwk",	{HB_TAG('M','N','K',' ')}},	/* Kita Maninkakan -> Maninka */
--  {"mwl",	{HB_TAG('M','W','L',' ')}},	/* Mirandese */
--  {"mwr",	{HB_TAG('M','A','W',' ')}},	/* Marwari [macrolanguage] */
--  {"mww",	{HB_TAG('M','W','W',' ')}},	/* Hmong Daw */
--  {"my",	{HB_TAG('B','R','M',' ')}},	/* Burmese */
--  {"mym",	{HB_TAG('M','E','N',' ')}},	/* Me’en */
--  {"myn",	{HB_TAG('M','Y','N',' ')}},	/* Mayan [family] */
--  {"myq",	{HB_TAG('M','N','K',' ')}},	/* Forest Maninka (retired code) -> Maninka */
--  {"myv",	{HB_TAG('E','R','Z',' ')}},	/* Erzya */
--  {"mzn",	{HB_TAG('M','Z','N',' ')}},	/* Mazanderani */
--  {"na",	{HB_TAG('N','A','U',' ')}},	/* Nauru -> Nauruan */
--  {"nag",	{HB_TAG('N','A','G',' ')}},	/* Naga Pidgin -> Naga-Assamese */
--  {"nah",	{HB_TAG('N','A','H',' ')}},	/* Nahuatl [family] */
--  {"nan",	{HB_TAG('Z','H','S',' ')}},	/* Min Nan Chinese -> Chinese Simplified */
--  {"nap",	{HB_TAG('N','A','P',' ')}},	/* Neapolitan */
--  {"nb",	{HB_TAG('N','O','R',' ')}},	/* Norwegian Bokmål -> Norwegian */
--  {"nd",	{HB_TAG('N','D','B',' ')}},	/* North Ndebele -> Ndebele */
--  {"ndc",	{HB_TAG('N','D','C',' ')}},	/* Ndau */
--  {"nds",	{HB_TAG('N','D','S',' ')}},	/* Low Saxon */
--  {"ne",	{HB_TAG('N','E','P',' ')}},	/* Nepali [macrolanguage] */
--  {"new",	{HB_TAG('N','E','W',' ')}},	/* Newari */
--  {"ng",	{HB_TAG('N','D','G',' ')}},	/* Ndonga */
--  {"nga",	{HB_TAG('N','G','A',' ')}},	/* Ngbaka */
--  {"ngl",	{HB_TAG('L','M','W',' ')}},	/* Lomwe */
--  {"ngo",	{HB_TAG('S','X','T',' ')}},	/* Ngoni -> Sutu */
--  {"nhd",	{HB_TAG('G','U','A',' ')}},	/* Chiripá -> Guarani */
--  {"niq",	{HB_TAG('K','A','L',' ')}},	/* Nandi -> Kalenjin */
--  {"niu",	{HB_TAG('N','I','U',' ')}},	/* Niuean */
--  {"niv",	{HB_TAG('G','I','L',' ')}},	/* Gilyak */
--  {"njz",	{HB_TAG('N','I','S',' ')}},	/* Nyishi -> Nisi */
--  {"nl",	{HB_TAG('N','L','D',' ')}},	/* Dutch */
--  {"nle",	{HB_TAG('L','U','H',' ')}},	/* East Nyala -> Luyia */
--  {"nn",	{HB_TAG('N','Y','N',' ')}},	/* Norwegian Nynorsk (Nynorsk, Norwegian) */
--  {"no",	{HB_TAG('N','O','R',' ')}},	/* Norwegian [macrolanguage] */
--  {"nod",	{HB_TAG('N','T','A',' ')}},	/* Northern Thai -> Northern Tai */
--  {"noe",	{HB_TAG('N','O','E',' ')}},	/* Nimadi */
--  {"nog",	{HB_TAG('N','O','G',' ')}},	/* Nogai */
--  {"nov",	{HB_TAG('N','O','V',' ')}},	/* Novial */
--  {"npi",	{HB_TAG('N','E','P',' ')}},	/* Nepali */
--  {"nqo",	{HB_TAG('N','K','O',' ')}},	/* N’Ko */
--  {"nr",	{HB_TAG('N','D','B',' ')}},	/* South Ndebele -> Ndebele */
--  {"nsk",	{HB_TAG('N','A','S',' ')}},	/* Naskapi */
--  {"nso",	{HB_TAG('N','S','O',' ')}},	/* Pedi -> Sotho, Northern */
--  {"nv",	{HB_TAG('N','A','V',' '),	/* Navajo */
--		 HB_TAG('A','T','H',' ')}},	/* Navajo -> Athapaskan */
--  {"ny",	{HB_TAG('C','H','I',' ')}},	/* Chichewa (Chewa, Nyanja) */
--  {"nyd",	{HB_TAG('L','U','H',' ')}},	/* Nyore -> Luyia */
--  {"nym",	{HB_TAG('N','Y','M',' ')}},	/* Nyamwezi */
--  {"nyn",	{HB_TAG('N','K','L',' ')}},	/* Nyankole */
--  {"nza",	{HB_TAG('N','Z','A',' ')}},	/* Tigon Mbembe -> Mbembe Tigon */
--  {"oc",	{HB_TAG('O','C','I',' ')}},	/* Occitan (post 1500) */
--  {"oj",	{HB_TAG('O','J','B',' ')}},	/* Ojibwa [macrolanguage] -> Ojibway */
--  {"ojb",	{HB_TAG('O','J','B',' ')}},	/* Northwestern Ojibwa -> Ojibway */
--  {"ojc",	{HB_TAG('O','J','B',' ')}},	/* Central Ojibwa -> Ojibway */
--  {"ojg",	{HB_TAG('O','J','B',' ')}},	/* Eastern Ojibwa -> Ojibway */
--  {"ojs",	{HB_TAG('O','C','R',' ')}},	/* Severn Ojibwa -> Oji-Cree */
--  {"ojw",	{HB_TAG('O','J','B',' ')}},	/* Western Ojibwa -> Ojibway */
--  {"oki",	{HB_TAG('K','A','L',' ')}},	/* Okiek -> Kalenjin */
--  {"okm",	{HB_TAG('K','O','H',' ')}},	/* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
--  {"om",	{HB_TAG('O','R','O',' ')}},	/* Oromo [macrolanguage] */
--  {"or",	{HB_TAG('O','R','I',' ')}},	/* Odia (formerly Oriya) [macrolanguage] */
--  {"orc",	{HB_TAG('O','R','O',' ')}},	/* Orma -> Oromo */
--  {"orn",	{HB_TAG('M','L','Y',' ')}},	/* Orang Kanaq -> Malay */
--  {"ors",	{HB_TAG('M','L','Y',' ')}},	/* Orang Seletar -> Malay */
--  {"ory",	{HB_TAG('O','R','I',' ')}},	/* Odia (formerly Oriya) */
--  {"os",	{HB_TAG('O','S','S',' ')}},	/* Ossetian */
--  {"otw",	{HB_TAG('O','J','B',' ')}},	/* Ottawa -> Ojibway */
--  {"pa",	{HB_TAG('P','A','N',' ')}},	/* Punjabi */
--  {"pag",	{HB_TAG('P','A','G',' ')}},	/* Pangasinan */
--  {"pam",	{HB_TAG('P','A','M',' ')}},	/* Pampanga -> Pampangan */
--  {"pap",	{HB_TAG('P','A','P','0')}},	/* Papiamento -> Papiamentu */
--  {"pau",	{HB_TAG('P','A','U',' ')}},	/* Palauan */
--  {"pbt",	{HB_TAG('P','A','S',' ')}},	/* Southern Pashto -> Pashto */
--  {"pbu",	{HB_TAG('P','A','S',' ')}},	/* Northern Pashto -> Pashto */
--  {"pcc",	{HB_TAG('P','C','C',' ')}},	/* Bouyei */
--  {"pcd",	{HB_TAG('P','C','D',' ')}},	/* Picard */
--  {"pce",	{HB_TAG('P','L','G',' ')}},	/* Ruching Palaung -> Palaung */
--  {"pck",	{HB_TAG('Q','I','N',' ')}},	/* Paite Chin -> Chin */
--  {"pdc",	{HB_TAG('P','D','C',' ')}},	/* Pennsylvania German */
--  {"pel",	{HB_TAG('M','L','Y',' ')}},	/* Pekal -> Malay */
--  {"pes",	{HB_TAG('F','A','R',' ')}},	/* Iranian Persian -> Persian */
--  {"pga",	{HB_TAG('A','R','A',' ')}},	/* Sudanese Creole Arabic -> Arabic */
--  {"phk",	{HB_TAG('P','H','K',' ')}},	/* Phake */
--  {"pi",	{HB_TAG('P','A','L',' ')}},	/* Pali */
--  {"pih",	{HB_TAG('P','I','H',' ')}},	/* Pitcairn-Norfolk -> Norfolk */
--  {"pko",	{HB_TAG('K','A','L',' ')}},	/* Pökoot -> Kalenjin */
--  {"pl",	{HB_TAG('P','L','K',' ')}},	/* Polish */
--  {"pll",	{HB_TAG('P','L','G',' ')}},	/* Shwe Palaung -> Palaung */
--  {"plp",	{HB_TAG('P','A','P',' ')}},	/* Palpa */
--  {"plt",	{HB_TAG('M','L','G',' ')}},	/* Plateau Malagasy -> Malagasy */
--  {"pms",	{HB_TAG('P','M','S',' ')}},	/* Piemontese */
--  {"pnb",	{HB_TAG('P','N','B',' ')}},	/* Western Panjabi */
--  {"poh",	{HB_TAG('P','O','H',' ')}},	/* Poqomchi' -> Pocomchi */
--  {"pon",	{HB_TAG('P','O','N',' ')}},	/* Pohnpeian */
--  {"ppa",	{HB_TAG('B','A','G',' ')}},	/* Pao (retired code) -> Baghelkhandi */
--  {"pro",	{HB_TAG('P','R','O',' ')}},	/* Old Provençal (to 1500) -> Provençal / Old Provençal */
--  {"prs",	{HB_TAG('D','R','I',' ')}},	/* Dari */
--  {"ps",	{HB_TAG('P','A','S',' ')}},	/* Pashto [macrolanguage] */
--  {"pse",	{HB_TAG('M','L','Y',' ')}},	/* Central Malay -> Malay */
--  {"pst",	{HB_TAG('P','A','S',' ')}},	/* Central Pashto -> Pashto */
--  {"pt",	{HB_TAG('P','T','G',' ')}},	/* Portuguese */
--  {"pwo",	{HB_TAG('P','W','O',' ')}},	/* Pwo Western Karen -> Western Pwo Karen */
--  {"qu",	{HB_TAG('Q','U','Z',' ')}},	/* Quechua [macrolanguage] */
--  {"qub",	{HB_TAG('Q','W','H',' ')}},	/* Huallaga Huánuco Quechua -> Quechua (Peru) */
--  {"quc",	{HB_TAG('Q','U','C',' ')}},	/* K’iche’ */
--  {"qud",	{HB_TAG('Q','V','I',' ')}},	/* Calderón Highland Quichua -> Quechua (Ecuador) */
--  {"quf",	{HB_TAG('Q','U','Z',' ')}},	/* Lambayeque Quechua -> Quechua */
--  {"qug",	{HB_TAG('Q','V','I',' ')}},	/* Chimborazo Highland Quichua -> Quechua (Ecuador) */
--  {"quh",	{HB_TAG('Q','U','H',' ')}},	/* South Bolivian Quechua -> Quechua (Bolivia) */
--  {"quk",	{HB_TAG('Q','U','Z',' ')}},	/* Chachapoyas Quechua -> Quechua */
--  {"qul",	{HB_TAG('Q','U','Z',' ')}},	/* North Bolivian Quechua -> Quechua */
--  {"qup",	{HB_TAG('Q','V','I',' ')}},	/* Southern Pastaza Quechua -> Quechua (Ecuador) */
--  {"qur",	{HB_TAG('Q','W','H',' ')}},	/* Yanahuanca Pasco Quechua -> Quechua (Peru) */
--  {"qus",	{HB_TAG('Q','U','H',' ')}},	/* Santiago del Estero Quichua -> Quechua (Bolivia) */
--  {"quw",	{HB_TAG('Q','V','I',' ')}},	/* Tena Lowland Quichua -> Quechua (Ecuador) */
--  {"qux",	{HB_TAG('Q','W','H',' ')}},	/* Yauyos Quechua -> Quechua (Peru) */
--  {"quy",	{HB_TAG('Q','U','Z',' ')}},	/* Ayacucho Quechua -> Quechua */
--  {"quz",	{HB_TAG('Q','U','Z',' ')}},	/* Cusco Quechua -> Quechua */
--  {"qva",	{HB_TAG('Q','W','H',' ')}},	/* Ambo-Pasco Quechua -> Quechua (Peru) */
--  {"qvc",	{HB_TAG('Q','U','Z',' ')}},	/* Cajamarca Quechua -> Quechua */
--  {"qve",	{HB_TAG('Q','U','Z',' ')}},	/* Eastern Apurímac Quechua -> Quechua */
--  {"qvh",	{HB_TAG('Q','W','H',' ')}},	/* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
--  {"qvi",	{HB_TAG('Q','V','I',' ')}},	/* Imbabura Highland Quichua -> Quechua (Ecuador) */
--  {"qvj",	{HB_TAG('Q','V','I',' ')}},	/* Loja Highland Quichua -> Quechua (Ecuador) */
--  {"qvl",	{HB_TAG('Q','W','H',' ')}},	/* Cajatambo North Lima Quechua -> Quechua (Peru) */
--  {"qvm",	{HB_TAG('Q','W','H',' ')}},	/* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
--  {"qvn",	{HB_TAG('Q','W','H',' ')}},	/* North Junín Quechua -> Quechua (Peru) */
--  {"qvo",	{HB_TAG('Q','V','I',' ')}},	/* Napo Lowland Quechua -> Quechua (Ecuador) */
--  {"qvp",	{HB_TAG('Q','W','H',' ')}},	/* Pacaraos Quechua -> Quechua (Peru) */
--  {"qvs",	{HB_TAG('Q','U','Z',' ')}},	/* San Martín Quechua -> Quechua */
--  {"qvw",	{HB_TAG('Q','W','H',' ')}},	/* Huaylla Wanca Quechua -> Quechua (Peru) */
--  {"qvz",	{HB_TAG('Q','V','I',' ')}},	/* Northern Pastaza Quichua -> Quechua (Ecuador) */
--  {"qwa",	{HB_TAG('Q','W','H',' ')}},	/* Corongo Ancash Quechua -> Quechua (Peru) */
--  {"qwc",	{HB_TAG('Q','U','Z',' ')}},	/* Classical Quechua -> Quechua */
--  {"qwh",	{HB_TAG('Q','W','H',' ')}},	/* Huaylas Ancash Quechua -> Quechua (Peru) */
--  {"qws",	{HB_TAG('Q','W','H',' ')}},	/* Sihuas Ancash Quechua -> Quechua (Peru) */
--  {"qxa",	{HB_TAG('Q','W','H',' ')}},	/* Chiquián Ancash Quechua -> Quechua (Peru) */
--  {"qxc",	{HB_TAG('Q','W','H',' ')}},	/* Chincha Quechua -> Quechua (Peru) */
--  {"qxh",	{HB_TAG('Q','W','H',' ')}},	/* Panao Huánuco Quechua -> Quechua (Peru) */
--  {"qxl",	{HB_TAG('Q','V','I',' ')}},	/* Salasaca Highland Quichua -> Quechua (Ecuador) */
--  {"qxn",	{HB_TAG('Q','W','H',' ')}},	/* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
--  {"qxo",	{HB_TAG('Q','W','H',' ')}},	/* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
--  {"qxp",	{HB_TAG('Q','U','Z',' ')}},	/* Puno Quechua -> Quechua */
--  {"qxr",	{HB_TAG('Q','V','I',' ')}},	/* Cañar Highland Quichua -> Quechua (Ecuador) */
--  {"qxt",	{HB_TAG('Q','W','H',' ')}},	/* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
--  {"qxu",	{HB_TAG('Q','U','Z',' ')}},	/* Arequipa-La Unión Quechua -> Quechua */
--  {"qxw",	{HB_TAG('Q','W','H',' ')}},	/* Jauja Wanca Quechua -> Quechua (Peru) */
--  {"rag",	{HB_TAG('L','U','H',' ')}},	/* Logooli -> Luyia */
--  {"raj",	{HB_TAG('R','A','J',' ')}},	/* Rajasthani [macrolanguage] */
--  {"rar",	{HB_TAG('R','A','R',' ')}},	/* Rarotongan */
--  {"rbb",	{HB_TAG('P','L','G',' ')}},	/* Rumai Palaung -> Palaung */
--  {"rbl",	{HB_TAG('B','I','K',' ')}},	/* Miraya Bikol -> Bikol */
--  {"rej",	{HB_TAG('R','E','J',' ')}},	/* Rejang */
--  {"ria",	{HB_TAG('R','I','A',' ')}},	/* Riang (India) */
--  {"rif",	{HB_TAG('R','I','F',' ')}},	/* Tarifit */
--  {"rit",	{HB_TAG('R','I','T',' ')}},	/* Ritarungo */
--  {"rki",	{HB_TAG('A','R','K',' ')}},	/* Rakhine */
--  {"rkw",	{HB_TAG('R','K','W',' ')}},	/* Arakwal */
--  {"rm",	{HB_TAG('R','M','S',' ')}},	/* Romansh */
--  {"rmc",	{HB_TAG('R','O','Y',' ')}},	/* Carpathian Romani -> Romany */
--  {"rmf",	{HB_TAG('R','O','Y',' ')}},	/* Kalo Finnish Romani -> Romany */
--  {"rml",	{HB_TAG('R','O','Y',' ')}},	/* Baltic Romani -> Romany */
--  {"rmn",	{HB_TAG('R','O','Y',' ')}},	/* Balkan Romani -> Romany */
--  {"rmo",	{HB_TAG('R','O','Y',' ')}},	/* Sinte Romani -> Romany */
--  {"rmw",	{HB_TAG('R','O','Y',' ')}},	/* Welsh Romani -> Romany */
--  {"rmy",	{HB_TAG('R','M','Y',' ')}},	/* Vlax Romani */
--  {"rmz",	{HB_TAG('A','R','K',' ')}},	/* Marma -> Rakhine */
--  {"rn",	{HB_TAG('R','U','N',' ')}},	/* Rundi */
--  {"rnl",	{HB_TAG('H','A','L',' ')}},	/* Ranglong -> Halam (Falam Chin) */
--  {"ro",	{HB_TAG('R','O','M',' ')}},	/* Romanian */
--  {"rom",	{HB_TAG('R','O','Y',' ')}},	/* Romany [macrolanguage] */
--  {"rtm",	{HB_TAG('R','T','M',' ')}},	/* Rotuman */
--  {"ru",	{HB_TAG('R','U','S',' ')}},	/* Russian */
--  {"rue",	{HB_TAG('R','S','Y',' ')}},	/* Rusyn */
--  {"rup",	{HB_TAG('R','U','P',' ')}},	/* Aromanian */
--  {"rw",	{HB_TAG('R','U','A',' ')}},	/* Kinyarwanda */
--  {"rwr",	{HB_TAG('M','A','W',' ')}},	/* Marwari (India) */
--  {"sa",	{HB_TAG('S','A','N',' ')}},	/* Sanskrit */
--  {"sah",	{HB_TAG('Y','A','K',' ')}},	/* Yakut -> Sakha */
--  {"sam",	{HB_TAG('P','A','A',' ')}},	/* Samaritan Aramaic -> Palestinian Aramaic */
--  {"sas",	{HB_TAG('S','A','S',' ')}},	/* Sasak */
--  {"sat",	{HB_TAG('S','A','T',' ')}},	/* Santali */
--  {"sc",	{HB_TAG('S','R','D',' ')}},	/* Sardinian [macrolanguage] */
--  {"sck",	{HB_TAG('S','A','D',' ')}},	/* Sadri */
--  {"scn",	{HB_TAG('S','C','N',' ')}},	/* Sicilian */
--  {"sco",	{HB_TAG('S','C','O',' ')}},	/* Scots */
--  {"scs",	{HB_TAG('S','C','S',' '),	/* North Slavey */
--		 HB_TAG('S','L','A',' '),	/* North Slavey -> Slavey */
--		 HB_TAG('A','T','H',' ')}},	/* North Slavey -> Athapaskan */
--  {"sd",	{HB_TAG('S','N','D',' ')}},	/* Sindhi */
--  {"sdc",	{HB_TAG('S','R','D',' ')}},	/* Sassarese Sardinian -> Sardinian */
--  {"sdh",	{HB_TAG('K','U','R',' ')}},	/* Southern Kurdish -> Kurdish */
--  {"sdn",	{HB_TAG('S','R','D',' ')}},	/* Gallurese Sardinian -> Sardinian */
--  {"se",	{HB_TAG('N','S','M',' ')}},	/* Northern Sami */
--  {"seh",	{HB_TAG('S','N','A',' ')}},	/* Sena */
--  {"sek",	{HB_TAG('A','T','H',' ')}},	/* Sekani -> Athapaskan */
--  {"sel",	{HB_TAG('S','E','L',' ')}},	/* Selkup */
--  {"sez",	{HB_TAG('Q','I','N',' ')}},	/* Senthang Chin -> Chin */
--  {"sfm",	{HB_TAG('H','M','N',' ')}},	/* Small Flowery Miao -> Hmong */
--  {"sg",	{HB_TAG('S','G','O',' ')}},	/* Sango */
--  {"sga",	{HB_TAG('S','G','A',' ')}},	/* Old Irish (to 900) */
--  {"sgc",	{HB_TAG('K','A','L',' ')}},	/* Kipsigis -> Kalenjin */
--  {"sgs",	{HB_TAG('S','G','S',' ')}},	/* Samogitian */
--  {"sgw",	{HB_TAG('C','H','G',' '),	/* Sebat Bet Gurage -> Chaha Gurage */
--		 HB_TAG('S','G','W',' ')}},	/* Sebat Bet Gurage -> Chaha Gurage (SIL fonts) */
--  {"shi",	{HB_TAG('S','H','I',' ')}},	/* Tachelhit */
--  {"shn",	{HB_TAG('S','H','N',' ')}},	/* Shan */
--  {"shu",	{HB_TAG('A','R','A',' ')}},	/* Chadian Arabic -> Arabic */
--  {"si",	{HB_TAG('S','N','H',' ')}},	/* Sinhala (Sinhalese) */
--  {"sid",	{HB_TAG('S','I','D',' ')}},	/* Sidamo */
--  {"sjd",	{HB_TAG('K','S','M',' ')}},	/* Kildin Sami */
--  {"sjo",	{HB_TAG('S','I','B',' ')}},	/* Xibe -> Sibe */
--  {"sk",	{HB_TAG('S','K','Y',' ')}},	/* Slovak */
--  {"skg",	{HB_TAG('M','L','G',' ')}},	/* Sakalava Malagasy -> Malagasy */
--  {"skr",	{HB_TAG('S','R','K',' ')}},	/* Saraiki */
--  {"sl",	{HB_TAG('S','L','V',' ')}},	/* Slovenian */
--  {"sm",	{HB_TAG('S','M','O',' ')}},	/* Samoan */
--  {"sma",	{HB_TAG('S','S','M',' ')}},	/* Southern Sami */
--  {"smj",	{HB_TAG('L','S','M',' ')}},	/* Lule Sami */
--  {"smn",	{HB_TAG('I','S','M',' ')}},	/* Inari Sami */
--  {"sms",	{HB_TAG('S','K','S',' ')}},	/* Skolt Sami */
--  {"sn",	{HB_TAG('S','N','A','0')}},	/* Shona */
--  {"snk",	{HB_TAG('S','N','K',' ')}},	/* Soninke */
--  {"so",	{HB_TAG('S','M','L',' ')}},	/* Somali */
--  {"sop",	{HB_TAG('S','O','P',' ')}},	/* Songe */
--  {"spv",	{HB_TAG('O','R','I',' ')}},	/* Sambalpuri -> Odia (formerly Oriya) */
--  {"spy",	{HB_TAG('K','A','L',' ')}},	/* Sabaot -> Kalenjin */
--  {"sq",	{HB_TAG('S','Q','I',' ')}},	/* Albanian [macrolanguage] */
--  {"sr",	{HB_TAG('S','R','B',' ')}},	/* Serbian */
--  {"src",	{HB_TAG('S','R','D',' ')}},	/* Logudorese Sardinian -> Sardinian */
--  {"sro",	{HB_TAG('S','R','D',' ')}},	/* Campidanese Sardinian -> Sardinian */
--  {"srr",	{HB_TAG('S','R','R',' ')}},	/* Serer */
--  {"srs",	{HB_TAG('A','T','H',' ')}},	/* Sarsi -> Athapaskan */
--  {"ss",	{HB_TAG('S','W','Z',' ')}},	/* Swati */
--  {"ssh",	{HB_TAG('A','R','A',' ')}},	/* Shihhi Arabic -> Arabic */
--  {"st",	{HB_TAG('S','O','T',' ')}},	/* Southern Sotho -> Sotho, Southern */
--  {"stq",	{HB_TAG('S','T','Q',' ')}},	/* Saterfriesisch -> Saterland Frisian */
--  {"stv",	{HB_TAG('S','I','G',' ')}},	/* Silt'e -> Silte Gurage */
--  {"su",	{HB_TAG('S','U','N',' ')}},	/* Sundanese */
--  {"suk",	{HB_TAG('S','U','K',' ')}},	/* Sukuma */
--  {"suq",	{HB_TAG('S','U','R',' ')}},	/* Suri */
--  {"sv",	{HB_TAG('S','V','E',' ')}},	/* Swedish */
--  {"sva",	{HB_TAG('S','V','A',' ')}},	/* Svan */
--  {"sw",	{HB_TAG('S','W','K',' ')}},	/* Swahili [macrolanguage] */
--  {"swb",	{HB_TAG('C','M','R',' ')}},	/* Maore Comorian -> Comorian */
--  {"swc",	{HB_TAG('S','W','K',' ')}},	/* Congo Swahili -> Swahili */
--  {"swh",	{HB_TAG('S','W','K',' ')}},	/* Swahili */
--  {"swv",	{HB_TAG('M','A','W',' ')}},	/* Shekhawati -> Marwari */
--  {"sxu",	{HB_TAG('S','X','U',' ')}},	/* Upper Saxon */
--  {"syc",	{HB_TAG('S','Y','R',' ')}},	/* Classical Syriac -> Syriac */
--  {"syl",	{HB_TAG('S','Y','L',' ')}},	/* Sylheti */
--  {"syr",	{HB_TAG('S','Y','R',' ')}},	/* Syriac [macrolanguage] */
--  {"szl",	{HB_TAG('S','Z','L',' ')}},	/* Silesian */
--  {"ta",	{HB_TAG('T','A','M',' ')}},	/* Tamil */
--  {"taa",	{HB_TAG('A','T','H',' ')}},	/* Lower Tanana -> Athapaskan */
--  {"tab",	{HB_TAG('T','A','B',' ')}},	/* Tabassaran -> Tabasaran */
--  {"taq",	{HB_TAG('T','M','H',' ')}},	/* Tamasheq -> Tamashek */
--  {"tau",	{HB_TAG('A','T','H',' ')}},	/* Upper Tanana -> Athapaskan */
--  {"tcb",	{HB_TAG('A','T','H',' ')}},	/* Tanacross -> Athapaskan */
--  {"tce",	{HB_TAG('A','T','H',' ')}},	/* Southern Tutchone -> Athapaskan */
--  {"tcp",	{HB_TAG('Q','I','N',' ')}},	/* Tawr Chin -> Chin */
--  {"tcy",	{HB_TAG('T','U','L',' ')}},	/* Tulu -> Tumbuka */
--  {"tcz",	{HB_TAG('Q','I','N',' ')}},	/* Thado Chin -> Chin */
--  {"tdd",	{HB_TAG('T','D','D',' ')}},	/* Tai Nüa -> Dehong Dai */
--  {"tdx",	{HB_TAG('M','L','G',' ')}},	/* Tandroy-Mahafaly Malagasy -> Malagasy */
--  {"te",	{HB_TAG('T','E','L',' ')}},	/* Telugu */
--  {"tec",	{HB_TAG('K','A','L',' ')}},	/* Terik -> Kalenjin */
--  {"tem",	{HB_TAG('T','M','N',' ')}},	/* Timne -> Temne */
--  {"tet",	{HB_TAG('T','E','T',' ')}},	/* Tetum */
--  {"tfn",	{HB_TAG('A','T','H',' ')}},	/* Tanaina -> Athapaskan */
--  {"tg",	{HB_TAG('T','A','J',' ')}},	/* Tajik -> Tajiki */
--  {"tgj",	{HB_TAG('N','I','S',' ')}},	/* Tagin -> Nisi */
--  {"tgx",	{HB_TAG('A','T','H',' ')}},	/* Tagish -> Athapaskan */
--  {"th",	{HB_TAG('T','H','A',' ')}},	/* Thai */
--  {"tht",	{HB_TAG('A','T','H',' ')}},	/* Tahltan -> Athapaskan */
--  {"thv",	{HB_TAG('T','M','H',' ')}},	/* Tahaggart Tamahaq -> Tamashek */
--  {"thz",	{HB_TAG('T','M','H',' ')}},	/* Tayart Tamajeq -> Tamashek */
--  {"ti",	{HB_TAG('T','G','Y',' ')}},	/* Tigrinya */
--  {"tig",	{HB_TAG('T','G','R',' ')}},	/* Tigre */
--  {"tiv",	{HB_TAG('T','I','V',' ')}},	/* Tiv */
--  {"tk",	{HB_TAG('T','K','M',' ')}},	/* Turkmen */
--  {"tkg",	{HB_TAG('M','L','G',' ')}},	/* Tesaka Malagasy -> Malagasy */
--  {"tl",	{HB_TAG('T','G','L',' ')}},	/* Tagalog */
--  {"tmh",	{HB_TAG('T','M','H',' ')}},	/* Tamashek [macrolanguage] */
--  {"tmw",	{HB_TAG('M','L','Y',' ')}},	/* Temuan -> Malay */
--  {"tn",	{HB_TAG('T','N','A',' ')}},	/* Tswana */
--  {"tnf",	{HB_TAG('D','R','I',' ')}},	/* Tangshewi (retired code) -> Dari */
--  {"to",	{HB_TAG('T','G','N',' ')}},	/* Tonga (Tonga Islands) -> Tongan */
--  {"tod",	{HB_TAG('T','O','D','0')}},	/* Toma */
--  {"toi",	{HB_TAG('T','N','G',' ')}},	/* Tonga (Zambia) */
--  {"tol",	{HB_TAG('A','T','H',' ')}},	/* Tolowa -> Athapaskan */
--  {"tpi",	{HB_TAG('T','P','I',' ')}},	/* Tok Pisin */
--  {"tr",	{HB_TAG('T','R','K',' ')}},	/* Turkish */
--  {"tru",	{HB_TAG('T','U','A',' '),	/* Turoyo -> Turoyo Aramaic */
--		 HB_TAG('S','Y','R',' ')}},	/* Turoyo -> Syriac */
--  {"ts",	{HB_TAG('T','S','G',' ')}},	/* Tsonga */
--  {"tsj",	{HB_TAG('T','S','J',' ')}},	/* Tshangla */
--  {"tt",	{HB_TAG('T','A','T',' ')}},	/* Tatar */
--  {"ttm",	{HB_TAG('A','T','H',' ')}},	/* Northern Tutchone -> Athapaskan */
--  {"ttq",	{HB_TAG('T','M','H',' ')}},	/* Tawallammat Tamajaq -> Tamashek */
--  {"tum",	{HB_TAG('T','U','M',' ')}},	/* Tumbuka -> Tulu */
--  {"tuu",	{HB_TAG('A','T','H',' ')}},	/* Tututni -> Athapaskan */
--  {"tuy",	{HB_TAG('K','A','L',' ')}},	/* Tugen -> Kalenjin */
--  {"tvl",	{HB_TAG('T','V','L',' ')}},	/* Tuvalu */
--  {"tw",	{HB_TAG('T','W','I',' '),	/* Twi */
--		 HB_TAG('A','K','A',' ')}},	/* Twi -> Akan */
--  {"txc",	{HB_TAG('A','T','H',' ')}},	/* Tsetsaut -> Athapaskan */
--  {"txy",	{HB_TAG('M','L','G',' ')}},	/* Tanosy Malagasy -> Malagasy */
--  {"ty",	{HB_TAG('T','H','T',' ')}},	/* Tahitian */
--  {"tyv",	{HB_TAG('T','U','V',' ')}},	/* Tuvinian -> Tuvin */
--  {"tyz",	{HB_TAG('T','Y','Z',' ')}},	/* Tày */
--  {"tzm",	{HB_TAG('T','Z','M',' ')}},	/* Central Atlas Tamazight -> Tamazight */
--  {"tzo",	{HB_TAG('T','Z','O',' ')}},	/* Tzotzil */
--  {"ubl",	{HB_TAG('B','I','K',' ')}},	/* Buhi'non Bikol -> Bikol */
--  {"udm",	{HB_TAG('U','D','M',' ')}},	/* Udmurt */
--  {"ug",	{HB_TAG('U','Y','G',' ')}},	/* Uyghur */
--  {"uk",	{HB_TAG('U','K','R',' ')}},	/* Ukrainian */
--  {"umb",	{HB_TAG('U','M','B',' ')}},	/* Umbundu */
--  {"unr",	{HB_TAG('M','U','N',' ')}},	/* Mundari */
--  {"ur",	{HB_TAG('U','R','D',' ')}},	/* Urdu */
--  {"urk",	{HB_TAG('M','L','Y',' ')}},	/* Urak Lawoi' -> Malay */
--  {"uz",	{HB_TAG('U','Z','B',' ')}},	/* Uzbek [macrolanguage] */
--  {"uzn",	{HB_TAG('U','Z','B',' ')}},	/* Northern Uzbek -> Uzbek */
--  {"uzs",	{HB_TAG('U','Z','B',' ')}},	/* Southern Uzbek -> Uzbek */
--  {"ve",	{HB_TAG('V','E','N',' ')}},	/* Venda */
--  {"vec",	{HB_TAG('V','E','C',' ')}},	/* Venetian */
--  {"vi",	{HB_TAG('V','I','T',' ')}},	/* Vietnamese */
--  {"vkk",	{HB_TAG('M','L','Y',' ')}},	/* Kaur -> Malay */
--  {"vkt",	{HB_TAG('M','L','Y',' ')}},	/* Tenggarong Kutai Malay -> Malay */
--  {"vls",	{HB_TAG('F','L','E',' ')}},	/* Vlaams -> Dutch (Flemish) */
--  {"vmw",	{HB_TAG('M','A','K',' ')}},	/* Makhuwa */
--  {"vo",	{HB_TAG('V','O','L',' ')}},	/* Volapük */
--  {"vro",	{HB_TAG('V','R','O',' ')}},	/* Võro */
--  {"wa",	{HB_TAG('W','L','N',' ')}},	/* Walloon */
--  {"war",	{HB_TAG('W','A','R',' ')}},	/* Waray (Philippines) -> Waray-Waray */
--  {"wbm",	{HB_TAG('W','A',' ',' ')}},	/* Wa */
--  {"wbr",	{HB_TAG('W','A','G',' ')}},	/* Wagdi */
--  {"wlc",	{HB_TAG('C','M','R',' ')}},	/* Mwali Comorian -> Comorian */
--  {"wle",	{HB_TAG('S','I','G',' ')}},	/* Wolane -> Silte Gurage */
--  {"wlk",	{HB_TAG('A','T','H',' ')}},	/* Wailaki -> Athapaskan */
--  {"wni",	{HB_TAG('C','M','R',' ')}},	/* Ndzwani Comorian -> Comorian */
--  {"wo",	{HB_TAG('W','L','F',' ')}},	/* Wolof */
--  {"wry",	{HB_TAG('M','A','W',' ')}},	/* Merwari -> Marwari */
--  {"wsg",	{HB_TAG('G','O','N',' ')}},	/* Adilabad Gondi -> Gondi */
--  {"wtm",	{HB_TAG('W','T','M',' ')}},	/* Mewati */
--  {"wuu",	{HB_TAG('Z','H','S',' ')}},	/* Wu Chinese -> Chinese Simplified */
--  {"xal",	{HB_TAG('K','L','M',' '),	/* Kalmyk */
--		 HB_TAG('T','O','D',' ')}},	/* Kalmyk -> Todo */
--  {"xan",	{HB_TAG('S','E','K',' ')}},	/* Xamtanga -> Sekota */
--  {"xh",	{HB_TAG('X','H','S',' ')}},	/* Xhosa */
--  {"xjb",	{HB_TAG('X','J','B',' ')}},	/* Minjungbal -> Minjangbal */
--  {"xkf",	{HB_TAG('X','K','F',' ')}},	/* Khengkha */
--  {"xmm",	{HB_TAG('M','L','Y',' ')}},	/* Manado Malay -> Malay */
--  {"xmv",	{HB_TAG('M','L','G',' ')}},	/* Antankarana Malagasy -> Malagasy */
--  {"xmw",	{HB_TAG('M','L','G',' ')}},	/* Tsimihety Malagasy -> Malagasy */
--  {"xnr",	{HB_TAG('D','G','R',' ')}},	/* Kangri -> Dogri */
--  {"xog",	{HB_TAG('X','O','G',' ')}},	/* Soga */
--  {"xpe",	{HB_TAG('X','P','E',' ')}},	/* Liberia Kpelle -> Kpelle (Liberia) */
--  {"xsl",	{HB_TAG('S','S','L',' '),	/* South Slavey */
--		 HB_TAG('S','L','A',' '),	/* South Slavey -> Slavey */
--		 HB_TAG('A','T','H',' ')}},	/* South Slavey -> Athapaskan */
--  {"xst",	{HB_TAG('S','I','G',' ')}},	/* Silt'e (retired code) -> Silte Gurage */
--  {"xwo",	{HB_TAG('T','O','D',' ')}},	/* Written Oirat -> Todo */
--  {"yao",	{HB_TAG('Y','A','O',' ')}},	/* Yao */
--  {"yap",	{HB_TAG('Y','A','P',' ')}},	/* Yapese */
--  {"ybd",	{HB_TAG('A','R','K',' ')}},	/* Yangbye (retired code) -> Rakhine */
--  {"ydd",	{HB_TAG('J','I','I',' ')}},	/* Eastern Yiddish -> Yiddish */
--  {"yi",	{HB_TAG('J','I','I',' ')}},	/* Yiddish [macrolanguage] */
--  {"yih",	{HB_TAG('J','I','I',' ')}},	/* Western Yiddish -> Yiddish */
--  {"yo",	{HB_TAG('Y','B','A',' ')}},	/* Yoruba */
--  {"yos",	{HB_TAG('Q','I','N',' ')}},	/* Yos (retired code) -> Chin */
--  {"yrk",	{HB_TAG('T','N','E',' '),	/* Nenets -> Tundra Nenets */
--		 HB_TAG('F','N','E',' ')}},	/* Nenets -> Forest Nenets */
--  {"yue",	{HB_TAG('Z','H','H',' ')}},	/* Yue Chinese -> Chinese, Hong Kong SAR */
--  {"za",	{HB_TAG('Z','H','A',' ')}},	/* Zhuang [macrolanguage] */
--  {"zch",	{HB_TAG('Z','H','A',' ')}},	/* Central Hongshuihe Zhuang -> Zhuang */
--  {"zdj",	{HB_TAG('C','M','R',' ')}},	/* Ngazidja Comorian -> Comorian */
--  {"zea",	{HB_TAG('Z','E','A',' ')}},	/* Zeeuws -> Zealandic */
--  {"zeh",	{HB_TAG('Z','H','A',' ')}},	/* Eastern Hongshuihe Zhuang -> Zhuang */
--  {"zgb",	{HB_TAG('Z','H','A',' ')}},	/* Guibei Zhuang -> Zhuang */
--  {"zgh",	{HB_TAG('Z','G','H',' ')}},	/* Standard Moroccan Tamazight */
--  {"zgm",	{HB_TAG('Z','H','A',' ')}},	/* Minz Zhuang -> Zhuang */
--  {"zgn",	{HB_TAG('Z','H','A',' ')}},	/* Guibian Zhuang -> Zhuang */
--  {"zh",	{HB_TAG('Z','H','S',' ')}},	/* Chinese [macrolanguage] -> Chinese Simplified */
--  {"zhd",	{HB_TAG('Z','H','A',' ')}},	/* Dai Zhuang -> Zhuang */
--  {"zhn",	{HB_TAG('Z','H','A',' ')}},	/* Nong Zhuang -> Zhuang */
--  {"zlj",	{HB_TAG('Z','H','A',' ')}},	/* Liujiang Zhuang -> Zhuang */
--  {"zlm",	{HB_TAG('M','L','Y',' ')}},	/* Malay */
--  {"zln",	{HB_TAG('Z','H','A',' ')}},	/* Lianshan Zhuang -> Zhuang */
--  {"zlq",	{HB_TAG('Z','H','A',' ')}},	/* Liuqian Zhuang -> Zhuang */
--  {"zmi",	{HB_TAG('M','L','Y',' ')}},	/* Negeri Sembilan Malay -> Malay */
--  {"zne",	{HB_TAG('Z','N','D',' ')}},	/* Zande */
--  {"zom",	{HB_TAG('Q','I','N',' ')}},	/* Zou -> Chin */
--  {"zqe",	{HB_TAG('Z','H','A',' ')}},	/* Qiubei Zhuang -> Zhuang */
--  {"zsm",	{HB_TAG('M','L','Y',' ')}},	/* Standard Malay -> Malay */
--  {"zu",	{HB_TAG('Z','U','L',' ')}},	/* Zulu */
--  {"zum",	{HB_TAG('L','R','C',' ')}},	/* Kumzari -> Luri */
--  {"zyb",	{HB_TAG('Z','H','A',' ')}},	/* Yongbei Zhuang -> Zhuang */
--  {"zyg",	{HB_TAG('Z','H','A',' ')}},	/* Yang Zhuang -> Zhuang */
--  {"zyj",	{HB_TAG('Z','H','A',' ')}},	/* Youjiang Zhuang -> Zhuang */
--  {"zyn",	{HB_TAG('Z','H','A',' ')}},	/* Yongnan Zhuang -> Zhuang */
--  {"zza",	{HB_TAG('Z','Z','A',' ')}},	/* Zazaki [macrolanguage] */
--  {"zzj",	{HB_TAG('Z','H','A',' ')}},	/* Zuojiang Zhuang -> Zhuang */
-+  {"aa",	HB_TAG('A','F','R',' ')},	/* Afar */
-+  {"aae",	HB_TAG('S','Q','I',' ')},	/* Arbëreshë Albanian -> Albanian */
-+  {"aao",	HB_TAG('A','R','A',' ')},	/* Algerian Saharan Arabic -> Arabic */
-+  {"aat",	HB_TAG('S','Q','I',' ')},	/* Arvanitika Albanian -> Albanian */
-+  {"ab",	HB_TAG('A','B','K',' ')},	/* Abkhazian */
-+  {"abh",	HB_TAG('A','R','A',' ')},	/* Tajiki Arabic -> Arabic */
-+  {"abq",	HB_TAG('A','B','A',' ')},	/* Abaza */
-+  {"abv",	HB_TAG('A','R','A',' ')},	/* Baharna Arabic -> Arabic */
-+  {"acf",	HB_TAG('F','A','N',' ')},	/* Saint Lucian Creole French -> French Antillean */
-+/*{"ach",	HB_TAG('A','C','H',' ')},*/	/* Acoli -> Acholi */
-+  {"acm",	HB_TAG('A','R','A',' ')},	/* Mesopotamian Arabic -> Arabic */
-+  {"acq",	HB_TAG('A','R','A',' ')},	/* Ta'izzi-Adeni Arabic -> Arabic */
-+/*{"acr",	HB_TAG('A','C','R',' ')},*/	/* Achi */
-+  {"acw",	HB_TAG('A','R','A',' ')},	/* Hijazi Arabic -> Arabic */
-+  {"acx",	HB_TAG('A','R','A',' ')},	/* Omani Arabic -> Arabic */
-+  {"acy",	HB_TAG('A','R','A',' ')},	/* Cypriot Arabic -> Arabic */
-+  {"ada",	HB_TAG('D','N','G',' ')},	/* Adangme -> Dangme */
-+  {"adf",	HB_TAG('A','R','A',' ')},	/* Dhofari Arabic -> Arabic */
-+  {"adp",	HB_TAG('D','Z','N',' ')},	/* Adap (retired code) -> Dzongkha */
-+/*{"ady",	HB_TAG('A','D','Y',' ')},*/	/* Adyghe */
-+  {"aeb",	HB_TAG('A','R','A',' ')},	/* Tunisian Arabic -> Arabic */
-+  {"aec",	HB_TAG('A','R','A',' ')},	/* Saidi Arabic -> Arabic */
-+  {"af",	HB_TAG('A','F','K',' ')},	/* Afrikaans */
-+  {"afb",	HB_TAG('A','R','A',' ')},	/* Gulf Arabic -> Arabic */
-+  {"ahg",	HB_TAG('A','G','W',' ')},	/* Qimant -> Agaw */
-+  {"aht",	HB_TAG('A','T','H',' ')},	/* Ahtena -> Athapaskan */
-+  {"aii",	HB_TAG('S','W','A',' ')},	/* Assyrian Neo-Aramaic -> Swadaya Aramaic */
-+  {"aii",	HB_TAG('S','Y','R',' ')},	/* Assyrian Neo-Aramaic -> Syriac */
-+/*{"aio",	HB_TAG('A','I','O',' ')},*/	/* Aiton */
-+  {"aiw",	HB_TAG('A','R','I',' ')},	/* Aari */
-+  {"ajp",	HB_TAG('A','R','A',' ')},	/* South Levantine Arabic -> Arabic */
-+  {"ak",	HB_TAG('A','K','A',' ')},	/* Akan [macrolanguage] */
-+  {"ak",	HB_TAG('T','W','I',' ')},	/* Akan [macrolanguage] -> Twi */
-+  {"aln",	HB_TAG('S','Q','I',' ')},	/* Gheg Albanian -> Albanian */
-+  {"als",	HB_TAG('S','Q','I',' ')},	/* Tosk Albanian -> Albanian */
-+/*{"alt",	HB_TAG('A','L','T',' ')},*/	/* Southern Altai -> Altai */
-+  {"am",	HB_TAG('A','M','H',' ')},	/* Amharic */
-+  {"amf",	HB_TAG('H','B','N',' ')},	/* Hamer-Banna -> Hammer-Banna */
-+  {"amw",	HB_TAG('S','Y','R',' ')},	/* Western Neo-Aramaic -> Syriac */
-+  {"an",	HB_TAG('A','R','G',' ')},	/* Aragonese */
-+/*{"ang",	HB_TAG('A','N','G',' ')},*/	/* Old English (ca. 450-1100) -> Anglo-Saxon */
-+  {"apc",	HB_TAG('A','R','A',' ')},	/* North Levantine Arabic -> Arabic */
-+  {"apd",	HB_TAG('A','R','A',' ')},	/* Sudanese Arabic -> Arabic */
-+  {"apj",	HB_TAG('A','T','H',' ')},	/* Jicarilla Apache -> Athapaskan */
-+  {"apk",	HB_TAG('A','T','H',' ')},	/* Kiowa Apache -> Athapaskan */
-+  {"apl",	HB_TAG('A','T','H',' ')},	/* Lipan Apache -> Athapaskan */
-+  {"apm",	HB_TAG('A','T','H',' ')},	/* Mescalero-Chiricahua Apache -> Athapaskan */
-+  {"apw",	HB_TAG('A','T','H',' ')},	/* Western Apache -> Athapaskan */
-+  {"ar",	HB_TAG('A','R','A',' ')},	/* Arabic [macrolanguage] */
-+  {"arb",	HB_TAG('A','R','A',' ')},	/* Standard Arabic -> Arabic */
-+  {"arn",	HB_TAG('M','A','P',' ')},	/* Mapudungun */
-+  {"arq",	HB_TAG('A','R','A',' ')},	/* Algerian Arabic -> Arabic */
-+  {"ars",	HB_TAG('A','R','A',' ')},	/* Najdi Arabic -> Arabic */
-+  {"ary",	HB_TAG('M','O','R',' ')},	/* Moroccan Arabic -> Moroccan */
-+  {"arz",	HB_TAG('A','R','A',' ')},	/* Egyptian Arabic -> Arabic */
-+  {"as",	HB_TAG('A','S','M',' ')},	/* Assamese */
-+/*{"ast",	HB_TAG('A','S','T',' ')},*/	/* Asturian */
-+/*{"ath",	HB_TAG('A','T','H',' ')},*/	/* Athapascan [family] -> Athapaskan */
-+  {"atj",	HB_TAG('R','C','R',' ')},	/* Atikamekw -> R-Cree */
-+  {"atv",	HB_TAG('A','L','T',' ')},	/* Northern Altai -> Altai */
-+  {"auz",	HB_TAG('A','R','A',' ')},	/* Uzbeki Arabic -> Arabic */
-+  {"av",	HB_TAG('A','V','R',' ')},	/* Avaric -> Avar */
-+  {"avl",	HB_TAG('A','R','A',' ')},	/* Eastern Egyptian Bedawi Arabic -> Arabic */
-+/*{"awa",	HB_TAG('A','W','A',' ')},*/	/* Awadhi */
-+  {"ay",	HB_TAG('A','Y','M',' ')},	/* Aymara [macrolanguage] */
-+  {"ayc",	HB_TAG('A','Y','M',' ')},	/* Southern Aymara -> Aymara */
-+  {"ayh",	HB_TAG('A','R','A',' ')},	/* Hadrami Arabic -> Arabic */
-+  {"ayl",	HB_TAG('A','R','A',' ')},	/* Libyan Arabic -> Arabic */
-+  {"ayn",	HB_TAG('A','R','A',' ')},	/* Sanaani Arabic -> Arabic */
-+  {"ayp",	HB_TAG('A','R','A',' ')},	/* North Mesopotamian Arabic -> Arabic */
-+  {"ayr",	HB_TAG('A','Y','M',' ')},	/* Central Aymara -> Aymara */
-+  {"az",	HB_TAG('A','Z','E',' ')},	/* Azerbaijani [macrolanguage] */
-+/*{"azb",	HB_TAG('A','Z','B',' ')},*/	/* South Azerbaijani -> Torki */
-+  {"azj",	HB_TAG('A','Z','E',' ')},	/* North Azerbaijani -> Azerbaijani */
-+  {"ba",	HB_TAG('B','S','H',' ')},	/* Bashkir */
-+  {"bad",	HB_TAG('B','A','D','0')},	/* Banda [family] */
-+  {"bai",	HB_TAG('B','M','L',' ')},	/* Bamileke [family] */
-+  {"bal",	HB_TAG('B','L','I',' ')},	/* Baluchi [macrolanguage] */
-+/*{"ban",	HB_TAG('B','A','N',' ')},*/	/* Balinese */
-+/*{"bar",	HB_TAG('B','A','R',' ')},*/	/* Bavarian */
-+/*{"bbc",	HB_TAG('B','B','C',' ')},*/	/* Batak Toba */
-+  {"bbz",	HB_TAG('A','R','A',' ')},	/* Babalia Creole Arabic -> Arabic */
-+  {"bcc",	HB_TAG('B','L','I',' ')},	/* Southern Balochi -> Baluchi */
-+  {"bci",	HB_TAG('B','A','U',' ')},	/* Baoulé -> Baulé */
-+  {"bcl",	HB_TAG('B','I','K',' ')},	/* Central Bikol -> Bikol */
-+  {"bcq",	HB_TAG('B','C','H',' ')},	/* Bench */
-+  {"bcr",	HB_TAG('A','T','H',' ')},	/* Babine -> Athapaskan */
-+/*{"bdy",	HB_TAG('B','D','Y',' ')},*/	/* Bandjalang */
-+  {"be",	HB_TAG('B','E','L',' ')},	/* Belarusian -> Belarussian */
-+  {"bea",	HB_TAG('A','T','H',' ')},	/* Beaver -> Athapaskan */
-+  {"beb",	HB_TAG('B','T','I',' ')},	/* Bebele -> Beti */
-+/*{"bem",	HB_TAG('B','E','M',' ')},*/	/* Bemba (Zambia) */
-+  {"ber",	HB_TAG('B','B','R',' ')},	/* Berber [family] */
-+  {"bfq",	HB_TAG('B','A','D',' ')},	/* Badaga */
-+  {"bft",	HB_TAG('B','L','T',' ')},	/* Balti */
-+  {"bfu",	HB_TAG('L','A','H',' ')},	/* Gahri -> Lahuli */
-+  {"bfy",	HB_TAG('B','A','G',' ')},	/* Bagheli -> Baghelkhandi */
-+  {"bg",	HB_TAG('B','G','R',' ')},	/* Bulgarian */
-+/*{"bgc",	HB_TAG('B','G','C',' ')},*/	/* Haryanvi */
-+  {"bgn",	HB_TAG('B','L','I',' ')},	/* Western Balochi -> Baluchi */
-+  {"bgp",	HB_TAG('B','L','I',' ')},	/* Eastern Balochi -> Baluchi */
-+/*{"bgq",	HB_TAG('B','G','Q',' ')},*/	/* Bagri */
-+  {"bgr",	HB_TAG('Q','I','N',' ')},	/* Bawm Chin -> Chin */
-+  {"bhb",	HB_TAG('B','H','I',' ')},	/* Bhili */
-+/*{"bhi",	HB_TAG('B','H','I',' ')},*/	/* Bhilali -> Bhili */
-+  {"bhk",	HB_TAG('B','I','K',' ')},	/* Albay Bicolano (retired code) -> Bikol */
-+/*{"bho",	HB_TAG('B','H','O',' ')},*/	/* Bhojpuri */
-+  {"bhr",	HB_TAG('M','L','G',' ')},	/* Bara Malagasy -> Malagasy */
-+  {"bi",	HB_TAG('B','I','S',' ')},	/* Bislama */
-+/*{"bik",	HB_TAG('B','I','K',' ')},*/	/* Bikol [macrolanguage] */
-+  {"bin",	HB_TAG('E','D','O',' ')},	/* Edo */
-+/*{"bjj",	HB_TAG('B','J','J',' ')},*/	/* Kanauji */
-+  {"bjn",	HB_TAG('M','L','Y',' ')},	/* Banjar -> Malay */
-+  {"bjq",	HB_TAG('M','L','G',' ')},	/* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
-+  {"bjt",	HB_TAG('B','L','N',' ')},	/* Balanta-Ganja -> Balante */
-+  {"bla",	HB_TAG('B','K','F',' ')},	/* Siksika -> Blackfoot */
-+  {"ble",	HB_TAG('B','L','N',' ')},	/* Balanta-Kentohe -> Balante */
-+/*{"blk",	HB_TAG('B','L','K',' ')},*/	/* Pa’o Karen */
-+  {"bln",	HB_TAG('B','I','K',' ')},	/* Southern Catanduanes Bikol -> Bikol */
-+  {"bm",	HB_TAG('B','M','B',' ')},	/* Bambara (Bamanankan) */
-+  {"bmm",	HB_TAG('M','L','G',' ')},	/* Northern Betsimisaraka Malagasy -> Malagasy */
-+  {"bn",	HB_TAG('B','E','N',' ')},	/* Bengali */
-+  {"bo",	HB_TAG('T','I','B',' ')},	/* Tibetan */
-+/*{"bpy",	HB_TAG('B','P','Y',' ')},*/	/* Bishnupriya -> Bishnupriya Manipuri */
-+  {"bqi",	HB_TAG('L','R','C',' ')},	/* Bakhtiari -> Luri */
-+  {"br",	HB_TAG('B','R','E',' ')},	/* Breton */
-+  {"bra",	HB_TAG('B','R','I',' ')},	/* Braj -> Braj Bhasha */
-+/*{"brh",	HB_TAG('B','R','H',' ')},*/	/* Brahui */
-+/*{"brx",	HB_TAG('B','R','X',' ')},*/	/* Bodo (India) */
-+  {"bs",	HB_TAG('B','O','S',' ')},	/* Bosnian */
-+/*{"bsk",	HB_TAG('B','S','K',' ')},*/	/* Burushaski */
-+  {"btb",	HB_TAG('B','T','I',' ')},	/* Beti (Cameroon) (retired code) */
-+  {"btj",	HB_TAG('M','L','Y',' ')},	/* Bacanese Malay -> Malay */
-+  {"bto",	HB_TAG('B','I','K',' ')},	/* Rinconada Bikol -> Bikol */
-+/*{"bts",	HB_TAG('B','T','S',' ')},*/	/* Batak Simalungun */
-+/*{"bug",	HB_TAG('B','U','G',' ')},*/	/* Buginese -> Bugis */
-+  {"bum",	HB_TAG('B','T','I',' ')},	/* Bulu (Cameroon) -> Beti */
-+  {"bve",	HB_TAG('M','L','Y',' ')},	/* Berau Malay -> Malay */
-+  {"bvu",	HB_TAG('M','L','Y',' ')},	/* Bukit Malay -> Malay */
-+  {"bxk",	HB_TAG('L','U','H',' ')},	/* Bukusu -> Luyia */
-+  {"bxp",	HB_TAG('B','T','I',' ')},	/* Bebil -> Beti */
-+  {"bxr",	HB_TAG('R','B','U',' ')},	/* Russia Buriat -> Russian Buriat */
-+  {"byn",	HB_TAG('B','I','L',' ')},	/* Bilin -> Bilen */
-+/*{"byv",	HB_TAG('B','Y','V',' ')},*/	/* Medumba */
-+  {"bzc",	HB_TAG('M','L','G',' ')},	/* Southern Betsimisaraka Malagasy -> Malagasy */
-+  {"ca",	HB_TAG('C','A','T',' ')},	/* Catalan */
-+  {"caf",	HB_TAG('C','R','R',' ')},	/* Southern Carrier -> Carrier */
-+  {"caf",	HB_TAG('A','T','H',' ')},	/* Southern Carrier -> Athapaskan */
-+/*{"cak",	HB_TAG('C','A','K',' ')},*/	/* Kaqchikel */
-+/*{"cbk",	HB_TAG('C','B','K',' ')},*/	/* Chavacano -> Zamboanga Chavacano */
-+  {"cbl",	HB_TAG('Q','I','N',' ')},	/* Bualkhaw Chin -> Chin */
-+  {"cco",	HB_TAG('C','C','H','N')},	/* Comaltepec Chinantec -> Chinantec */
-+  {"ccq",	HB_TAG('A','R','K',' ')},	/* Chaungtha (retired code) -> Rakhine */
-+  {"cdo",	HB_TAG('Z','H','S',' ')},	/* Min Dong Chinese -> Chinese Simplified */
-+  {"ce",	HB_TAG('C','H','E',' ')},	/* Chechen */
-+/*{"ceb",	HB_TAG('C','E','B',' ')},*/	/* Cebuano */
-+  {"cfm",	HB_TAG('H','A','L',' ')},	/* Halam (Falam Chin) */
-+/*{"cgg",	HB_TAG('C','G','G',' ')},*/	/* Chiga */
-+  {"ch",	HB_TAG('C','H','A',' ')},	/* Chamorro */
-+  {"chj",	HB_TAG('C','C','H','N')},	/* Ojitlán Chinantec -> Chinantec */
-+  {"chk",	HB_TAG('C','H','K','0')},	/* Chuukese */
-+/*{"cho",	HB_TAG('C','H','O',' ')},*/	/* Choctaw */
-+  {"chp",	HB_TAG('C','H','P',' ')},	/* Chipewyan */
-+  {"chp",	HB_TAG('S','A','Y',' ')},	/* Chipewyan -> Sayisi */
-+  {"chp",	HB_TAG('A','T','H',' ')},	/* Chipewyan -> Athapaskan */
-+  {"chq",	HB_TAG('C','C','H','N')},	/* Quiotepec Chinantec -> Chinantec */
-+/*{"chr",	HB_TAG('C','H','R',' ')},*/	/* Cherokee */
-+/*{"chy",	HB_TAG('C','H','Y',' ')},*/	/* Cheyenne */
-+  {"chz",	HB_TAG('C','C','H','N')},	/* Ozumacín Chinantec -> Chinantec */
-+  {"ciw",	HB_TAG('O','J','B',' ')},	/* Chippewa -> Ojibway */
-+/*{"cja",	HB_TAG('C','J','A',' ')},*/	/* Western Cham */
-+/*{"cjm",	HB_TAG('C','J','M',' ')},*/	/* Eastern Cham */
-+  {"cjy",	HB_TAG('Z','H','S',' ')},	/* Jinyu Chinese -> Chinese Simplified */
-+  {"cka",	HB_TAG('Q','I','N',' ')},	/* Khumi Awa Chin (retired code) -> Chin */
-+  {"ckb",	HB_TAG('K','U','R',' ')},	/* Central Kurdish -> Kurdish */
-+  {"ckt",	HB_TAG('C','H','K',' ')},	/* Chukot -> Chukchi */
-+  {"clc",	HB_TAG('A','T','H',' ')},	/* Chilcotin -> Athapaskan */
-+  {"cld",	HB_TAG('S','Y','R',' ')},	/* Chaldean Neo-Aramaic -> Syriac */
-+  {"cle",	HB_TAG('C','C','H','N')},	/* Lealao Chinantec -> Chinantec */
-+  {"cmn",	HB_TAG('Z','H','S',' ')},	/* Mandarin Chinese -> Chinese Simplified */
-+  {"cmr",	HB_TAG('Q','I','N',' ')},	/* Mro-Khimi Chin -> Chin */
-+  {"cnb",	HB_TAG('Q','I','N',' ')},	/* Chinbon Chin -> Chin */
-+  {"cnh",	HB_TAG('Q','I','N',' ')},	/* Hakha Chin -> Chin */
-+  {"cnk",	HB_TAG('Q','I','N',' ')},	/* Khumi Chin -> Chin */
-+  {"cnl",	HB_TAG('C','C','H','N')},	/* Lalana Chinantec -> Chinantec */
-+  {"cnt",	HB_TAG('C','C','H','N')},	/* Tepetotutla Chinantec -> Chinantec */
-+  {"cnw",	HB_TAG('Q','I','N',' ')},	/* Ngawn Chin -> Chin */
-+  {"co",	HB_TAG('C','O','S',' ')},	/* Corsican */
-+  {"coa",	HB_TAG('M','L','Y',' ')},	/* Cocos Islands Malay -> Malay */
-+/*{"cop",	HB_TAG('C','O','P',' ')},*/	/* Coptic */
-+  {"coq",	HB_TAG('A','T','H',' ')},	/* Coquille -> Athapaskan */
-+  {"cpa",	HB_TAG('C','C','H','N')},	/* Palantla Chinantec -> Chinantec */
-+  {"cpe",	HB_TAG('C','P','P',' ')},	/* English-based creoles and pidgins [family] -> Creoles */
-+  {"cpf",	HB_TAG('C','P','P',' ')},	/* French-based creoles and pidgins [family] -> Creoles */
-+/*{"cpp",	HB_TAG('C','P','P',' ')},*/	/* Portuguese-based creoles and pidgins [family] -> Creoles */
-+  {"cpx",	HB_TAG('Z','H','S',' ')},	/* Pu-Xian Chinese -> Chinese Simplified */
-+  {"cqd",	HB_TAG('H','M','N',' ')},	/* Chuanqiandian Cluster Miao -> Hmong */
-+  {"cqu",	HB_TAG('Q','U','H',' ')},	/* Chilean Quechua (retired code) -> Quechua (Bolivia) */
-+  {"cr",	HB_TAG('C','R','E',' ')},	/* Cree [macrolanguage] */
-+  {"cr",	HB_TAG('Y','C','R',' ')},	/* Cree [macrolanguage] -> Y-Cree */
-+  {"crh",	HB_TAG('C','R','T',' ')},	/* Crimean Tatar */
-+  {"crj",	HB_TAG('E','C','R',' ')},	/* Southern East Cree -> Eastern Cree */
-+  {"crk",	HB_TAG('W','C','R',' ')},	/* Plains Cree -> West-Cree */
-+  {"crl",	HB_TAG('E','C','R',' ')},	/* Northern East Cree -> Eastern Cree */
-+  {"crm",	HB_TAG('M','C','R',' ')},	/* Moose Cree */
-+  {"crm",	HB_TAG('L','C','R',' ')},	/* Moose Cree -> L-Cree */
-+  {"crp",	HB_TAG('C','P','P',' ')},	/* Creoles and pidgins [family] -> Creoles */
-+  {"crx",	HB_TAG('C','R','R',' ')},	/* Carrier */
-+  {"crx",	HB_TAG('A','T','H',' ')},	/* Carrier -> Athapaskan */
-+  {"cs",	HB_TAG('C','S','Y',' ')},	/* Czech */
-+  {"csa",	HB_TAG('C','C','H','N')},	/* Chiltepec Chinantec -> Chinantec */
-+/*{"csb",	HB_TAG('C','S','B',' ')},*/	/* Kashubian */
-+  {"csh",	HB_TAG('Q','I','N',' ')},	/* Asho Chin -> Chin */
-+  {"cso",	HB_TAG('C','C','H','N')},	/* Sochiapam Chinantec -> Chinantec */
-+  {"csw",	HB_TAG('N','C','R',' ')},	/* Swampy Cree -> N-Cree */
-+  {"csw",	HB_TAG('N','H','C',' ')},	/* Swampy Cree -> Norway House Cree */
-+  {"csy",	HB_TAG('Q','I','N',' ')},	/* Siyin Chin -> Chin */
-+  {"ctc",	HB_TAG('A','T','H',' ')},	/* Chetco -> Athapaskan */
-+  {"ctd",	HB_TAG('Q','I','N',' ')},	/* Tedim Chin -> Chin */
-+  {"cte",	HB_TAG('C','C','H','N')},	/* Tepinapa Chinantec -> Chinantec */
-+/*{"ctg",	HB_TAG('C','T','G',' ')},*/	/* Chittagonian */
-+  {"ctl",	HB_TAG('C','C','H','N')},	/* Tlacoatzintepec Chinantec -> Chinantec */
-+  {"cts",	HB_TAG('B','I','K',' ')},	/* Northern Catanduanes Bikol -> Bikol */
-+  {"cu",	HB_TAG('C','S','L',' ')},	/* Church Slavonic */
-+  {"cuc",	HB_TAG('C','C','H','N')},	/* Usila Chinantec -> Chinantec */
-+/*{"cuk",	HB_TAG('C','U','K',' ')},*/	/* San Blas Kuna */
-+  {"cv",	HB_TAG('C','H','U',' ')},	/* Chuvash */
-+  {"cvn",	HB_TAG('C','C','H','N')},	/* Valle Nacional Chinantec -> Chinantec */
-+  {"cwd",	HB_TAG('D','C','R',' ')},	/* Woods Cree */
-+  {"cwd",	HB_TAG('T','C','R',' ')},	/* Woods Cree -> TH-Cree */
-+  {"cy",	HB_TAG('W','E','L',' ')},	/* Welsh */
-+  {"czh",	HB_TAG('Z','H','S',' ')},	/* Huizhou Chinese -> Chinese Simplified */
-+  {"czo",	HB_TAG('Z','H','S',' ')},	/* Min Zhong Chinese -> Chinese Simplified */
-+  {"czt",	HB_TAG('Q','I','N',' ')},	/* Zotung Chin -> Chin */
-+  {"da",	HB_TAG('D','A','N',' ')},	/* Danish */
-+  {"dao",	HB_TAG('Q','I','N',' ')},	/* Daai Chin -> Chin */
-+  {"dap",	HB_TAG('N','I','S',' ')},	/* Nisi (India) (retired code) */
-+/*{"dar",	HB_TAG('D','A','R',' ')},*/	/* Dargwa */
-+/*{"dax",	HB_TAG('D','A','X',' ')},*/	/* Dayi */
-+  {"de",	HB_TAG('D','E','U',' ')},	/* German */
-+  {"den",	HB_TAG('S','L','A',' ')},	/* Slave (Athapascan) [macrolanguage] -> Slavey */
-+  {"den",	HB_TAG('A','T','H',' ')},	/* Slave (Athapascan) [macrolanguage] -> Athapaskan */
-+/*{"dgo",	HB_TAG('D','G','O',' ')},*/	/* Dogri */
-+  {"dgr",	HB_TAG('A','T','H',' ')},	/* Dogrib -> Athapaskan */
-+  {"dhd",	HB_TAG('M','A','W',' ')},	/* Dhundari -> Marwari */
-+/*{"dhg",	HB_TAG('D','H','G',' ')},*/	/* Dhangu */
-+  {"dib",	HB_TAG('D','N','K',' ')},	/* South Central Dinka -> Dinka */
-+  {"dik",	HB_TAG('D','N','K',' ')},	/* Southwestern Dinka -> Dinka */
-+  {"din",	HB_TAG('D','N','K',' ')},	/* Dinka [macrolanguage] */
-+  {"dip",	HB_TAG('D','N','K',' ')},	/* Northeastern Dinka -> Dinka */
-+/*{"diq",	HB_TAG('D','I','Q',' ')},*/	/* Dimli */
-+  {"diw",	HB_TAG('D','N','K',' ')},	/* Northwestern Dinka -> Dinka */
-+  {"dje",	HB_TAG('D','J','R',' ')},	/* Zarma */
-+  {"djr",	HB_TAG('D','J','R','0')},	/* Djambarrpuyngu */
-+  {"dks",	HB_TAG('D','N','K',' ')},	/* Southeastern Dinka -> Dinka */
-+  {"dng",	HB_TAG('D','U','N',' ')},	/* Dungan */
-+/*{"dnj",	HB_TAG('D','N','J',' ')},*/	/* Dan */
-+  {"doi",	HB_TAG('D','G','R',' ')},	/* Dogri [macrolanguage] */
-+  {"drh",	HB_TAG('M','N','G',' ')},	/* Darkhat (retired code) -> Mongolian */
-+  {"drw",	HB_TAG('D','R','I',' ')},	/* Darwazi (retired code) -> Dari */
-+  {"dsb",	HB_TAG('L','S','B',' ')},	/* Lower Sorbian */
-+  {"dty",	HB_TAG('N','E','P',' ')},	/* Dotyali -> Nepali */
-+/*{"duj",	HB_TAG('D','U','J',' ')},*/	/* Dhuwal (retired code) */
-+  {"dup",	HB_TAG('M','L','Y',' ')},	/* Duano -> Malay */
-+  {"dv",	HB_TAG('D','I','V',' ')},	/* Divehi (Dhivehi, Maldivian) */
-+  {"dv",	HB_TAG('D','H','V',' ')},	/* Divehi (Dhivehi, Maldivian) (deprecated) */
-+  {"dwu",	HB_TAG('D','U','J',' ')},	/* Dhuwal */
-+  {"dwy",	HB_TAG('D','U','J',' ')},	/* Dhuwaya -> Dhuwal */
-+  {"dyu",	HB_TAG('J','U','L',' ')},	/* Dyula -> Jula */
-+  {"dz",	HB_TAG('D','Z','N',' ')},	/* Dzongkha */
-+  {"ee",	HB_TAG('E','W','E',' ')},	/* Ewe */
-+/*{"efi",	HB_TAG('E','F','I',' ')},*/	/* Efik */
-+  {"ekk",	HB_TAG('E','T','I',' ')},	/* Standard Estonian -> Estonian */
-+  {"el",	HB_TAG('E','L','L',' ')},	/* Modern Greek (1453-) -> Greek */
-+  {"emk",	HB_TAG('E','M','K',' ')},	/* Eastern Maninkakan */
-+  {"emk",	HB_TAG('M','N','K',' ')},	/* Eastern Maninkakan -> Maninka */
-+  {"en",	HB_TAG('E','N','G',' ')},	/* English */
-+  {"enb",	HB_TAG('K','A','L',' ')},	/* Markweeta -> Kalenjin */
-+  {"enf",	HB_TAG('F','N','E',' ')},	/* Forest Enets -> Forest Nenets */
-+  {"enh",	HB_TAG('T','N','E',' ')},	/* Tundra Enets -> Tundra Nenets */
-+  {"eo",	HB_TAG('N','T','O',' ')},	/* Esperanto */
-+  {"es",	HB_TAG('E','S','P',' ')},	/* Spanish */
-+  {"esg",	HB_TAG('G','O','N',' ')},	/* Aheri Gondi -> Gondi */
-+  {"esi",	HB_TAG('I','P','K',' ')},	/* North Alaskan Inupiatun -> Inupiat */
-+  {"esk",	HB_TAG('I','P','K',' ')},	/* Northwest Alaska Inupiatun -> Inupiat */
-+/*{"esu",	HB_TAG('E','S','U',' ')},*/	/* Central Yupik */
-+  {"et",	HB_TAG('E','T','I',' ')},	/* Estonian [macrolanguage] */
-+  {"eto",	HB_TAG('B','T','I',' ')},	/* Eton (Cameroon) -> Beti */
-+  {"eu",	HB_TAG('E','U','Q',' ')},	/* Basque */
-+  {"eve",	HB_TAG('E','V','N',' ')},	/* Even */
-+  {"evn",	HB_TAG('E','V','K',' ')},	/* Evenki */
-+  {"ewo",	HB_TAG('B','T','I',' ')},	/* Ewondo -> Beti */
-+  {"eyo",	HB_TAG('K','A','L',' ')},	/* Keiyo -> Kalenjin */
-+  {"fa",	HB_TAG('F','A','R',' ')},	/* Persian [macrolanguage] */
-+  {"fan",	HB_TAG('F','A','N','0')},	/* Fang (Equatorial Guinea) */
-+/*{"fat",	HB_TAG('F','A','T',' ')},*/	/* Fanti */
-+  {"fbl",	HB_TAG('B','I','K',' ')},	/* West Albay Bikol -> Bikol */
-+  {"ff",	HB_TAG('F','U','L',' ')},	/* Fulah [macrolanguage] */
-+  {"ffm",	HB_TAG('F','U','L',' ')},	/* Maasina Fulfulde -> Fulah */
-+  {"fi",	HB_TAG('F','I','N',' ')},	/* Finnish */
-+  {"fil",	HB_TAG('P','I','L',' ')},	/* Filipino */
-+  {"fj",	HB_TAG('F','J','I',' ')},	/* Fijian */
-+  {"flm",	HB_TAG('H','A','L',' ')},	/* Halam (Falam Chin) (retired code) */
-+  {"flm",	HB_TAG('Q','I','N',' ')},	/* Falam Chin (retired code) -> Chin */
-+/*{"fmp",	HB_TAG('F','M','P',' ')},*/	/* Fe’fe’ */
-+  {"fo",	HB_TAG('F','O','S',' ')},	/* Faroese */
-+/*{"fon",	HB_TAG('F','O','N',' ')},*/	/* Fon */
-+  {"fr",	HB_TAG('F','R','A',' ')},	/* French */
-+/*{"frc",	HB_TAG('F','R','C',' ')},*/	/* Cajun French */
-+/*{"frp",	HB_TAG('F','R','P',' ')},*/	/* Arpitan */
-+  {"fub",	HB_TAG('F','U','L',' ')},	/* Adamawa Fulfulde -> Fulah */
-+  {"fuc",	HB_TAG('F','U','L',' ')},	/* Pulaar -> Fulah */
-+  {"fue",	HB_TAG('F','U','L',' ')},	/* Borgu Fulfulde -> Fulah */
-+  {"fuf",	HB_TAG('F','T','A',' ')},	/* Pular -> Futa */
-+  {"fuh",	HB_TAG('F','U','L',' ')},	/* Western Niger Fulfulde -> Fulah */
-+  {"fui",	HB_TAG('F','U','L',' ')},	/* Bagirmi Fulfulde -> Fulah */
-+  {"fuq",	HB_TAG('F','U','L',' ')},	/* Central-Eastern Niger Fulfulde -> Fulah */
-+  {"fur",	HB_TAG('F','R','L',' ')},	/* Friulian */
-+/*{"fuv",	HB_TAG('F','U','V',' ')},*/	/* Nigerian Fulfulde */
-+  {"fy",	HB_TAG('F','R','I',' ')},	/* Western Frisian -> Frisian */
-+  {"ga",	HB_TAG('I','R','I',' ')},	/* Irish */
-+  {"gaa",	HB_TAG('G','A','D',' ')},	/* Ga */
-+/*{"gag",	HB_TAG('G','A','G',' ')},*/	/* Gagauz */
-+  {"gan",	HB_TAG('Z','H','S',' ')},	/* Gan Chinese -> Chinese Simplified */
-+  {"gax",	HB_TAG('O','R','O',' ')},	/* Borana-Arsi-Guji Oromo -> Oromo */
-+  {"gaz",	HB_TAG('O','R','O',' ')},	/* West Central Oromo -> Oromo */
-+  {"gbm",	HB_TAG('G','A','W',' ')},	/* Garhwali */
-+  {"gce",	HB_TAG('A','T','H',' ')},	/* Galice -> Athapaskan */
-+  {"gd",	HB_TAG('G','A','E',' ')},	/* Scottish Gaelic (Gaelic) */
-+  {"gda",	HB_TAG('R','A','J',' ')},	/* Gade Lohar -> Rajasthani */
-+/*{"gez",	HB_TAG('G','E','Z',' ')},*/	/* Geez */
-+  {"ggo",	HB_TAG('G','O','N',' ')},	/* Southern Gondi (retired code) -> Gondi */
-+/*{"gih",	HB_TAG('G','I','H',' ')},*/	/* Githabul */
-+  {"gil",	HB_TAG('G','I','L','0')},	/* Kiribati (Gilbertese) */
-+  {"gju",	HB_TAG('R','A','J',' ')},	/* Gujari -> Rajasthani */
-+/*{"gkp",	HB_TAG('G','K','P',' ')},*/	/* Guinea Kpelle -> Kpelle (Guinea) */
-+  {"gl",	HB_TAG('G','A','L',' ')},	/* Galician */
-+  {"gld",	HB_TAG('N','A','N',' ')},	/* Nanai */
-+/*{"glk",	HB_TAG('G','L','K',' ')},*/	/* Gilaki */
-+  {"gn",	HB_TAG('G','U','A',' ')},	/* Guarani [macrolanguage] */
-+/*{"gnn",	HB_TAG('G','N','N',' ')},*/	/* Gumatj */
-+  {"gno",	HB_TAG('G','O','N',' ')},	/* Northern Gondi -> Gondi */
-+  {"gnw",	HB_TAG('G','U','A',' ')},	/* Western Bolivian Guaraní -> Guarani */
-+/*{"gog",	HB_TAG('G','O','G',' ')},*/	/* Gogo */
-+  {"gom",	HB_TAG('K','O','K',' ')},	/* Goan Konkani -> Konkani */
-+/*{"gon",	HB_TAG('G','O','N',' ')},*/	/* Gondi [macrolanguage] */
-+  {"grt",	HB_TAG('G','R','O',' ')},	/* Garo */
-+  {"gru",	HB_TAG('S','O','G',' ')},	/* Kistane -> Sodo Gurage */
-+  {"gsw",	HB_TAG('A','L','S',' ')},	/* Alsatian */
-+  {"gu",	HB_TAG('G','U','J',' ')},	/* Gujarati */
-+/*{"guc",	HB_TAG('G','U','C',' ')},*/	/* Wayuu */
-+/*{"guf",	HB_TAG('G','U','F',' ')},*/	/* Gupapuyngu */
-+  {"gug",	HB_TAG('G','U','A',' ')},	/* Paraguayan Guaraní -> Guarani */
-+  {"gui",	HB_TAG('G','U','A',' ')},	/* Eastern Bolivian Guaraní -> Guarani */
-+  {"guk",	HB_TAG('G','M','Z',' ')},	/* Gumuz */
-+  {"guk",	HB_TAG('G','U','K',' ')},	/* Gumuz (SIL fonts) */
-+  {"gun",	HB_TAG('G','U','A',' ')},	/* Mbyá Guaraní -> Guarani */
-+/*{"guz",	HB_TAG('G','U','Z',' ')},*/	/* Gusii */
-+  {"gv",	HB_TAG('M','N','X',' ')},	/* Manx */
-+  {"gwi",	HB_TAG('A','T','H',' ')},	/* Gwichʼin -> Athapaskan */
-+  {"ha",	HB_TAG('H','A','U',' ')},	/* Hausa */
-+  {"haa",	HB_TAG('A','T','H',' ')},	/* Han -> Athapaskan */
-+  {"hae",	HB_TAG('O','R','O',' ')},	/* Eastern Oromo -> Oromo */
-+  {"hak",	HB_TAG('Z','H','S',' ')},	/* Hakka Chinese -> Chinese Simplified */
-+  {"har",	HB_TAG('H','R','I',' ')},	/* Harari */
-+/*{"haw",	HB_TAG('H','A','W',' ')},*/	/* Hawaiian */
-+/*{"hay",	HB_TAG('H','A','Y',' ')},*/	/* Haya */
-+/*{"haz",	HB_TAG('H','A','Z',' ')},*/	/* Hazaragi */
-+  {"he",	HB_TAG('I','W','R',' ')},	/* Hebrew */
-+  {"hea",	HB_TAG('H','M','N',' ')},	/* Northern Qiandong Miao -> Hmong */
-+  {"hi",	HB_TAG('H','I','N',' ')},	/* Hindi */
-+/*{"hil",	HB_TAG('H','I','L',' ')},*/	/* Hiligaynon */
-+  {"hji",	HB_TAG('M','L','Y',' ')},	/* Haji -> Malay */
-+  {"hlt",	HB_TAG('Q','I','N',' ')},	/* Matu Chin -> Chin */
-+  {"hma",	HB_TAG('H','M','N',' ')},	/* Southern Mashan Hmong -> Hmong */
-+  {"hmc",	HB_TAG('H','M','N',' ')},	/* Central Huishui Hmong -> Hmong */
-+  {"hmd",	HB_TAG('H','M','N',' ')},	/* Large Flowery Miao -> Hmong */
-+  {"hme",	HB_TAG('H','M','N',' ')},	/* Eastern Huishui Hmong -> Hmong */
-+  {"hmg",	HB_TAG('H','M','N',' ')},	/* Southwestern Guiyang Hmong -> Hmong */
-+  {"hmh",	HB_TAG('H','M','N',' ')},	/* Southwestern Huishui Hmong -> Hmong */
-+  {"hmi",	HB_TAG('H','M','N',' ')},	/* Northern Huishui Hmong -> Hmong */
-+  {"hmj",	HB_TAG('H','M','N',' ')},	/* Ge -> Hmong */
-+  {"hml",	HB_TAG('H','M','N',' ')},	/* Luopohe Hmong -> Hmong */
-+  {"hmm",	HB_TAG('H','M','N',' ')},	/* Central Mashan Hmong -> Hmong */
-+/*{"hmn",	HB_TAG('H','M','N',' ')},*/	/* Hmong [macrolanguage] */
-+  {"hmp",	HB_TAG('H','M','N',' ')},	/* Northern Mashan Hmong -> Hmong */
-+  {"hmq",	HB_TAG('H','M','N',' ')},	/* Eastern Qiandong Miao -> Hmong */
-+  {"hms",	HB_TAG('H','M','N',' ')},	/* Southern Qiandong Miao -> Hmong */
-+  {"hmw",	HB_TAG('H','M','N',' ')},	/* Western Mashan Hmong -> Hmong */
-+  {"hmy",	HB_TAG('H','M','N',' ')},	/* Southern Guiyang Hmong -> Hmong */
-+  {"hmz",	HB_TAG('H','M','N',' ')},	/* Hmong Shua -> Hmong */
-+/*{"hnd",	HB_TAG('H','N','D',' ')},*/	/* Southern Hindko -> Hindko */
-+  {"hne",	HB_TAG('C','H','H',' ')},	/* Chhattisgarhi -> Chattisgarhi */
-+  {"hnj",	HB_TAG('H','M','N',' ')},	/* Hmong Njua -> Hmong */
-+  {"hno",	HB_TAG('H','N','D',' ')},	/* Northern Hindko -> Hindko */
-+  {"ho",	HB_TAG('H','M','O',' ')},	/* Hiri Motu */
-+  {"hoc",	HB_TAG('H','O',' ',' ')},	/* Ho */
-+  {"hoi",	HB_TAG('A','T','H',' ')},	/* Holikachuk -> Athapaskan */
-+  {"hoj",	HB_TAG('H','A','R',' ')},	/* Hadothi -> Harauti */
-+  {"hr",	HB_TAG('H','R','V',' ')},	/* Croatian */
-+  {"hrm",	HB_TAG('H','M','N',' ')},	/* Horned Miao -> Hmong */
-+  {"hsb",	HB_TAG('U','S','B',' ')},	/* Upper Sorbian */
-+  {"hsn",	HB_TAG('Z','H','S',' ')},	/* Xiang Chinese -> Chinese Simplified */
-+  {"ht",	HB_TAG('H','A','I',' ')},	/* Haitian (Haitian Creole) */
-+  {"hu",	HB_TAG('H','U','N',' ')},	/* Hungarian */
-+  {"huj",	HB_TAG('H','M','N',' ')},	/* Northern Guiyang Hmong -> Hmong */
-+  {"hup",	HB_TAG('A','T','H',' ')},	/* Hupa -> Athapaskan */
-+  {"hy",	HB_TAG('H','Y','E','0')},	/* Armenian -> Armenian East */
-+  {"hy",	HB_TAG('H','Y','E',' ')},	/* Armenian */
-+  {"hyw",	HB_TAG('H','Y','E',' ')},	/* Western Armenian -> Armenian */
-+  {"hz",	HB_TAG('H','E','R',' ')},	/* Herero */
-+  {"ia",	HB_TAG('I','N','A',' ')},	/* Interlingua (International Auxiliary Language Association) */
-+/*{"iba",	HB_TAG('I','B','A',' ')},*/	/* Iban */
-+/*{"ibb",	HB_TAG('I','B','B',' ')},*/	/* Ibibio */
-+  {"id",	HB_TAG('I','N','D',' ')},	/* Indonesian */
-+  {"ida",	HB_TAG('L','U','H',' ')},	/* Idakho-Isukha-Tiriki -> Luyia */
-+  {"ie",	HB_TAG('I','L','E',' ')},	/* Interlingue */
-+  {"ig",	HB_TAG('I','B','O',' ')},	/* Igbo */
-+  {"igb",	HB_TAG('E','B','I',' ')},	/* Ebira */
-+  {"ii",	HB_TAG('Y','I','M',' ')},	/* Sichuan Yi -> Yi Modern */
-+  {"ijc",	HB_TAG('I','J','O',' ')},	/* Izon -> Ijo */
-+/*{"ijo",	HB_TAG('I','J','O',' ')},*/	/* Ijo [family] */
-+  {"ik",	HB_TAG('I','P','K',' ')},	/* Inupiaq [macrolanguage] -> Inupiat */
-+  {"ike",	HB_TAG('I','N','U',' ')},	/* Eastern Canadian Inuktitut -> Inuktitut */
-+  {"ikt",	HB_TAG('I','N','U',' ')},	/* Inuinnaqtun -> Inuktitut */
-+/*{"ilo",	HB_TAG('I','L','O',' ')},*/	/* Iloko -> Ilokano */
-+  {"in",	HB_TAG('I','N','D',' ')},	/* Indonesian (retired code) */
-+  {"ing",	HB_TAG('A','T','H',' ')},	/* Degexit'an -> Athapaskan */
-+  {"inh",	HB_TAG('I','N','G',' ')},	/* Ingush */
-+  {"io",	HB_TAG('I','D','O',' ')},	/* Ido */
-+  {"is",	HB_TAG('I','S','L',' ')},	/* Icelandic */
-+  {"it",	HB_TAG('I','T','A',' ')},	/* Italian */
-+  {"iu",	HB_TAG('I','N','U',' ')},	/* Inuktitut [macrolanguage] */
-+  {"iw",	HB_TAG('I','W','R',' ')},	/* Hebrew (retired code) */
-+  {"ja",	HB_TAG('J','A','N',' ')},	/* Japanese */
-+  {"jak",	HB_TAG('M','L','Y',' ')},	/* Jakun -> Malay */
-+/*{"jam",	HB_TAG('J','A','M',' ')},*/	/* Jamaican Creole English -> Jamaican Creole */
-+  {"jax",	HB_TAG('M','L','Y',' ')},	/* Jambi Malay -> Malay */
-+/*{"jbo",	HB_TAG('J','B','O',' ')},*/	/* Lojban */
-+/*{"jct",	HB_TAG('J','C','T',' ')},*/	/* Krymchak */
-+  {"ji",	HB_TAG('J','I','I',' ')},	/* Yiddish (retired code) */
-+  {"jv",	HB_TAG('J','A','V',' ')},	/* Javanese */
-+  {"jw",	HB_TAG('J','A','V',' ')},	/* Javanese (retired code) */
-+  {"ka",	HB_TAG('K','A','T',' ')},	/* Georgian */
-+  {"kaa",	HB_TAG('K','R','K',' ')},	/* Kara-Kalpak -> Karakalpak */
-+  {"kab",	HB_TAG('K','A','B','0')},	/* Kabyle */
-+  {"kam",	HB_TAG('K','M','B',' ')},	/* Kamba (Kenya) */
-+  {"kar",	HB_TAG('K','R','N',' ')},	/* Karen [family] */
-+  {"kbd",	HB_TAG('K','A','B',' ')},	/* Kabardian */
-+  {"kby",	HB_TAG('K','N','R',' ')},	/* Manga Kanuri -> Kanuri */
-+  {"kca",	HB_TAG('K','H','K',' ')},	/* Khanty -> Khanty-Kazim */
-+  {"kca",	HB_TAG('K','H','S',' ')},	/* Khanty -> Khanty-Shurishkar */
-+  {"kca",	HB_TAG('K','H','V',' ')},	/* Khanty -> Khanty-Vakhi */
-+/*{"kde",	HB_TAG('K','D','E',' ')},*/	/* Makonde */
-+  {"kdr",	HB_TAG('K','R','M',' ')},	/* Karaim */
-+  {"kdt",	HB_TAG('K','U','Y',' ')},	/* Kuy */
-+/*{"kea",	HB_TAG('K','E','A',' ')},*/	/* Kabuverdianu (Crioulo) */
-+/*{"kek",	HB_TAG('K','E','K',' ')},*/	/* Kekchi */
-+  {"kex",	HB_TAG('K','K','N',' ')},	/* Kukna -> Kokni */
-+  {"kfa",	HB_TAG('K','O','D',' ')},	/* Kodava -> Kodagu */
-+  {"kfr",	HB_TAG('K','A','C',' ')},	/* Kachhi -> Kachchi */
-+  {"kfx",	HB_TAG('K','U','L',' ')},	/* Kullu Pahari -> Kulvi */
-+  {"kfy",	HB_TAG('K','M','N',' ')},	/* Kumaoni */
-+  {"kg",	HB_TAG('K','O','N','0')},	/* Kongo [macrolanguage] */
-+  {"kha",	HB_TAG('K','S','I',' ')},	/* Khasi */
-+  {"khb",	HB_TAG('X','B','D',' ')},	/* Lü */
-+  {"khk",	HB_TAG('M','N','G',' ')},	/* Halh Mongolian -> Mongolian */
-+  {"kht",	HB_TAG('K','H','N',' ')},	/* Khamti -> Khamti Shan (Microsoft fonts) */
-+  {"kht",	HB_TAG('K','H','T',' ')},	/* Khamti -> Khamti Shan (OpenType spec and SIL fonts) */
-+/*{"khw",	HB_TAG('K','H','W',' ')},*/	/* Khowar */
-+  {"ki",	HB_TAG('K','I','K',' ')},	/* Kikuyu (Gikuyu) */
-+/*{"kiu",	HB_TAG('K','I','U',' ')},*/	/* Kirmanjki */
-+  {"kj",	HB_TAG('K','U','A',' ')},	/* Kuanyama */
-+/*{"kjd",	HB_TAG('K','J','D',' ')},*/	/* Southern Kiwai */
-+  {"kjh",	HB_TAG('K','H','A',' ')},	/* Khakas -> Khakass */
-+/*{"kjp",	HB_TAG('K','J','P',' ')},*/	/* Pwo Eastern Karen -> Eastern Pwo Karen */
-+/*{"kjz",	HB_TAG('K','J','Z',' ')},*/	/* Bumthangkha */
-+  {"kk",	HB_TAG('K','A','Z',' ')},	/* Kazakh */
-+  {"kkz",	HB_TAG('A','T','H',' ')},	/* Kaska -> Athapaskan */
-+  {"kl",	HB_TAG('G','R','N',' ')},	/* Greenlandic */
-+  {"kln",	HB_TAG('K','A','L',' ')},	/* Kalenjin [macrolanguage] */
-+  {"km",	HB_TAG('K','H','M',' ')},	/* Khmer */
-+  {"kmb",	HB_TAG('M','B','N',' ')},	/* Kimbundu -> Mbundu */
-+  {"kmr",	HB_TAG('K','U','R',' ')},	/* Northern Kurdish -> Kurdish */
-+  {"kmw",	HB_TAG('K','M','O',' ')},	/* Komo (Democratic Republic of Congo) */
-+/*{"kmz",	HB_TAG('K','M','Z',' ')},*/	/* Khorasani Turkish -> Khorasani Turkic */
-+  {"kn",	HB_TAG('K','A','N',' ')},	/* Kannada */
-+  {"knc",	HB_TAG('K','N','R',' ')},	/* Central Kanuri -> Kanuri */
-+  {"kng",	HB_TAG('K','O','N','0')},	/* Koongo -> Kongo */
-+  {"knn",	HB_TAG('K','O','K',' ')},	/* Konkani */
-+  {"ko",	HB_TAG('K','O','R',' ')},	/* Korean */
-+  {"koi",	HB_TAG('K','O','P',' ')},	/* Komi-Permyak */
-+/*{"kok",	HB_TAG('K','O','K',' ')},*/	/* Konkani [macrolanguage] */
-+/*{"kos",	HB_TAG('K','O','S',' ')},*/	/* Kosraean */
-+  {"koy",	HB_TAG('A','T','H',' ')},	/* Koyukon -> Athapaskan */
-+  {"kpe",	HB_TAG('K','P','L',' ')},	/* Kpelle [macrolanguage] */
-+  {"kpv",	HB_TAG('K','O','Z',' ')},	/* Komi-Zyrian */
-+  {"kpy",	HB_TAG('K','Y','K',' ')},	/* Koryak */
-+  {"kqs",	HB_TAG('K','I','S',' ')},	/* Northern Kissi -> Kisii */
-+  {"kqy",	HB_TAG('K','R','T',' ')},	/* Koorete */
-+  {"kr",	HB_TAG('K','N','R',' ')},	/* Kanuri [macrolanguage] */
-+  {"krc",	HB_TAG('K','A','R',' ')},	/* Karachay-Balkar -> Karachay */
-+  {"krc",	HB_TAG('B','A','L',' ')},	/* Karachay-Balkar -> Balkar */
-+/*{"kri",	HB_TAG('K','R','I',' ')},*/	/* Krio */
-+/*{"krl",	HB_TAG('K','R','L',' ')},*/	/* Karelian */
-+  {"krt",	HB_TAG('K','N','R',' ')},	/* Tumari Kanuri -> Kanuri */
-+  {"kru",	HB_TAG('K','U','U',' ')},	/* Kurukh */
-+  {"ks",	HB_TAG('K','S','H',' ')},	/* Kashmiri */
-+  {"ksh",	HB_TAG('K','S','H','0')},	/* Kölsch -> Ripuarian */
-+  {"kss",	HB_TAG('K','I','S',' ')},	/* Southern Kisi -> Kisii */
-+/*{"ksw",	HB_TAG('K','S','W',' ')},*/	/* S’gaw Karen */
-+  {"ktb",	HB_TAG('K','E','B',' ')},	/* Kambaata -> Kebena */
-+  {"ktu",	HB_TAG('K','O','N',' ')},	/* Kituba (Democratic Republic of Congo) -> Kikongo */
-+  {"ktw",	HB_TAG('A','T','H',' ')},	/* Kato -> Athapaskan */
-+  {"ku",	HB_TAG('K','U','R',' ')},	/* Kurdish [macrolanguage] */
-+/*{"kum",	HB_TAG('K','U','M',' ')},*/	/* Kumyk */
-+  {"kuu",	HB_TAG('A','T','H',' ')},	/* Upper Kuskokwim -> Athapaskan */
-+  {"kv",	HB_TAG('K','O','M',' ')},	/* Komi [macrolanguage] */
-+  {"kvb",	HB_TAG('M','L','Y',' ')},	/* Kubu -> Malay */
-+  {"kvr",	HB_TAG('M','L','Y',' ')},	/* Kerinci -> Malay */
-+  {"kw",	HB_TAG('C','O','R',' ')},	/* Cornish */
-+  {"kwy",	HB_TAG('K','O','N','0')},	/* San Salvador Kongo -> Kongo */
-+  {"kxc",	HB_TAG('K','M','S',' ')},	/* Konso -> Komso */
-+  {"kxd",	HB_TAG('M','L','Y',' ')},	/* Brunei -> Malay */
-+  {"kxu",	HB_TAG('K','U','I',' ')},	/* Kui (India) */
-+  {"ky",	HB_TAG('K','I','R',' ')},	/* Kirghiz (Kyrgyz) */
-+/*{"kyu",	HB_TAG('K','Y','U',' ')},*/	/* Western Kayah */
-+  {"la",	HB_TAG('L','A','T',' ')},	/* Latin */
-+  {"lad",	HB_TAG('J','U','D',' ')},	/* Ladino */
-+  {"lb",	HB_TAG('L','T','Z',' ')},	/* Luxembourgish */
-+  {"lbe",	HB_TAG('L','A','K',' ')},	/* Lak */
-+  {"lbj",	HB_TAG('L','D','K',' ')},	/* Ladakhi */
-+  {"lbl",	HB_TAG('B','I','K',' ')},	/* Libon Bikol -> Bikol */
-+  {"lce",	HB_TAG('M','L','Y',' ')},	/* Loncong -> Malay */
-+  {"lcf",	HB_TAG('M','L','Y',' ')},	/* Lubu -> Malay */
-+  {"ldi",	HB_TAG('K','O','N','0')},	/* Laari -> Kongo */
-+/*{"lez",	HB_TAG('L','E','Z',' ')},*/	/* Lezghian -> Lezgi */
-+  {"lg",	HB_TAG('L','U','G',' ')},	/* Ganda */
-+  {"li",	HB_TAG('L','I','M',' ')},	/* Limburgish */
-+  {"lif",	HB_TAG('L','M','B',' ')},	/* Limbu */
-+/*{"lij",	HB_TAG('L','I','J',' ')},*/	/* Ligurian */
-+/*{"lis",	HB_TAG('L','I','S',' ')},*/	/* Lisu */
-+  {"liw",	HB_TAG('M','L','Y',' ')},	/* Col -> Malay */
-+/*{"ljp",	HB_TAG('L','J','P',' ')},*/	/* Lampung Api -> Lampung */
-+  {"lkb",	HB_TAG('L','U','H',' ')},	/* Kabras -> Luyia */
-+/*{"lki",	HB_TAG('L','K','I',' ')},*/	/* Laki */
-+  {"lko",	HB_TAG('L','U','H',' ')},	/* Khayo -> Luyia */
-+  {"lks",	HB_TAG('L','U','H',' ')},	/* Kisa -> Luyia */
-+  {"lld",	HB_TAG('L','A','D',' ')},	/* Ladin */
-+  {"lmn",	HB_TAG('L','A','M',' ')},	/* Lambadi -> Lambani */
-+/*{"lmo",	HB_TAG('L','M','O',' ')},*/	/* Lombard */
-+  {"ln",	HB_TAG('L','I','N',' ')},	/* Lingala */
-+  {"lo",	HB_TAG('L','A','O',' ')},	/* Lao */
-+/*{"lom",	HB_TAG('L','O','M',' ')},*/	/* Loma (Liberia) */
-+/*{"lrc",	HB_TAG('L','R','C',' ')},*/	/* Northern Luri -> Luri */
-+  {"lri",	HB_TAG('L','U','H',' ')},	/* Marachi -> Luyia */
-+  {"lrm",	HB_TAG('L','U','H',' ')},	/* Marama -> Luyia */
-+  {"lsm",	HB_TAG('L','U','H',' ')},	/* Saamia -> Luyia */
-+  {"lt",	HB_TAG('L','T','H',' ')},	/* Lithuanian */
-+  {"ltg",	HB_TAG('L','V','I',' ')},	/* Latgalian -> Latvian */
-+  {"lto",	HB_TAG('L','U','H',' ')},	/* Tsotso -> Luyia */
-+  {"lts",	HB_TAG('L','U','H',' ')},	/* Tachoni -> Luyia */
-+  {"lu",	HB_TAG('L','U','B',' ')},	/* Luba-Katanga */
-+/*{"lua",	HB_TAG('L','U','A',' ')},*/	/* Luba-Lulua */
-+/*{"luo",	HB_TAG('L','U','O',' ')},*/	/* Luo (Kenya and Tanzania) */
-+  {"lus",	HB_TAG('M','I','Z',' ')},	/* Lushai -> Mizo */
-+  {"luy",	HB_TAG('L','U','H',' ')},	/* Luyia [macrolanguage] */
-+  {"luz",	HB_TAG('L','R','C',' ')},	/* Southern Luri -> Luri */
-+  {"lv",	HB_TAG('L','V','I',' ')},	/* Latvian [macrolanguage] */
-+  {"lvs",	HB_TAG('L','V','I',' ')},	/* Standard Latvian -> Latvian */
-+  {"lwg",	HB_TAG('L','U','H',' ')},	/* Wanga -> Luyia */
-+  {"lzh",	HB_TAG('Z','H','T',' ')},	/* Literary Chinese -> Chinese Traditional */
-+  {"lzz",	HB_TAG('L','A','Z',' ')},	/* Laz */
-+/*{"mad",	HB_TAG('M','A','D',' ')},*/	/* Madurese -> Madura */
-+/*{"mag",	HB_TAG('M','A','G',' ')},*/	/* Magahi */
-+  {"mai",	HB_TAG('M','T','H',' ')},	/* Maithili */
-+  {"mak",	HB_TAG('M','K','R',' ')},	/* Makasar */
-+/*{"mam",	HB_TAG('M','A','M',' ')},*/	/* Mam */
-+  {"man",	HB_TAG('M','N','K',' ')},	/* Mandingo [macrolanguage] -> Maninka */
-+  {"max",	HB_TAG('M','L','Y',' ')},	/* North Moluccan Malay -> Malay */
-+/*{"mbo",	HB_TAG('M','B','O',' ')},*/	/* Mbo (Cameroon) */
-+  {"mct",	HB_TAG('B','T','I',' ')},	/* Mengisa -> Beti */
-+  {"mdf",	HB_TAG('M','O','K',' ')},	/* Moksha */
-+/*{"mdr",	HB_TAG('M','D','R',' ')},*/	/* Mandar */
-+  {"mdy",	HB_TAG('M','L','E',' ')},	/* Male (Ethiopia) */
-+  {"men",	HB_TAG('M','D','E',' ')},	/* Mende (Sierra Leone) */
-+  {"meo",	HB_TAG('M','L','Y',' ')},	/* Kedah Malay -> Malay */
-+/*{"mer",	HB_TAG('M','E','R',' ')},*/	/* Meru */
-+/*{"mfa",	HB_TAG('M','F','A',' ')},*/	/* Pattani Malay */
-+  {"mfb",	HB_TAG('M','L','Y',' ')},	/* Bangka -> Malay */
-+/*{"mfe",	HB_TAG('M','F','E',' ')},*/	/* Morisyen */
-+  {"mg",	HB_TAG('M','L','G',' ')},	/* Malagasy [macrolanguage] */
-+  {"mh",	HB_TAG('M','A','H',' ')},	/* Marshallese */
-+  {"mhr",	HB_TAG('L','M','A',' ')},	/* Eastern Mari -> Low Mari */
-+  {"mhv",	HB_TAG('A','R','K',' ')},	/* Arakanese (retired code) -> Rakhine */
-+  {"mi",	HB_TAG('M','R','I',' ')},	/* Maori */
-+/*{"min",	HB_TAG('M','I','N',' ')},*/	/* Minangkabau */
-+  {"mk",	HB_TAG('M','K','D',' ')},	/* Macedonian */
-+  {"mku",	HB_TAG('M','N','K',' ')},	/* Konyanka Maninka -> Maninka */
-+/*{"mkw",	HB_TAG('M','K','W',' ')},*/	/* Kituba (Congo) */
-+  {"ml",	HB_TAG('M','A','L',' ')},	/* Malayalam -> Malayalam Traditional */
-+  {"ml",	HB_TAG('M','L','R',' ')},	/* Malayalam -> Malayalam Reformed */
-+  {"mlq",	HB_TAG('M','L','N',' ')},	/* Western Maninkakan -> Malinke */
-+  {"mlq",	HB_TAG('M','N','K',' ')},	/* Western Maninkakan -> Maninka */
-+  {"mmr",	HB_TAG('H','M','N',' ')},	/* Western Xiangxi Miao -> Hmong */
-+  {"mn",	HB_TAG('M','N','G',' ')},	/* Mongolian [macrolanguage] */
-+  {"mnc",	HB_TAG('M','C','H',' ')},	/* Manchu */
-+/*{"mni",	HB_TAG('M','N','I',' ')},*/	/* Manipuri */
-+  {"mnk",	HB_TAG('M','N','D',' ')},	/* Mandinka */
-+  {"mnk",	HB_TAG('M','N','K',' ')},	/* Mandinka -> Maninka */
-+  {"mnp",	HB_TAG('Z','H','S',' ')},	/* Min Bei Chinese -> Chinese Simplified */
-+  {"mns",	HB_TAG('M','A','N',' ')},	/* Mansi */
-+  {"mnw",	HB_TAG('M','O','N',' ')},	/* Mon */
-+  {"mo",	HB_TAG('M','O','L',' ')},	/* Moldavian (retired code) */
-+/*{"moh",	HB_TAG('M','O','H',' ')},*/	/* Mohawk */
-+/*{"mos",	HB_TAG('M','O','S',' ')},*/	/* Mossi */
-+  {"mpe",	HB_TAG('M','A','J',' ')},	/* Majang */
-+  {"mqg",	HB_TAG('M','L','Y',' ')},	/* Kota Bangun Kutai Malay -> Malay */
-+  {"mr",	HB_TAG('M','A','R',' ')},	/* Marathi */
-+  {"mrh",	HB_TAG('Q','I','N',' ')},	/* Mara Chin -> Chin */
-+  {"mrj",	HB_TAG('H','M','A',' ')},	/* Western Mari -> High Mari */
-+  {"ms",	HB_TAG('M','L','Y',' ')},	/* Malay [macrolanguage] */
-+  {"msc",	HB_TAG('M','N','K',' ')},	/* Sankaran Maninka -> Maninka */
-+  {"msh",	HB_TAG('M','L','G',' ')},	/* Masikoro Malagasy -> Malagasy */
-+  {"msi",	HB_TAG('M','L','Y',' ')},	/* Sabah Malay -> Malay */
-+  {"mt",	HB_TAG('M','T','S',' ')},	/* Maltese */
-+  {"mtr",	HB_TAG('M','A','W',' ')},	/* Mewari -> Marwari */
-+  {"mui",	HB_TAG('M','L','Y',' ')},	/* Musi -> Malay */
-+  {"mup",	HB_TAG('R','A','J',' ')},	/* Malvi -> Rajasthani */
-+  {"muq",	HB_TAG('H','M','N',' ')},	/* Eastern Xiangxi Miao -> Hmong */
-+/*{"mus",	HB_TAG('M','U','S',' ')},*/	/* Creek -> Muscogee */
-+  {"mvb",	HB_TAG('A','T','H',' ')},	/* Mattole -> Athapaskan */
-+  {"mve",	HB_TAG('M','A','W',' ')},	/* Marwari (Pakistan) */
-+  {"mvf",	HB_TAG('M','N','G',' ')},	/* Peripheral Mongolian -> Mongolian */
-+  {"mwk",	HB_TAG('M','N','K',' ')},	/* Kita Maninkakan -> Maninka */
-+/*{"mwl",	HB_TAG('M','W','L',' ')},*/	/* Mirandese */
-+  {"mwr",	HB_TAG('M','A','W',' ')},	/* Marwari [macrolanguage] */
-+/*{"mww",	HB_TAG('M','W','W',' ')},*/	/* Hmong Daw */
-+  {"my",	HB_TAG('B','R','M',' ')},	/* Burmese */
-+  {"mym",	HB_TAG('M','E','N',' ')},	/* Me’en */
-+/*{"myn",	HB_TAG('M','Y','N',' ')},*/	/* Mayan [family] */
-+  {"myq",	HB_TAG('M','N','K',' ')},	/* Forest Maninka (retired code) -> Maninka */
-+  {"myv",	HB_TAG('E','R','Z',' ')},	/* Erzya */
-+/*{"mzn",	HB_TAG('M','Z','N',' ')},*/	/* Mazanderani */
-+  {"na",	HB_TAG('N','A','U',' ')},	/* Nauru -> Nauruan */
-+/*{"nag",	HB_TAG('N','A','G',' ')},*/	/* Naga Pidgin -> Naga-Assamese */
-+/*{"nah",	HB_TAG('N','A','H',' ')},*/	/* Nahuatl [family] */
-+  {"nan",	HB_TAG('Z','H','S',' ')},	/* Min Nan Chinese -> Chinese Simplified */
-+/*{"nap",	HB_TAG('N','A','P',' ')},*/	/* Neapolitan */
-+  {"nb",	HB_TAG('N','O','R',' ')},	/* Norwegian Bokmål -> Norwegian */
-+  {"nd",	HB_TAG('N','D','B',' ')},	/* North Ndebele -> Ndebele */
-+/*{"ndc",	HB_TAG('N','D','C',' ')},*/	/* Ndau */
-+/*{"nds",	HB_TAG('N','D','S',' ')},*/	/* Low Saxon */
-+  {"ne",	HB_TAG('N','E','P',' ')},	/* Nepali [macrolanguage] */
-+/*{"new",	HB_TAG('N','E','W',' ')},*/	/* Newari */
-+  {"ng",	HB_TAG('N','D','G',' ')},	/* Ndonga */
-+/*{"nga",	HB_TAG('N','G','A',' ')},*/	/* Ngbaka */
-+  {"ngl",	HB_TAG('L','M','W',' ')},	/* Lomwe */
-+  {"ngo",	HB_TAG('S','X','T',' ')},	/* Ngoni -> Sutu */
-+  {"nhd",	HB_TAG('G','U','A',' ')},	/* Chiripá -> Guarani */
-+  {"niq",	HB_TAG('K','A','L',' ')},	/* Nandi -> Kalenjin */
-+/*{"niu",	HB_TAG('N','I','U',' ')},*/	/* Niuean */
-+  {"niv",	HB_TAG('G','I','L',' ')},	/* Gilyak */
-+  {"njz",	HB_TAG('N','I','S',' ')},	/* Nyishi -> Nisi */
-+  {"nl",	HB_TAG('N','L','D',' ')},	/* Dutch */
-+  {"nle",	HB_TAG('L','U','H',' ')},	/* East Nyala -> Luyia */
-+  {"nn",	HB_TAG('N','Y','N',' ')},	/* Norwegian Nynorsk (Nynorsk, Norwegian) */
-+  {"no",	HB_TAG('N','O','R',' ')},	/* Norwegian [macrolanguage] */
-+  {"nod",	HB_TAG('N','T','A',' ')},	/* Northern Thai -> Northern Tai */
-+/*{"noe",	HB_TAG('N','O','E',' ')},*/	/* Nimadi */
-+/*{"nog",	HB_TAG('N','O','G',' ')},*/	/* Nogai */
-+/*{"nov",	HB_TAG('N','O','V',' ')},*/	/* Novial */
-+  {"npi",	HB_TAG('N','E','P',' ')},	/* Nepali */
-+  {"nqo",	HB_TAG('N','K','O',' ')},	/* N’Ko */
-+  {"nr",	HB_TAG('N','D','B',' ')},	/* South Ndebele -> Ndebele */
-+  {"nsk",	HB_TAG('N','A','S',' ')},	/* Naskapi */
-+/*{"nso",	HB_TAG('N','S','O',' ')},*/	/* Pedi -> Sotho, Northern */
-+  {"nv",	HB_TAG('N','A','V',' ')},	/* Navajo */
-+  {"nv",	HB_TAG('A','T','H',' ')},	/* Navajo -> Athapaskan */
-+  {"ny",	HB_TAG('C','H','I',' ')},	/* Chichewa (Chewa, Nyanja) */
-+  {"nyd",	HB_TAG('L','U','H',' ')},	/* Nyore -> Luyia */
-+/*{"nym",	HB_TAG('N','Y','M',' ')},*/	/* Nyamwezi */
-+  {"nyn",	HB_TAG('N','K','L',' ')},	/* Nyankole */
-+/*{"nza",	HB_TAG('N','Z','A',' ')},*/	/* Tigon Mbembe -> Mbembe Tigon */
-+  {"oc",	HB_TAG('O','C','I',' ')},	/* Occitan (post 1500) */
-+  {"oj",	HB_TAG('O','J','B',' ')},	/* Ojibwa [macrolanguage] -> Ojibway */
-+/*{"ojb",	HB_TAG('O','J','B',' ')},*/	/* Northwestern Ojibwa -> Ojibway */
-+  {"ojc",	HB_TAG('O','J','B',' ')},	/* Central Ojibwa -> Ojibway */
-+  {"ojg",	HB_TAG('O','J','B',' ')},	/* Eastern Ojibwa -> Ojibway */
-+  {"ojs",	HB_TAG('O','C','R',' ')},	/* Severn Ojibwa -> Oji-Cree */
-+  {"ojw",	HB_TAG('O','J','B',' ')},	/* Western Ojibwa -> Ojibway */
-+  {"oki",	HB_TAG('K','A','L',' ')},	/* Okiek -> Kalenjin */
-+  {"okm",	HB_TAG('K','O','H',' ')},	/* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
-+  {"om",	HB_TAG('O','R','O',' ')},	/* Oromo [macrolanguage] */
-+  {"or",	HB_TAG('O','R','I',' ')},	/* Odia (formerly Oriya) [macrolanguage] */
-+  {"orc",	HB_TAG('O','R','O',' ')},	/* Orma -> Oromo */
-+  {"orn",	HB_TAG('M','L','Y',' ')},	/* Orang Kanaq -> Malay */
-+  {"ors",	HB_TAG('M','L','Y',' ')},	/* Orang Seletar -> Malay */
-+  {"ory",	HB_TAG('O','R','I',' ')},	/* Odia (formerly Oriya) */
-+  {"os",	HB_TAG('O','S','S',' ')},	/* Ossetian */
-+  {"otw",	HB_TAG('O','J','B',' ')},	/* Ottawa -> Ojibway */
-+  {"pa",	HB_TAG('P','A','N',' ')},	/* Punjabi */
-+/*{"pag",	HB_TAG('P','A','G',' ')},*/	/* Pangasinan */
-+/*{"pam",	HB_TAG('P','A','M',' ')},*/	/* Pampanga -> Pampangan */
-+  {"pap",	HB_TAG('P','A','P','0')},	/* Papiamento -> Papiamentu */
-+/*{"pau",	HB_TAG('P','A','U',' ')},*/	/* Palauan */
-+  {"pbt",	HB_TAG('P','A','S',' ')},	/* Southern Pashto -> Pashto */
-+  {"pbu",	HB_TAG('P','A','S',' ')},	/* Northern Pashto -> Pashto */
-+/*{"pcc",	HB_TAG('P','C','C',' ')},*/	/* Bouyei */
-+/*{"pcd",	HB_TAG('P','C','D',' ')},*/	/* Picard */
-+  {"pce",	HB_TAG('P','L','G',' ')},	/* Ruching Palaung -> Palaung */
-+  {"pck",	HB_TAG('Q','I','N',' ')},	/* Paite Chin -> Chin */
-+/*{"pdc",	HB_TAG('P','D','C',' ')},*/	/* Pennsylvania German */
-+  {"pel",	HB_TAG('M','L','Y',' ')},	/* Pekal -> Malay */
-+  {"pes",	HB_TAG('F','A','R',' ')},	/* Iranian Persian -> Persian */
-+  {"pga",	HB_TAG('A','R','A',' ')},	/* Sudanese Creole Arabic -> Arabic */
-+/*{"phk",	HB_TAG('P','H','K',' ')},*/	/* Phake */
-+  {"pi",	HB_TAG('P','A','L',' ')},	/* Pali */
-+/*{"pih",	HB_TAG('P','I','H',' ')},*/	/* Pitcairn-Norfolk -> Norfolk */
-+  {"pko",	HB_TAG('K','A','L',' ')},	/* Pökoot -> Kalenjin */
-+  {"pl",	HB_TAG('P','L','K',' ')},	/* Polish */
-+  {"pll",	HB_TAG('P','L','G',' ')},	/* Shwe Palaung -> Palaung */
-+  {"plp",	HB_TAG('P','A','P',' ')},	/* Palpa */
-+  {"plt",	HB_TAG('M','L','G',' ')},	/* Plateau Malagasy -> Malagasy */
-+/*{"pms",	HB_TAG('P','M','S',' ')},*/	/* Piemontese */
-+/*{"pnb",	HB_TAG('P','N','B',' ')},*/	/* Western Panjabi */
-+/*{"poh",	HB_TAG('P','O','H',' ')},*/	/* Poqomchi' -> Pocomchi */
-+/*{"pon",	HB_TAG('P','O','N',' ')},*/	/* Pohnpeian */
-+  {"ppa",	HB_TAG('B','A','G',' ')},	/* Pao (retired code) -> Baghelkhandi */
-+/*{"pro",	HB_TAG('P','R','O',' ')},*/	/* Old Provençal (to 1500) -> Provençal / Old Provençal */
-+  {"prs",	HB_TAG('D','R','I',' ')},	/* Dari */
-+  {"ps",	HB_TAG('P','A','S',' ')},	/* Pashto [macrolanguage] */
-+  {"pse",	HB_TAG('M','L','Y',' ')},	/* Central Malay -> Malay */
-+  {"pst",	HB_TAG('P','A','S',' ')},	/* Central Pashto -> Pashto */
-+  {"pt",	HB_TAG('P','T','G',' ')},	/* Portuguese */
-+/*{"pwo",	HB_TAG('P','W','O',' ')},*/	/* Pwo Western Karen -> Western Pwo Karen */
-+  {"qu",	HB_TAG('Q','U','Z',' ')},	/* Quechua [macrolanguage] */
-+  {"qub",	HB_TAG('Q','W','H',' ')},	/* Huallaga Huánuco Quechua -> Quechua (Peru) */
-+/*{"quc",	HB_TAG('Q','U','C',' ')},*/	/* K’iche’ */
-+  {"qud",	HB_TAG('Q','V','I',' ')},	/* Calderón Highland Quichua -> Quechua (Ecuador) */
-+  {"quf",	HB_TAG('Q','U','Z',' ')},	/* Lambayeque Quechua -> Quechua */
-+  {"qug",	HB_TAG('Q','V','I',' ')},	/* Chimborazo Highland Quichua -> Quechua (Ecuador) */
-+/*{"quh",	HB_TAG('Q','U','H',' ')},*/	/* South Bolivian Quechua -> Quechua (Bolivia) */
-+  {"quk",	HB_TAG('Q','U','Z',' ')},	/* Chachapoyas Quechua -> Quechua */
-+  {"qul",	HB_TAG('Q','U','Z',' ')},	/* North Bolivian Quechua -> Quechua */
-+  {"qup",	HB_TAG('Q','V','I',' ')},	/* Southern Pastaza Quechua -> Quechua (Ecuador) */
-+  {"qur",	HB_TAG('Q','W','H',' ')},	/* Yanahuanca Pasco Quechua -> Quechua (Peru) */
-+  {"qus",	HB_TAG('Q','U','H',' ')},	/* Santiago del Estero Quichua -> Quechua (Bolivia) */
-+  {"quw",	HB_TAG('Q','V','I',' ')},	/* Tena Lowland Quichua -> Quechua (Ecuador) */
-+  {"qux",	HB_TAG('Q','W','H',' ')},	/* Yauyos Quechua -> Quechua (Peru) */
-+  {"quy",	HB_TAG('Q','U','Z',' ')},	/* Ayacucho Quechua -> Quechua */
-+/*{"quz",	HB_TAG('Q','U','Z',' ')},*/	/* Cusco Quechua -> Quechua */
-+  {"qva",	HB_TAG('Q','W','H',' ')},	/* Ambo-Pasco Quechua -> Quechua (Peru) */
-+  {"qvc",	HB_TAG('Q','U','Z',' ')},	/* Cajamarca Quechua -> Quechua */
-+  {"qve",	HB_TAG('Q','U','Z',' ')},	/* Eastern Apurímac Quechua -> Quechua */
-+  {"qvh",	HB_TAG('Q','W','H',' ')},	/* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
-+/*{"qvi",	HB_TAG('Q','V','I',' ')},*/	/* Imbabura Highland Quichua -> Quechua (Ecuador) */
-+  {"qvj",	HB_TAG('Q','V','I',' ')},	/* Loja Highland Quichua -> Quechua (Ecuador) */
-+  {"qvl",	HB_TAG('Q','W','H',' ')},	/* Cajatambo North Lima Quechua -> Quechua (Peru) */
-+  {"qvm",	HB_TAG('Q','W','H',' ')},	/* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
-+  {"qvn",	HB_TAG('Q','W','H',' ')},	/* North Junín Quechua -> Quechua (Peru) */
-+  {"qvo",	HB_TAG('Q','V','I',' ')},	/* Napo Lowland Quechua -> Quechua (Ecuador) */
-+  {"qvp",	HB_TAG('Q','W','H',' ')},	/* Pacaraos Quechua -> Quechua (Peru) */
-+  {"qvs",	HB_TAG('Q','U','Z',' ')},	/* San Martín Quechua -> Quechua */
-+  {"qvw",	HB_TAG('Q','W','H',' ')},	/* Huaylla Wanca Quechua -> Quechua (Peru) */
-+  {"qvz",	HB_TAG('Q','V','I',' ')},	/* Northern Pastaza Quichua -> Quechua (Ecuador) */
-+  {"qwa",	HB_TAG('Q','W','H',' ')},	/* Corongo Ancash Quechua -> Quechua (Peru) */
-+  {"qwc",	HB_TAG('Q','U','Z',' ')},	/* Classical Quechua -> Quechua */
-+/*{"qwh",	HB_TAG('Q','W','H',' ')},*/	/* Huaylas Ancash Quechua -> Quechua (Peru) */
-+  {"qws",	HB_TAG('Q','W','H',' ')},	/* Sihuas Ancash Quechua -> Quechua (Peru) */
-+  {"qxa",	HB_TAG('Q','W','H',' ')},	/* Chiquián Ancash Quechua -> Quechua (Peru) */
-+  {"qxc",	HB_TAG('Q','W','H',' ')},	/* Chincha Quechua -> Quechua (Peru) */
-+  {"qxh",	HB_TAG('Q','W','H',' ')},	/* Panao Huánuco Quechua -> Quechua (Peru) */
-+  {"qxl",	HB_TAG('Q','V','I',' ')},	/* Salasaca Highland Quichua -> Quechua (Ecuador) */
-+  {"qxn",	HB_TAG('Q','W','H',' ')},	/* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
-+  {"qxo",	HB_TAG('Q','W','H',' ')},	/* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
-+  {"qxp",	HB_TAG('Q','U','Z',' ')},	/* Puno Quechua -> Quechua */
-+  {"qxr",	HB_TAG('Q','V','I',' ')},	/* Cañar Highland Quichua -> Quechua (Ecuador) */
-+  {"qxt",	HB_TAG('Q','W','H',' ')},	/* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
-+  {"qxu",	HB_TAG('Q','U','Z',' ')},	/* Arequipa-La Unión Quechua -> Quechua */
-+  {"qxw",	HB_TAG('Q','W','H',' ')},	/* Jauja Wanca Quechua -> Quechua (Peru) */
-+  {"rag",	HB_TAG('L','U','H',' ')},	/* Logooli -> Luyia */
-+/*{"raj",	HB_TAG('R','A','J',' ')},*/	/* Rajasthani [macrolanguage] */
-+/*{"rar",	HB_TAG('R','A','R',' ')},*/	/* Rarotongan */
-+  {"rbb",	HB_TAG('P','L','G',' ')},	/* Rumai Palaung -> Palaung */
-+  {"rbl",	HB_TAG('B','I','K',' ')},	/* Miraya Bikol -> Bikol */
-+/*{"rej",	HB_TAG('R','E','J',' ')},*/	/* Rejang */
-+/*{"ria",	HB_TAG('R','I','A',' ')},*/	/* Riang (India) */
-+/*{"rif",	HB_TAG('R','I','F',' ')},*/	/* Tarifit */
-+/*{"rit",	HB_TAG('R','I','T',' ')},*/	/* Ritarungo */
-+  {"rki",	HB_TAG('A','R','K',' ')},	/* Rakhine */
-+/*{"rkw",	HB_TAG('R','K','W',' ')},*/	/* Arakwal */
-+  {"rm",	HB_TAG('R','M','S',' ')},	/* Romansh */
-+  {"rmc",	HB_TAG('R','O','Y',' ')},	/* Carpathian Romani -> Romany */
-+  {"rmf",	HB_TAG('R','O','Y',' ')},	/* Kalo Finnish Romani -> Romany */
-+  {"rml",	HB_TAG('R','O','Y',' ')},	/* Baltic Romani -> Romany */
-+  {"rmn",	HB_TAG('R','O','Y',' ')},	/* Balkan Romani -> Romany */
-+  {"rmo",	HB_TAG('R','O','Y',' ')},	/* Sinte Romani -> Romany */
-+  {"rmw",	HB_TAG('R','O','Y',' ')},	/* Welsh Romani -> Romany */
-+/*{"rmy",	HB_TAG('R','M','Y',' ')},*/	/* Vlax Romani */
-+  {"rmz",	HB_TAG('A','R','K',' ')},	/* Marma -> Rakhine */
-+  {"rn",	HB_TAG('R','U','N',' ')},	/* Rundi */
-+  {"rnl",	HB_TAG('H','A','L',' ')},	/* Ranglong -> Halam (Falam Chin) */
-+  {"ro",	HB_TAG('R','O','M',' ')},	/* Romanian */
-+  {"rom",	HB_TAG('R','O','Y',' ')},	/* Romany [macrolanguage] */
-+/*{"rtm",	HB_TAG('R','T','M',' ')},*/	/* Rotuman */
-+  {"ru",	HB_TAG('R','U','S',' ')},	/* Russian */
-+  {"rue",	HB_TAG('R','S','Y',' ')},	/* Rusyn */
-+/*{"rup",	HB_TAG('R','U','P',' ')},*/	/* Aromanian */
-+  {"rw",	HB_TAG('R','U','A',' ')},	/* Kinyarwanda */
-+  {"rwr",	HB_TAG('M','A','W',' ')},	/* Marwari (India) */
-+  {"sa",	HB_TAG('S','A','N',' ')},	/* Sanskrit */
-+  {"sah",	HB_TAG('Y','A','K',' ')},	/* Yakut -> Sakha */
-+  {"sam",	HB_TAG('P','A','A',' ')},	/* Samaritan Aramaic -> Palestinian Aramaic */
-+/*{"sas",	HB_TAG('S','A','S',' ')},*/	/* Sasak */
-+/*{"sat",	HB_TAG('S','A','T',' ')},*/	/* Santali */
-+  {"sc",	HB_TAG('S','R','D',' ')},	/* Sardinian [macrolanguage] */
-+  {"sck",	HB_TAG('S','A','D',' ')},	/* Sadri */
-+/*{"scn",	HB_TAG('S','C','N',' ')},*/	/* Sicilian */
-+/*{"sco",	HB_TAG('S','C','O',' ')},*/	/* Scots */
-+  {"scs",	HB_TAG('S','C','S',' ')},	/* North Slavey */
-+  {"scs",	HB_TAG('S','L','A',' ')},	/* North Slavey -> Slavey */
-+  {"scs",	HB_TAG('A','T','H',' ')},	/* North Slavey -> Athapaskan */
-+  {"sd",	HB_TAG('S','N','D',' ')},	/* Sindhi */
-+  {"sdc",	HB_TAG('S','R','D',' ')},	/* Sassarese Sardinian -> Sardinian */
-+  {"sdh",	HB_TAG('K','U','R',' ')},	/* Southern Kurdish -> Kurdish */
-+  {"sdn",	HB_TAG('S','R','D',' ')},	/* Gallurese Sardinian -> Sardinian */
-+  {"se",	HB_TAG('N','S','M',' ')},	/* Northern Sami */
-+  {"seh",	HB_TAG('S','N','A',' ')},	/* Sena */
-+  {"sek",	HB_TAG('A','T','H',' ')},	/* Sekani -> Athapaskan */
-+/*{"sel",	HB_TAG('S','E','L',' ')},*/	/* Selkup */
-+  {"sez",	HB_TAG('Q','I','N',' ')},	/* Senthang Chin -> Chin */
-+  {"sfm",	HB_TAG('H','M','N',' ')},	/* Small Flowery Miao -> Hmong */
-+  {"sg",	HB_TAG('S','G','O',' ')},	/* Sango */
-+/*{"sga",	HB_TAG('S','G','A',' ')},*/	/* Old Irish (to 900) */
-+  {"sgc",	HB_TAG('K','A','L',' ')},	/* Kipsigis -> Kalenjin */
-+/*{"sgs",	HB_TAG('S','G','S',' ')},*/	/* Samogitian */
-+  {"sgw",	HB_TAG('C','H','G',' ')},	/* Sebat Bet Gurage -> Chaha Gurage */
-+  {"sgw",	HB_TAG('S','G','W',' ')},	/* Sebat Bet Gurage -> Chaha Gurage (SIL fonts) */
-+/*{"shi",	HB_TAG('S','H','I',' ')},*/	/* Tachelhit */
-+/*{"shn",	HB_TAG('S','H','N',' ')},*/	/* Shan */
-+  {"shu",	HB_TAG('A','R','A',' ')},	/* Chadian Arabic -> Arabic */
-+  {"si",	HB_TAG('S','N','H',' ')},	/* Sinhala (Sinhalese) */
-+/*{"sid",	HB_TAG('S','I','D',' ')},*/	/* Sidamo */
-+  {"sjd",	HB_TAG('K','S','M',' ')},	/* Kildin Sami */
-+  {"sjo",	HB_TAG('S','I','B',' ')},	/* Xibe -> Sibe */
-+  {"sk",	HB_TAG('S','K','Y',' ')},	/* Slovak */
-+  {"skg",	HB_TAG('M','L','G',' ')},	/* Sakalava Malagasy -> Malagasy */
-+  {"skr",	HB_TAG('S','R','K',' ')},	/* Saraiki */
-+  {"sl",	HB_TAG('S','L','V',' ')},	/* Slovenian */
-+  {"sm",	HB_TAG('S','M','O',' ')},	/* Samoan */
-+  {"sma",	HB_TAG('S','S','M',' ')},	/* Southern Sami */
-+  {"smj",	HB_TAG('L','S','M',' ')},	/* Lule Sami */
-+  {"smn",	HB_TAG('I','S','M',' ')},	/* Inari Sami */
-+  {"sms",	HB_TAG('S','K','S',' ')},	/* Skolt Sami */
-+  {"sn",	HB_TAG('S','N','A','0')},	/* Shona */
-+/*{"snk",	HB_TAG('S','N','K',' ')},*/	/* Soninke */
-+  {"so",	HB_TAG('S','M','L',' ')},	/* Somali */
-+/*{"sop",	HB_TAG('S','O','P',' ')},*/	/* Songe */
-+  {"spv",	HB_TAG('O','R','I',' ')},	/* Sambalpuri -> Odia (formerly Oriya) */
-+  {"spy",	HB_TAG('K','A','L',' ')},	/* Sabaot -> Kalenjin */
-+  {"sq",	HB_TAG('S','Q','I',' ')},	/* Albanian [macrolanguage] */
-+  {"sr",	HB_TAG('S','R','B',' ')},	/* Serbian */
-+  {"src",	HB_TAG('S','R','D',' ')},	/* Logudorese Sardinian -> Sardinian */
-+  {"sro",	HB_TAG('S','R','D',' ')},	/* Campidanese Sardinian -> Sardinian */
-+/*{"srr",	HB_TAG('S','R','R',' ')},*/	/* Serer */
-+  {"srs",	HB_TAG('A','T','H',' ')},	/* Sarsi -> Athapaskan */
-+  {"ss",	HB_TAG('S','W','Z',' ')},	/* Swati */
-+  {"ssh",	HB_TAG('A','R','A',' ')},	/* Shihhi Arabic -> Arabic */
-+  {"st",	HB_TAG('S','O','T',' ')},	/* Southern Sotho -> Sotho, Southern */
-+/*{"stq",	HB_TAG('S','T','Q',' ')},*/	/* Saterfriesisch -> Saterland Frisian */
-+  {"stv",	HB_TAG('S','I','G',' ')},	/* Silt'e -> Silte Gurage */
-+  {"su",	HB_TAG('S','U','N',' ')},	/* Sundanese */
-+/*{"suk",	HB_TAG('S','U','K',' ')},*/	/* Sukuma */
-+  {"suq",	HB_TAG('S','U','R',' ')},	/* Suri */
-+  {"sv",	HB_TAG('S','V','E',' ')},	/* Swedish */
-+/*{"sva",	HB_TAG('S','V','A',' ')},*/	/* Svan */
-+  {"sw",	HB_TAG('S','W','K',' ')},	/* Swahili [macrolanguage] */
-+  {"swb",	HB_TAG('C','M','R',' ')},	/* Maore Comorian -> Comorian */
-+  {"swc",	HB_TAG('S','W','K',' ')},	/* Congo Swahili -> Swahili */
-+  {"swh",	HB_TAG('S','W','K',' ')},	/* Swahili */
-+  {"swv",	HB_TAG('M','A','W',' ')},	/* Shekhawati -> Marwari */
-+/*{"sxu",	HB_TAG('S','X','U',' ')},*/	/* Upper Saxon */
-+  {"syc",	HB_TAG('S','Y','R',' ')},	/* Classical Syriac -> Syriac */
-+/*{"syl",	HB_TAG('S','Y','L',' ')},*/	/* Sylheti */
-+/*{"syr",	HB_TAG('S','Y','R',' ')},*/	/* Syriac [macrolanguage] */
-+/*{"szl",	HB_TAG('S','Z','L',' ')},*/	/* Silesian */
-+  {"ta",	HB_TAG('T','A','M',' ')},	/* Tamil */
-+  {"taa",	HB_TAG('A','T','H',' ')},	/* Lower Tanana -> Athapaskan */
-+/*{"tab",	HB_TAG('T','A','B',' ')},*/	/* Tabassaran -> Tabasaran */
-+  {"taq",	HB_TAG('T','M','H',' ')},	/* Tamasheq -> Tamashek */
-+  {"tau",	HB_TAG('A','T','H',' ')},	/* Upper Tanana -> Athapaskan */
-+  {"tcb",	HB_TAG('A','T','H',' ')},	/* Tanacross -> Athapaskan */
-+  {"tce",	HB_TAG('A','T','H',' ')},	/* Southern Tutchone -> Athapaskan */
-+  {"tcp",	HB_TAG('Q','I','N',' ')},	/* Tawr Chin -> Chin */
-+  {"tcy",	HB_TAG('T','U','L',' ')},	/* Tulu -> Tumbuka */
-+  {"tcz",	HB_TAG('Q','I','N',' ')},	/* Thado Chin -> Chin */
-+/*{"tdd",	HB_TAG('T','D','D',' ')},*/	/* Tai Nüa -> Dehong Dai */
-+  {"tdx",	HB_TAG('M','L','G',' ')},	/* Tandroy-Mahafaly Malagasy -> Malagasy */
-+  {"te",	HB_TAG('T','E','L',' ')},	/* Telugu */
-+  {"tec",	HB_TAG('K','A','L',' ')},	/* Terik -> Kalenjin */
-+  {"tem",	HB_TAG('T','M','N',' ')},	/* Timne -> Temne */
-+/*{"tet",	HB_TAG('T','E','T',' ')},*/	/* Tetum */
-+  {"tfn",	HB_TAG('A','T','H',' ')},	/* Tanaina -> Athapaskan */
-+  {"tg",	HB_TAG('T','A','J',' ')},	/* Tajik -> Tajiki */
-+  {"tgj",	HB_TAG('N','I','S',' ')},	/* Tagin -> Nisi */
-+  {"tgx",	HB_TAG('A','T','H',' ')},	/* Tagish -> Athapaskan */
-+  {"th",	HB_TAG('T','H','A',' ')},	/* Thai */
-+  {"tht",	HB_TAG('A','T','H',' ')},	/* Tahltan -> Athapaskan */
-+  {"thv",	HB_TAG('T','M','H',' ')},	/* Tahaggart Tamahaq -> Tamashek */
-+  {"thz",	HB_TAG('T','M','H',' ')},	/* Tayart Tamajeq -> Tamashek */
-+  {"ti",	HB_TAG('T','G','Y',' ')},	/* Tigrinya */
-+  {"tig",	HB_TAG('T','G','R',' ')},	/* Tigre */
-+/*{"tiv",	HB_TAG('T','I','V',' ')},*/	/* Tiv */
-+  {"tk",	HB_TAG('T','K','M',' ')},	/* Turkmen */
-+  {"tkg",	HB_TAG('M','L','G',' ')},	/* Tesaka Malagasy -> Malagasy */
-+  {"tl",	HB_TAG('T','G','L',' ')},	/* Tagalog */
-+/*{"tmh",	HB_TAG('T','M','H',' ')},*/	/* Tamashek [macrolanguage] */
-+  {"tmw",	HB_TAG('M','L','Y',' ')},	/* Temuan -> Malay */
-+  {"tn",	HB_TAG('T','N','A',' ')},	/* Tswana */
-+  {"tnf",	HB_TAG('D','R','I',' ')},	/* Tangshewi (retired code) -> Dari */
-+  {"to",	HB_TAG('T','G','N',' ')},	/* Tonga (Tonga Islands) -> Tongan */
-+  {"tod",	HB_TAG('T','O','D','0')},	/* Toma */
-+  {"toi",	HB_TAG('T','N','G',' ')},	/* Tonga (Zambia) */
-+  {"tol",	HB_TAG('A','T','H',' ')},	/* Tolowa -> Athapaskan */
-+/*{"tpi",	HB_TAG('T','P','I',' ')},*/	/* Tok Pisin */
-+  {"tr",	HB_TAG('T','R','K',' ')},	/* Turkish */
-+  {"tru",	HB_TAG('T','U','A',' ')},	/* Turoyo -> Turoyo Aramaic */
-+  {"tru",	HB_TAG('S','Y','R',' ')},	/* Turoyo -> Syriac */
-+  {"ts",	HB_TAG('T','S','G',' ')},	/* Tsonga */
-+/*{"tsj",	HB_TAG('T','S','J',' ')},*/	/* Tshangla */
-+  {"tt",	HB_TAG('T','A','T',' ')},	/* Tatar */
-+  {"ttm",	HB_TAG('A','T','H',' ')},	/* Northern Tutchone -> Athapaskan */
-+  {"ttq",	HB_TAG('T','M','H',' ')},	/* Tawallammat Tamajaq -> Tamashek */
-+/*{"tum",	HB_TAG('T','U','M',' ')},*/	/* Tumbuka -> Tulu */
-+  {"tuu",	HB_TAG('A','T','H',' ')},	/* Tututni -> Athapaskan */
-+  {"tuy",	HB_TAG('K','A','L',' ')},	/* Tugen -> Kalenjin */
-+/*{"tvl",	HB_TAG('T','V','L',' ')},*/	/* Tuvalu */
-+  {"tw",	HB_TAG('T','W','I',' ')},	/* Twi */
-+  {"tw",	HB_TAG('A','K','A',' ')},	/* Twi -> Akan */
-+  {"txc",	HB_TAG('A','T','H',' ')},	/* Tsetsaut -> Athapaskan */
-+  {"txy",	HB_TAG('M','L','G',' ')},	/* Tanosy Malagasy -> Malagasy */
-+  {"ty",	HB_TAG('T','H','T',' ')},	/* Tahitian */
-+  {"tyv",	HB_TAG('T','U','V',' ')},	/* Tuvinian -> Tuvin */
-+/*{"tyz",	HB_TAG('T','Y','Z',' ')},*/	/* Tày */
-+/*{"tzm",	HB_TAG('T','Z','M',' ')},*/	/* Central Atlas Tamazight -> Tamazight */
-+/*{"tzo",	HB_TAG('T','Z','O',' ')},*/	/* Tzotzil */
-+  {"ubl",	HB_TAG('B','I','K',' ')},	/* Buhi'non Bikol -> Bikol */
-+/*{"udm",	HB_TAG('U','D','M',' ')},*/	/* Udmurt */
-+  {"ug",	HB_TAG('U','Y','G',' ')},	/* Uyghur */
-+  {"uk",	HB_TAG('U','K','R',' ')},	/* Ukrainian */
-+/*{"umb",	HB_TAG('U','M','B',' ')},*/	/* Umbundu */
-+  {"unr",	HB_TAG('M','U','N',' ')},	/* Mundari */
-+  {"ur",	HB_TAG('U','R','D',' ')},	/* Urdu */
-+  {"urk",	HB_TAG('M','L','Y',' ')},	/* Urak Lawoi' -> Malay */
-+  {"uz",	HB_TAG('U','Z','B',' ')},	/* Uzbek [macrolanguage] */
-+  {"uzn",	HB_TAG('U','Z','B',' ')},	/* Northern Uzbek -> Uzbek */
-+  {"uzs",	HB_TAG('U','Z','B',' ')},	/* Southern Uzbek -> Uzbek */
-+  {"ve",	HB_TAG('V','E','N',' ')},	/* Venda */
-+/*{"vec",	HB_TAG('V','E','C',' ')},*/	/* Venetian */
-+  {"vi",	HB_TAG('V','I','T',' ')},	/* Vietnamese */
-+  {"vkk",	HB_TAG('M','L','Y',' ')},	/* Kaur -> Malay */
-+  {"vkt",	HB_TAG('M','L','Y',' ')},	/* Tenggarong Kutai Malay -> Malay */
-+  {"vls",	HB_TAG('F','L','E',' ')},	/* Vlaams -> Dutch (Flemish) */
-+  {"vmw",	HB_TAG('M','A','K',' ')},	/* Makhuwa */
-+  {"vo",	HB_TAG('V','O','L',' ')},	/* Volapük */
-+/*{"vro",	HB_TAG('V','R','O',' ')},*/	/* Võro */
-+  {"wa",	HB_TAG('W','L','N',' ')},	/* Walloon */
-+/*{"war",	HB_TAG('W','A','R',' ')},*/	/* Waray (Philippines) -> Waray-Waray */
-+  {"wbm",	HB_TAG('W','A',' ',' ')},	/* Wa */
-+  {"wbr",	HB_TAG('W','A','G',' ')},	/* Wagdi */
-+  {"wlc",	HB_TAG('C','M','R',' ')},	/* Mwali Comorian -> Comorian */
-+  {"wle",	HB_TAG('S','I','G',' ')},	/* Wolane -> Silte Gurage */
-+  {"wlk",	HB_TAG('A','T','H',' ')},	/* Wailaki -> Athapaskan */
-+  {"wni",	HB_TAG('C','M','R',' ')},	/* Ndzwani Comorian -> Comorian */
-+  {"wo",	HB_TAG('W','L','F',' ')},	/* Wolof */
-+  {"wry",	HB_TAG('M','A','W',' ')},	/* Merwari -> Marwari */
-+  {"wsg",	HB_TAG('G','O','N',' ')},	/* Adilabad Gondi -> Gondi */
-+/*{"wtm",	HB_TAG('W','T','M',' ')},*/	/* Mewati */
-+  {"wuu",	HB_TAG('Z','H','S',' ')},	/* Wu Chinese -> Chinese Simplified */
-+  {"xal",	HB_TAG('K','L','M',' ')},	/* Kalmyk */
-+  {"xal",	HB_TAG('T','O','D',' ')},	/* Kalmyk -> Todo */
-+  {"xan",	HB_TAG('S','E','K',' ')},	/* Xamtanga -> Sekota */
-+  {"xh",	HB_TAG('X','H','S',' ')},	/* Xhosa */
-+/*{"xjb",	HB_TAG('X','J','B',' ')},*/	/* Minjungbal -> Minjangbal */
-+/*{"xkf",	HB_TAG('X','K','F',' ')},*/	/* Khengkha */
-+  {"xmm",	HB_TAG('M','L','Y',' ')},	/* Manado Malay -> Malay */
-+  {"xmv",	HB_TAG('M','L','G',' ')},	/* Antankarana Malagasy -> Malagasy */
-+  {"xmw",	HB_TAG('M','L','G',' ')},	/* Tsimihety Malagasy -> Malagasy */
-+  {"xnr",	HB_TAG('D','G','R',' ')},	/* Kangri -> Dogri */
-+/*{"xog",	HB_TAG('X','O','G',' ')},*/	/* Soga */
-+/*{"xpe",	HB_TAG('X','P','E',' ')},*/	/* Liberia Kpelle -> Kpelle (Liberia) */
-+  {"xsl",	HB_TAG('S','S','L',' ')},	/* South Slavey */
-+  {"xsl",	HB_TAG('S','L','A',' ')},	/* South Slavey -> Slavey */
-+  {"xsl",	HB_TAG('A','T','H',' ')},	/* South Slavey -> Athapaskan */
-+  {"xst",	HB_TAG('S','I','G',' ')},	/* Silt'e (retired code) -> Silte Gurage */
-+  {"xwo",	HB_TAG('T','O','D',' ')},	/* Written Oirat -> Todo */
-+/*{"yao",	HB_TAG('Y','A','O',' ')},*/	/* Yao */
-+/*{"yap",	HB_TAG('Y','A','P',' ')},*/	/* Yapese */
-+  {"ybd",	HB_TAG('A','R','K',' ')},	/* Yangbye (retired code) -> Rakhine */
-+  {"ydd",	HB_TAG('J','I','I',' ')},	/* Eastern Yiddish -> Yiddish */
-+  {"yi",	HB_TAG('J','I','I',' ')},	/* Yiddish [macrolanguage] */
-+  {"yih",	HB_TAG('J','I','I',' ')},	/* Western Yiddish -> Yiddish */
-+  {"yo",	HB_TAG('Y','B','A',' ')},	/* Yoruba */
-+  {"yos",	HB_TAG('Q','I','N',' ')},	/* Yos (retired code) -> Chin */
-+  {"yrk",	HB_TAG('T','N','E',' ')},	/* Nenets -> Tundra Nenets */
-+  {"yrk",	HB_TAG('F','N','E',' ')},	/* Nenets -> Forest Nenets */
-+  {"yue",	HB_TAG('Z','H','H',' ')},	/* Yue Chinese -> Chinese, Hong Kong SAR */
-+  {"za",	HB_TAG('Z','H','A',' ')},	/* Zhuang [macrolanguage] */
-+  {"zch",	HB_TAG('Z','H','A',' ')},	/* Central Hongshuihe Zhuang -> Zhuang */
-+  {"zdj",	HB_TAG('C','M','R',' ')},	/* Ngazidja Comorian -> Comorian */
-+/*{"zea",	HB_TAG('Z','E','A',' ')},*/	/* Zeeuws -> Zealandic */
-+  {"zeh",	HB_TAG('Z','H','A',' ')},	/* Eastern Hongshuihe Zhuang -> Zhuang */
-+  {"zgb",	HB_TAG('Z','H','A',' ')},	/* Guibei Zhuang -> Zhuang */
-+/*{"zgh",	HB_TAG('Z','G','H',' ')},*/	/* Standard Moroccan Tamazight */
-+  {"zgm",	HB_TAG('Z','H','A',' ')},	/* Minz Zhuang -> Zhuang */
-+  {"zgn",	HB_TAG('Z','H','A',' ')},	/* Guibian Zhuang -> Zhuang */
-+  {"zh",	HB_TAG('Z','H','S',' ')},	/* Chinese [macrolanguage] -> Chinese Simplified */
-+  {"zhd",	HB_TAG('Z','H','A',' ')},	/* Dai Zhuang -> Zhuang */
-+  {"zhn",	HB_TAG('Z','H','A',' ')},	/* Nong Zhuang -> Zhuang */
-+  {"zlj",	HB_TAG('Z','H','A',' ')},	/* Liujiang Zhuang -> Zhuang */
-+  {"zlm",	HB_TAG('M','L','Y',' ')},	/* Malay */
-+  {"zln",	HB_TAG('Z','H','A',' ')},	/* Lianshan Zhuang -> Zhuang */
-+  {"zlq",	HB_TAG('Z','H','A',' ')},	/* Liuqian Zhuang -> Zhuang */
-+  {"zmi",	HB_TAG('M','L','Y',' ')},	/* Negeri Sembilan Malay -> Malay */
-+  {"zne",	HB_TAG('Z','N','D',' ')},	/* Zande */
-+  {"zom",	HB_TAG('Q','I','N',' ')},	/* Zou -> Chin */
-+  {"zqe",	HB_TAG('Z','H','A',' ')},	/* Qiubei Zhuang -> Zhuang */
-+  {"zsm",	HB_TAG('M','L','Y',' ')},	/* Standard Malay -> Malay */
-+  {"zu",	HB_TAG('Z','U','L',' ')},	/* Zulu */
-+  {"zum",	HB_TAG('L','R','C',' ')},	/* Kumzari -> Luri */
-+  {"zyb",	HB_TAG('Z','H','A',' ')},	/* Yongbei Zhuang -> Zhuang */
-+  {"zyg",	HB_TAG('Z','H','A',' ')},	/* Yang Zhuang -> Zhuang */
-+  {"zyj",	HB_TAG('Z','H','A',' ')},	/* Youjiang Zhuang -> Zhuang */
-+  {"zyn",	HB_TAG('Z','H','A',' ')},	/* Yongnan Zhuang -> Zhuang */
-+/*{"zza",	HB_TAG('Z','Z','A',' ')},*/	/* Zazaki [macrolanguage] */
-+  {"zzj",	HB_TAG('Z','H','A',' ')},	/* Zuojiang Zhuang -> Zhuang */
- };
- 
--static_assert (HB_OT_MAX_TAGS_PER_LANGUAGE == 3u, "");
--
- /**
-  * hb_ot_tags_from_complex_language:
-  * @lang_str: a BCP 47 language tag to convert.
-  * @limit: a pointer to the end of the substring of @lang_str to consider for
-  * conversion.
-  * @count: maximum number of language tags to retrieve (IN) and actual number of
-  * language tags retrieved (OUT). If no tags are retrieved, it is not modified.
-  * @tags: array of size at least @language_count to store the language tag
-@@ -1929,26 +1927,29 @@ hb_ot_tags_from_complex_language (const 
- }
- 
- /**
-  * hb_ot_ambiguous_tag_to_language
-  * @tag: A language tag.
-  *
-  * Converts @tag to a BCP 47 language tag if it is ambiguous (it corresponds to
-  * many language tags) and the best tag is not the alphabetically first, or if
-- * the best tag consists of multiple subtags.
-+ * the best tag consists of multiple subtags, or if the best tag does not appear
-+ * in #ot_languages.
-  *
-  * Return value: The #hb_language_t corresponding to the BCP 47 language tag,
-  * or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
-  **/
- static hb_language_t
- hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
- {
-   switch (tag)
-   {
-+  case HB_TAG('A','L','T',' '):  /* Altai */
-+    return hb_language_from_string ("alt", -1);  /* Southern Altai */
-   case HB_TAG('A','P','P','H'):  /* Phonetic transcription—Americanist conventions */
-     return hb_language_from_string ("und-fonnapa", -1);  /* Undetermined; North American Phonetic Alphabet */
-   case HB_TAG('A','R','A',' '):  /* Arabic */
-     return hb_language_from_string ("ar", -1);  /* Arabic */
-   case HB_TAG('A','R','K',' '):  /* Rakhine */
-     return hb_language_from_string ("rki", -1);  /* Rakhine */
-   case HB_TAG('A','T','H',' '):  /* Athapaskan */
-     return hb_language_from_string ("ath", -1);  /* Athapascan */
-@@ -1957,26 +1958,26 @@ hb_ot_ambiguous_tag_to_language (hb_tag_
-   case HB_TAG('C','P','P',' '):  /* Creoles */
-     return hb_language_from_string ("crp", -1);  /* Creoles and pidgins */
-   case HB_TAG('C','R','R',' '):  /* Carrier */
-     return hb_language_from_string ("crx", -1);  /* Carrier */
-   case HB_TAG('D','N','K',' '):  /* Dinka */
-     return hb_language_from_string ("din", -1);  /* Dinka */
-   case HB_TAG('D','R','I',' '):  /* Dari */
-     return hb_language_from_string ("prs", -1);  /* Dari */
--  case HB_TAG('D','U','J',' '):  /* Dhuwal */
--    return hb_language_from_string ("dwu", -1);  /* Dhuwal */
-   case HB_TAG('D','Z','N',' '):  /* Dzongkha */
-     return hb_language_from_string ("dz", -1);  /* Dzongkha */
-   case HB_TAG('E','T','I',' '):  /* Estonian */
-     return hb_language_from_string ("et", -1);  /* Estonian */
-   case HB_TAG('G','O','N',' '):  /* Gondi */
-     return hb_language_from_string ("gon", -1);  /* Gondi */
-   case HB_TAG('H','M','N',' '):  /* Hmong */
-     return hb_language_from_string ("hmn", -1);  /* Hmong */
-+  case HB_TAG('H','N','D',' '):  /* Hindko */
-+    return hb_language_from_string ("hnd", -1);  /* Southern Hindko */
-   case HB_TAG('I','J','O',' '):  /* Ijo */
-     return hb_language_from_string ("ijo", -1);  /* Ijo */
-   case HB_TAG('I','N','U',' '):  /* Inuktitut */
-     return hb_language_from_string ("iu", -1);  /* Inuktitut */
-   case HB_TAG('I','P','K',' '):  /* Inupiat */
-     return hb_language_from_string ("ik", -1);  /* Inupiaq */
-   case HB_TAG('I','P','P','H'):  /* Phonetic transcription—IPA conventions */
-     return hb_language_from_string ("und-fonipa", -1);  /* Undetermined; International Phonetic Alphabet */
-diff --git a/gfx/harfbuzz/src/hb-ot-tag.cc b/gfx/harfbuzz/src/hb-ot-tag.cc
---- a/gfx/harfbuzz/src/hb-ot-tag.cc
-+++ b/gfx/harfbuzz/src/hb-ot-tag.cc
-@@ -108,27 +108,29 @@ hb_ot_new_tag_to_script (hb_tag_t tag)
-     case HB_TAG('t','m','l','2'):	return HB_SCRIPT_TAMIL;
-     case HB_TAG('t','e','l','2'):	return HB_SCRIPT_TELUGU;
-     case HB_TAG('m','y','m','2'):	return HB_SCRIPT_MYANMAR;
-   }
- 
-   return HB_SCRIPT_UNKNOWN;
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- void
- hb_ot_tags_from_script (hb_script_t  script,
- 			hb_tag_t    *script_tag_1,
- 			hb_tag_t    *script_tag_2)
- {
-   unsigned int count = 2;
-   hb_tag_t tags[2];
-   hb_ot_tags_from_script_and_language (script, HB_LANGUAGE_INVALID, &count, tags, nullptr, nullptr);
-   *script_tag_1 = count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_SCRIPT;
-   *script_tag_2 = count > 1 ? tags[1] : HB_OT_TAG_DEFAULT_SCRIPT;
- }
-+#endif
- 
- /*
-  * Complete list at:
-  * https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags
-  *
-  * Most of the script tags are the same as the ISO 15924 tag but lowercased.
-  * So we just do that, and handle the exceptional cases in a switch.
-  */
-@@ -193,31 +195,31 @@ lang_matches (const char *lang_str, cons
- 
-   return strncmp (lang_str, spec, len) == 0 &&
- 	 (lang_str[len] == '\0' || lang_str[len] == '-');
- }
- 
- struct LangTag
- {
-   char language[4];
--  hb_tag_t tags[HB_OT_MAX_TAGS_PER_LANGUAGE];
-+  hb_tag_t tag;
- 
-   int cmp (const char *a) const
-   {
-     const char *b = this->language;
-     unsigned int da, db;
-     const char *p;
- 
-     p = strchr (a, '-');
-     da = p ? (unsigned int) (p - a) : strlen (a);
- 
-     p = strchr (b, '-');
-     db = p ? (unsigned int) (p - b) : strlen (b);
- 
--    return strncmp (a, b, MAX (da, db));
-+    return strncmp (a, b, hb_max (da, db));
-   }
-   int cmp (const LangTag *that) const
-   { return cmp (that->language); }
- };
- 
- #include "hb-ot-tag-table.hh"
- 
- /* The corresponding languages IDs for the following IDs are unclear,
-@@ -225,55 +227,63 @@ struct LangTag
- 
- /*{"??",	{HB_TAG('B','C','R',' ')}},*/	/* Bible Cree */
- /*{"zh?",	{HB_TAG('C','H','N',' ')}},*/	/* Chinese (seen in Microsoft fonts) */
- /*{"ar-Syrc?",	{HB_TAG('G','A','R',' ')}},*/	/* Garshuni */
- /*{"??",	{HB_TAG('N','G','R',' ')}},*/	/* Nagari */
- /*{"??",	{HB_TAG('Y','I','C',' ')}},*/	/* Yi Classic */
- /*{"zh?",	{HB_TAG('Z','H','P',' ')}},*/	/* Chinese Phonetic */
- 
-+#ifndef HB_DISABLE_DEPRECATED
- hb_tag_t
- hb_ot_tag_from_language (hb_language_t language)
- {
-   unsigned int count = 1;
-   hb_tag_t tags[1];
-   hb_ot_tags_from_script_and_language (HB_SCRIPT_UNKNOWN, language, nullptr, nullptr, &count, tags);
-   return count > 0 ? tags[0] : HB_OT_TAG_DEFAULT_LANGUAGE;
- }
-+#endif
- 
- static void
- hb_ot_tags_from_language (const char   *lang_str,
- 			  const char   *limit,
- 			  unsigned int *count,
- 			  hb_tag_t     *tags)
- {
-   const char *s;
-+  unsigned int tag_idx;
- 
-   /* Check for matches of multiple subtags. */
-   if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags))
-     return;
- 
-   /* Find a language matching in the first component. */
-   s = strchr (lang_str, '-');
-   {
--    const LangTag *lang_tag;
-     if (s && limit - lang_str >= 6)
-     {
-       const char *extlang_end = strchr (s + 1, '-');
-       /* If there is an extended language tag, use it. */
-       if (3 == (extlang_end ? extlang_end - s - 1 : strlen (s + 1)) &&
- 	  ISALPHA (s[1]))
- 	lang_str = s + 1;
-     }
--    lang_tag = hb_sorted_array (ot_languages).bsearch (lang_str);
--    if (lang_tag)
-+    if (hb_sorted_array (ot_languages).bfind (lang_str, &tag_idx))
-     {
-       unsigned int i;
--      for (i = 0; i < *count && lang_tag->tags[i] != HB_TAG_NONE; i++)
--	tags[i] = lang_tag->tags[i];
-+      while (tag_idx != 0 &&
-+	     0 == strcmp (ot_languages[tag_idx].language, ot_languages[tag_idx - 1].language))
-+	tag_idx--;
-+      for (i = 0;
-+	   i < *count &&
-+	   tag_idx + i < ARRAY_LENGTH (ot_languages) &&
-+	   0 == strcmp (ot_languages[tag_idx + i].language, ot_languages[tag_idx].language);
-+	   i++)
-+	tags[i] = ot_languages[tag_idx + i].tag;
-       *count = i;
-       return;
-     }
-   }
- 
-   if (!s)
-     s = lang_str + strlen (lang_str);
-   if (s - lang_str == 3) {
-@@ -412,30 +422,43 @@ hb_ot_tag_to_language (hb_tag_t tag)
- 
-   {
-     hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag);
-     if (disambiguated_tag != HB_LANGUAGE_INVALID)
-       return disambiguated_tag;
-   }
- 
-   for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
--    if (ot_languages[i].tags[0] == tag)
-+    if (ot_languages[i].tag == tag)
-       return hb_language_from_string (ot_languages[i].language, -1);
- 
--  /* Else return a custom language in the form of "x-hbotABCD" */
-+  /* If it's three letters long, assume it's ISO 639-3 and lower-case and use it
-+   * (if it's not a registered tag, calling hb_ot_tag_from_language on the
-+   * result might not return the same tag as the original tag).
-+   * Else return a custom language in the form of "x-hbotABCD". */
-   {
--    unsigned char buf[11] = "x-hbot";
-+    char buf[11] = "x-hbot";
-+    char *str = buf;
-     buf[6] = tag >> 24;
-     buf[7] = (tag >> 16) & 0xFF;
-     buf[8] = (tag >> 8) & 0xFF;
-     buf[9] = tag & 0xFF;
-     if (buf[9] == 0x20)
-+    {
-       buf[9] = '\0';
-+      if (ISALPHA (buf[6]) && ISALPHA (buf[7]) && ISALPHA (buf[8]))
-+      {
-+	buf[6] = TOLOWER (buf[6]);
-+	buf[7] = TOLOWER (buf[7]);
-+	buf[8] = TOLOWER (buf[8]);
-+	str += 6;
-+      }
-+    }
-     buf[10] = '\0';
--    return hb_language_from_string ((char *) buf, -1);
-+    return hb_language_from_string (str, -1);
-   }
- }
- 
- /**
-  * hb_ot_tags_to_script_and_language:
-  * @script_tag: a script tag
-  * @language_tag: a language tag
-  * @script: (allow-none): the #hb_script_t corresponding to @script_tag (OUT).
-@@ -501,17 +524,17 @@ hb_ot_tags_to_script_and_language (hb_ta
- 
- #ifdef MAIN
- static inline void
- test_langs_sorted ()
- {
-   for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
-   {
-     int c = ot_languages[i].cmp (&ot_languages[i - 1]);
--    if (c >= 0)
-+    if (c > 0)
-     {
-       fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n",
- 	       i, ot_languages[i-1].language, c, ot_languages[i].language);
-       abort();
-     }
-   }
- }
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-var-avar-table.hh b/gfx/harfbuzz/src/hb-ot-var-avar-table.hh
---- a/gfx/harfbuzz/src/hb-ot-var-avar-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-var-avar-table.hh
-@@ -118,17 +118,17 @@ struct avar
-       map = &StructAfter<SegmentMaps> (*map);
-     }
- 
-     return_trace (true);
-   }
- 
-   void map_coords (int *coords, unsigned int coords_length) const
-   {
--    unsigned int count = MIN<unsigned int> (coords_length, axisCount);
-+    unsigned int count = hb_min (coords_length, axisCount);
- 
-     const SegmentMaps *map = &firstAxisSegmentMaps;
-     for (unsigned int i = 0; i < count; i++)
-     {
-       coords[i] = map->map (coords[i]);
-       map = &StructAfter<SegmentMaps> (*map);
-     }
-   }
-diff --git a/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh b/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
---- a/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-var-fvar-table.hh
-@@ -109,87 +109,92 @@ struct fvar
- 		  axisSize == 20 && /* Assumed in our code. */
- 		  instanceSize >= axisCount * 4 + 4 &&
- 		  get_axes ().sanitize (c) &&
- 		  c->check_range (get_instance (0), instanceCount, instanceSize));
-   }
- 
-   unsigned int get_axis_count () const { return axisCount; }
- 
-+#ifndef HB_DISABLE_DEPRECATED
-   void get_axis_deprecated (unsigned int axis_index,
- 				   hb_ot_var_axis_t *info) const
-   {
-     const AxisRecord &axis = get_axes ()[axis_index];
-     info->tag = axis.axisTag;
-     info->name_id =  axis.axisNameID;
--    info->default_value = axis.defaultValue / 65536.;
-+    info->default_value = axis.defaultValue / 65536.f;
-     /* Ensure order, to simplify client math. */
--    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
--    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
-+    info->min_value = hb_min (info->default_value, axis.minValue / 65536.f);
-+    info->max_value = hb_max (info->default_value, axis.maxValue / 65536.f);
-   }
-+#endif
- 
-   void get_axis_info (unsigned int axis_index,
- 		      hb_ot_var_axis_info_t *info) const
-   {
-     const AxisRecord &axis = get_axes ()[axis_index];
-     info->axis_index = axis_index;
-     info->tag = axis.axisTag;
-     info->name_id =  axis.axisNameID;
-     info->flags = (hb_ot_var_axis_flags_t) (unsigned int) axis.flags;
--    info->default_value = axis.defaultValue / 65536.;
-+    info->default_value = axis.defaultValue / 65536.f;
-     /* Ensure order, to simplify client math. */
--    info->min_value = MIN<float> (info->default_value, axis.minValue / 65536.);
--    info->max_value = MAX<float> (info->default_value, axis.maxValue / 65536.);
-+    info->min_value = hb_min (info->default_value, axis.minValue / 65536.f);
-+    info->max_value = hb_max (info->default_value, axis.maxValue / 65536.f);
-     info->reserved = 0;
-   }
- 
-+#ifndef HB_DISABLE_DEPRECATED
-   unsigned int get_axes_deprecated (unsigned int      start_offset,
- 				    unsigned int     *axes_count /* IN/OUT */,
- 				    hb_ot_var_axis_t *axes_array /* OUT */) const
-   {
-     if (axes_count)
-     {
-       /* TODO Rewrite as hb_array_t<>::sub-array() */
-       unsigned int count = axisCount;
--      start_offset = MIN (start_offset, count);
-+      start_offset = hb_min (start_offset, count);
- 
-       count -= start_offset;
-       axes_array += start_offset;
- 
--      count = MIN (count, *axes_count);
-+      count = hb_min (count, *axes_count);
-       *axes_count = count;
- 
-       for (unsigned int i = 0; i < count; i++)
- 	get_axis_deprecated (start_offset + i, axes_array + i);
-     }
-     return axisCount;
-   }
-+#endif
- 
-   unsigned int get_axis_infos (unsigned int           start_offset,
- 			       unsigned int          *axes_count /* IN/OUT */,
- 			       hb_ot_var_axis_info_t *axes_array /* OUT */) const
-   {
-     if (axes_count)
-     {
-       /* TODO Rewrite as hb_array_t<>::sub-array() */
-       unsigned int count = axisCount;
--      start_offset = MIN (start_offset, count);
-+      start_offset = hb_min (start_offset, count);
- 
-       count -= start_offset;
-       axes_array += start_offset;
- 
--      count = MIN (count, *axes_count);
-+      count = hb_min (count, *axes_count);
-       *axes_count = count;
- 
-       for (unsigned int i = 0; i < count; i++)
- 	get_axis_info (start_offset + i, axes_array + i);
-     }
-     return axisCount;
-   }
- 
-+#ifndef HB_DISABLE_DEPRECATED
-   bool find_axis_deprecated (hb_tag_t tag,
- 			     unsigned int *axis_index,
- 			     hb_ot_var_axis_t *info) const
-   {
-     const AxisRecord *axes = get_axes ();
-     unsigned int count = get_axis_count ();
-     for (unsigned int i = 0; i < count; i++)
-       if (axes[i].axisTag == tag)
-@@ -198,16 +203,17 @@ struct fvar
- 	  *axis_index = i;
- 	get_axis_deprecated (i, info);
- 	return true;
-       }
-     if (axis_index)
-       *axis_index = HB_OT_VAR_NO_AXIS_INDEX;
-     return false;
-   }
-+#endif
- 
-   bool find_axis_info (hb_tag_t tag,
- 		       hb_ot_var_axis_info_t *info) const
-   {
-     const AxisRecord *axes = get_axes ();
-     unsigned int count = get_axis_count ();
-     for (unsigned int i = 0; i < count; i++)
-       if (axes[i].axisTag == tag)
-@@ -218,17 +224,17 @@ struct fvar
-     return false;
-   }
- 
-   int normalize_axis_value (unsigned int axis_index, float v) const
-   {
-     hb_ot_var_axis_info_t axis;
-     get_axis_info (axis_index, &axis);
- 
--    v = MAX (MIN (v, axis.max_value), axis.min_value); /* Clamp. */
-+    v = hb_max (hb_min (v, axis.max_value), axis.min_value); /* Clamp. */
- 
-     if (v == axis.default_value)
-       return 0;
-     else if (v < axis.default_value)
-       v = (v - axis.default_value) / (axis.default_value - axis.min_value);
-     else
-       v = (v - axis.default_value) / (axis.max_value - axis.default_value);
-     return (int) (v * 16384.f + (v >= 0.f ? .5f : -.5f));
-@@ -248,18 +254,18 @@ struct fvar
-     const InstanceRecord *instance = get_instance (instance_index);
-     if (unlikely (!instance)) return HB_OT_NAME_ID_INVALID;
-     if (instanceSize >= axisCount * 4 + 6)
-       return StructAfter<NameID> (instance->get_coordinates (axisCount));
-     return HB_OT_NAME_ID_INVALID;
-   }
- 
-   unsigned int get_instance_coords (unsigned int  instance_index,
--					   unsigned int *coords_length, /* IN/OUT */
--					   float        *coords         /* OUT */) const
-+				    unsigned int *coords_length, /* IN/OUT */
-+				    float        *coords         /* OUT */) const
-   {
-     const InstanceRecord *instance = get_instance (instance_index);
-     if (unlikely (!instance))
-     {
-       if (coords_length)
-         *coords_length = 0;
-       return 0;
-     }
-@@ -269,16 +275,37 @@ struct fvar
-       hb_array_t<const Fixed> instanceCoords = instance->get_coordinates (axisCount)
- 							 .sub_array (0, *coords_length);
-       for (unsigned int i = 0; i < instanceCoords.length; i++)
-         coords[i] = instanceCoords.arrayZ[i].to_float ();
-     }
-     return axisCount;
-   }
- 
-+  void collect_name_ids (hb_set_t *nameids) const
-+  {
-+    if (!has_data ()) return;
-+
-+    + get_axes ()
-+    | hb_map (&AxisRecord::axisNameID)
-+    | hb_sink (nameids)
-+    ;
-+
-+    + hb_range ((unsigned) instanceCount)
-+    | hb_map ([this] (const unsigned _) { return get_instance_subfamily_name_id (_); })
-+    | hb_sink (nameids)
-+    ;
-+
-+    + hb_range ((unsigned) instanceCount)
-+    | hb_map ([this] (const unsigned _) { return get_instance_postscript_name_id (_); })
-+    | hb_sink (nameids)
-+    ;
-+  }
-+
-+
-   protected:
-   hb_array_t<const AxisRecord> get_axes () const
-   { return hb_array (&(this+firstAxis), axisCount); }
- 
-   const InstanceRecord *get_instance (unsigned int i) const
-   {
-     if (unlikely (i >= instanceCount)) return nullptr;
-    return &StructAtOffset<InstanceRecord> (&StructAfter<InstanceRecord> (get_axes ()),
-diff --git a/gfx/harfbuzz/src/hb-ot-var.cc b/gfx/harfbuzz/src/hb-ot-var.cc
---- a/gfx/harfbuzz/src/hb-ot-var.cc
-+++ b/gfx/harfbuzz/src/hb-ot-var.cc
-@@ -70,16 +70,17 @@ hb_ot_var_has_data (hb_face_t *face)
-  * Since: 1.4.2
-  **/
- unsigned int
- hb_ot_var_get_axis_count (hb_face_t *face)
- {
-   return face->table.fvar->get_axis_count ();
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_ot_var_get_axes:
-  *
-  * Since: 1.4.2
-  * Deprecated: 2.2.0
-  **/
- unsigned int
- hb_ot_var_get_axes (hb_face_t        *face,
-@@ -99,16 +100,17 @@ hb_ot_var_get_axes (hb_face_t        *fa
- hb_bool_t
- hb_ot_var_find_axis (hb_face_t        *face,
- 		     hb_tag_t          axis_tag,
- 		     unsigned int     *axis_index,
- 		     hb_ot_var_axis_t *axis_info)
- {
-   return face->table.fvar->find_axis_deprecated (axis_tag, axis_index, axis_info);
- }
-+#endif
- 
- /**
-  * hb_ot_var_get_axis_infos:
-  *
-  * Since: 2.2.0
-  **/
- HB_EXTERN unsigned int
- hb_ot_var_get_axis_infos (hb_face_t             *face,
-diff --git a/gfx/harfbuzz/src/hb-ot-vorg-table.hh b/gfx/harfbuzz/src/hb-ot-vorg-table.hh
---- a/gfx/harfbuzz/src/hb-ot-vorg-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-vorg-table.hh
-@@ -76,21 +76,21 @@ struct VORG
- 		void *dest) const
-   {
-     hb_serialize_context_t c (dest, dest_sz);
- 
-     VORG *subset_table = c.start_serialize<VORG> ();
-     if (unlikely (!c.extend_min (*subset_table)))
-       return false;
- 
--    subset_table->version.major.set (1);
--    subset_table->version.minor.set (0);
-+    subset_table->version.major = 1;
-+    subset_table->version.minor = 0;
- 
--    subset_table->defaultVertOriginY.set (vorg_table->defaultVertOriginY);
--    subset_table->vertYOrigins.len.set (subset_metrics.length);
-+    subset_table->defaultVertOriginY = vorg_table->defaultVertOriginY;
-+    subset_table->vertYOrigins.len = subset_metrics.length;
- 
-     bool success = true;
-     if (subset_metrics.length > 0)
-     {
-       unsigned int  size = VertOriginMetric::static_size * subset_metrics.length;
-       VertOriginMetric  *metrics = c.allocate_size<VertOriginMetric> (size);
-       if (likely (metrics != nullptr))
-         memcpy (metrics, &subset_metrics[0], size);
-@@ -125,18 +125,18 @@ struct VORG
-       }
- 
-       if (old_glyph == vertYOrigins[i].glyph)
-       {
-         hb_codepoint_t new_glyph;
-         if (plan->new_gid_for_old_gid (old_glyph, &new_glyph))
-         {
-           VertOriginMetric *metrics = subset_metrics.push ();
--          metrics->glyph.set (new_glyph);
--          metrics->vertOriginY.set (vertYOrigins[i].vertOriginY);
-+          metrics->glyph = new_glyph;
-+          metrics->vertOriginY = vertYOrigins[i].vertOriginY;
-         }
-       }
-     }
- 
-     /* alloc the new table */
-     unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.length;
-     void *dest = (void *) malloc (dest_sz);
-     if (unlikely (!dest))
-diff --git a/gfx/harfbuzz/src/hb-pool.hh b/gfx/harfbuzz/src/hb-pool.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-pool.hh
-@@ -0,0 +1,102 @@
-+/*
-+ * Copyright © 2019  Facebook, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Facebook Author(s): Behdad Esfahbod
-+ */
-+
-+#ifndef HB_POOL_HH
-+#define HB_POOL_HH
-+
-+#include "hb.hh"
-+
-+/* Memory pool for persistent allocation of small objects. */
-+
-+template <typename T, unsigned ChunkLen = 16>
-+struct hb_pool_t
-+{
-+  hb_pool_t () : next (nullptr) {}
-+  ~hb_pool_t () { fini (); }
-+
-+  void fini ()
-+  {
-+    next = nullptr;
-+
-+    + hb_iter (chunks)
-+    | hb_apply ([] (chunk_t *_) { ::free (_); })
-+    ;
-+
-+    chunks.fini ();
-+  }
-+
-+  T* alloc ()
-+  {
-+    if (unlikely (!next))
-+    {
-+      if (unlikely (!chunks.alloc (chunks.length + 1))) return nullptr;
-+      chunk_t *chunk = (chunk_t *) calloc (1, sizeof (chunk_t));
-+      if (unlikely (!chunk)) return nullptr;
-+      chunks.push (chunk);
-+      next = chunk->thread ();
-+    }
-+
-+    T* obj = next;
-+    next = * ((T**) next);
-+
-+    memset (obj, 0, sizeof (T));
-+
-+    return obj;
-+  }
-+
-+  void free (T* obj)
-+  {
-+    * (T**) obj = next;
-+    next = obj;
-+  }
-+
-+  private:
-+
-+  static_assert (ChunkLen > 1, "");
-+  static_assert (sizeof (T) >= sizeof (void *), "");
-+  static_assert (alignof (T) % sizeof (void *) == 0, "");
-+
-+  struct chunk_t
-+  {
-+    T* thread ()
-+    {
-+      for (unsigned i = 0; i < ARRAY_LENGTH (arrayZ) - 1; i++)
-+        * (T**) &arrayZ[i] = &arrayZ[i + 1];
-+
-+      * (T**) &arrayZ[ARRAY_LENGTH (arrayZ) - 1] = nullptr;
-+
-+      return arrayZ;
-+    }
-+
-+    T arrayZ[ChunkLen];
-+  };
-+
-+  T* next;
-+  hb_vector_t<chunk_t *> chunks;
-+};
-+
-+
-+#endif /* HB_POOL_HH */
-diff --git a/gfx/harfbuzz/src/hb-sanitize.hh b/gfx/harfbuzz/src/hb-sanitize.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-sanitize.hh
-@@ -0,0 +1,401 @@
-+/*
-+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
-+ * Copyright © 2012,2018  Google, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Red Hat Author(s): Behdad Esfahbod
-+ * Google Author(s): Behdad Esfahbod
-+ */
-+
-+#ifndef HB_SANITIZE_HH
-+#define HB_SANITIZE_HH
-+
-+#include "hb.hh"
-+#include "hb-blob.hh"
-+#include "hb-dispatch.hh"
-+
-+
-+/*
-+ * Sanitize
-+ *
-+ *
-+ * === Introduction ===
-+ *
-+ * The sanitize machinery is at the core of our zero-cost font loading.  We
-+ * mmap() font file into memory and create a blob out of it.  Font subtables
-+ * are returned as a readonly sub-blob of the main font blob.  These table
-+ * blobs are then sanitized before use, to ensure invalid memory access does
-+ * not happen.  The toplevel sanitize API use is like, eg. to load the 'head'
-+ * table:
-+ *
-+ *   hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<OT::head> (face);
-+ *
-+ * The blob then can be converted to a head table struct with:
-+ *
-+ *   const head *head_table = head_blob->as<head> ();
-+ *
-+ * What the reference_table does is, to call hb_face_reference_table() to load
-+ * the table blob, sanitize it and return either the sanitized blob, or empty
-+ * blob if sanitization failed.  The blob->as() function returns the null
-+ * object of its template type argument if the blob is empty.  Otherwise, it
-+ * just casts the blob contents to the desired type.
-+ *
-+ * Sanitizing a blob of data with a type T works as follows (with minor
-+ * simplification):
-+ *
-+ *   - Cast blob content to T*, call sanitize() method of it,
-+ *   - If sanitize succeeded, return blob.
-+ *   - Otherwise, if blob is not writable, try making it writable,
-+ *     or copy if cannot be made writable in-place,
-+ *   - Call sanitize() again.  Return blob if sanitize succeeded.
-+ *   - Return empty blob otherwise.
-+ *
-+ *
-+ * === The sanitize() contract ===
-+ *
-+ * The sanitize() method of each object type shall return true if it's safe to
-+ * call other methods of the object, and false otherwise.
-+ *
-+ * Note that what sanitize() checks for might align with what the specification
-+ * describes as valid table data, but does not have to be.  In particular, we
-+ * do NOT want to be pedantic and concern ourselves with validity checks that
-+ * are irrelevant to our use of the table.  On the contrary, we want to be
-+ * lenient with error handling and accept invalid data to the extent that it
-+ * does not impose extra burden on us.
-+ *
-+ * Based on the sanitize contract, one can see that what we check for depends
-+ * on how we use the data in other table methods.  Ie. if other table methods
-+ * assume that offsets do NOT point out of the table data block, then that's
-+ * something sanitize() must check for (GSUB/GPOS/GDEF/etc work this way).  On
-+ * the other hand, if other methods do such checks themselves, then sanitize()
-+ * does not have to bother with them (glyf/local work this way).  The choice
-+ * depends on the table structure and sanitize() performance.  For example, to
-+ * check glyf/loca offsets in sanitize() would cost O(num-glyphs).  We try hard
-+ * to avoid such costs during font loading.  By postponing such checks to the
-+ * actual glyph loading, we reduce the sanitize cost to O(1) and total runtime
-+ * cost to O(used-glyphs).  As such, this is preferred.
-+ *
-+ * The same argument can be made re GSUB/GPOS/GDEF, but there, the table
-+ * structure is so complicated that by checking all offsets at sanitize() time,
-+ * we make the code much simpler in other methods, as offsets and referenced
-+ * objects do not need to be validated at each use site.
-+ */
-+
-+/* This limits sanitizing time on really broken fonts. */
-+#ifndef HB_SANITIZE_MAX_EDITS
-+#define HB_SANITIZE_MAX_EDITS 32
-+#endif
-+#ifndef HB_SANITIZE_MAX_OPS_FACTOR
-+#define HB_SANITIZE_MAX_OPS_FACTOR 8
-+#endif
-+#ifndef HB_SANITIZE_MAX_OPS_MIN
-+#define HB_SANITIZE_MAX_OPS_MIN 16384
-+#endif
-+#ifndef HB_SANITIZE_MAX_OPS_MAX
-+#define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF
-+#endif
-+
-+struct hb_sanitize_context_t :
-+       hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
-+{
-+  hb_sanitize_context_t () :
-+	debug_depth (0),
-+	start (nullptr), end (nullptr),
-+	max_ops (0),
-+	writable (false), edit_count (0),
-+	blob (nullptr),
-+	num_glyphs (65536),
-+	num_glyphs_set (false) {}
-+
-+  const char *get_name () { return "SANITIZE"; }
-+  template <typename T, typename F>
-+  bool may_dispatch (const T *obj HB_UNUSED, const F *format)
-+  { return format->sanitize (this); }
-+  static return_t default_return_value () { return true; }
-+  static return_t no_dispatch_return_value () { return false; }
-+  bool stop_sublookup_iteration (const return_t r) const { return !r; }
-+
-+  private:
-+  template <typename T, typename ...Ts> auto
-+  _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
-+  ( obj.sanitize (this, hb_forward<Ts> (ds)...) )
-+  template <typename T, typename ...Ts> auto
-+  _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
-+  ( obj.dispatch (this, hb_forward<Ts> (ds)...) )
-+  public:
-+  template <typename T, typename ...Ts> auto
-+  dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
-+  ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
-+
-+
-+  void init (hb_blob_t *b)
-+  {
-+    this->blob = hb_blob_reference (b);
-+    this->writable = false;
-+  }
-+
-+  void set_num_glyphs (unsigned int num_glyphs_)
-+  {
-+    num_glyphs = num_glyphs_;
-+    num_glyphs_set = true;
-+  }
-+  unsigned int get_num_glyphs () { return num_glyphs; }
-+
-+  void set_max_ops (int max_ops_) { max_ops = max_ops_; }
-+
-+  template <typename T>
-+  void set_object (const T *obj)
-+  {
-+    reset_object ();
-+
-+    if (!obj) return;
-+
-+    const char *obj_start = (const char *) obj;
-+    if (unlikely (obj_start < this->start || this->end <= obj_start))
-+      this->start = this->end = nullptr;
-+    else
-+    {
-+      this->start = obj_start;
-+      this->end   = obj_start + hb_min (size_t (this->end - obj_start), obj->get_size ());
-+    }
-+  }
-+
-+  void reset_object ()
-+  {
-+    this->start = this->blob->data;
-+    this->end = this->start + this->blob->length;
-+    assert (this->start <= this->end); /* Must not overflow. */
-+  }
-+
-+  void start_processing ()
-+  {
-+    reset_object ();
-+    this->max_ops = hb_max ((unsigned int) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
-+			 (unsigned) HB_SANITIZE_MAX_OPS_MIN);
-+    this->edit_count = 0;
-+    this->debug_depth = 0;
-+
-+    DEBUG_MSG_LEVEL (SANITIZE, start, 0, +1,
-+		     "start [%p..%p] (%lu bytes)",
-+		     this->start, this->end,
-+		     (unsigned long) (this->end - this->start));
-+  }
-+
-+  void end_processing ()
-+  {
-+    DEBUG_MSG_LEVEL (SANITIZE, this->start, 0, -1,
-+		     "end [%p..%p] %u edit requests",
-+		     this->start, this->end, this->edit_count);
-+
-+    hb_blob_destroy (this->blob);
-+    this->blob = nullptr;
-+    this->start = this->end = nullptr;
-+  }
-+
-+  unsigned get_edit_count () { return edit_count; }
-+
-+  bool check_range (const void *base,
-+		    unsigned int len) const
-+  {
-+    const char *p = (const char *) base;
-+    bool ok = !len ||
-+	      (this->start <= p &&
-+	       p <= this->end &&
-+	       (unsigned int) (this->end - p) >= len &&
-+	       this->max_ops-- > 0);
-+
-+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-+		     "check_range [%p..%p]"
-+		     " (%d bytes) in [%p..%p] -> %s",
-+		     p, p + len, len,
-+		     this->start, this->end,
-+		     ok ? "OK" : "OUT-OF-RANGE");
-+
-+    return likely (ok);
-+  }
-+
-+  template <typename T>
-+  bool check_range (const T *base,
-+		    unsigned int a,
-+		    unsigned int b) const
-+  {
-+    return !hb_unsigned_mul_overflows (a, b) &&
-+	   this->check_range (base, a * b);
-+  }
-+
-+  template <typename T>
-+  bool check_range (const T *base,
-+		    unsigned int a,
-+		    unsigned int b,
-+		    unsigned int c) const
-+  {
-+    return !hb_unsigned_mul_overflows (a, b) &&
-+	   this->check_range (base, a * b, c);
-+  }
-+
-+  template <typename T>
-+  bool check_array (const T *base, unsigned int len) const
-+  {
-+    return this->check_range (base, len, hb_static_size (T));
-+  }
-+
-+  template <typename T>
-+  bool check_array (const T *base,
-+		    unsigned int a,
-+		    unsigned int b) const
-+  {
-+    return this->check_range (base, a, b, hb_static_size (T));
-+  }
-+
-+  template <typename Type>
-+  bool check_struct (const Type *obj) const
-+  { return likely (this->check_range (obj, obj->min_size)); }
-+
-+  bool may_edit (const void *base, unsigned int len)
-+  {
-+    if (this->edit_count >= HB_SANITIZE_MAX_EDITS)
-+      return false;
-+
-+    const char *p = (const char *) base;
-+    this->edit_count++;
-+
-+    DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0,
-+       "may_edit(%u) [%p..%p] (%d bytes) in [%p..%p] -> %s",
-+       this->edit_count,
-+       p, p + len, len,
-+       this->start, this->end,
-+       this->writable ? "GRANTED" : "DENIED");
-+
-+    return this->writable;
-+  }
-+
-+  template <typename Type, typename ValueType>
-+  bool try_set (const Type *obj, const ValueType &v)
-+  {
-+    if (this->may_edit (obj, hb_static_size (Type)))
-+    {
-+      * const_cast<Type *> (obj) = v;
-+      return true;
-+    }
-+    return false;
-+  }
-+
-+  template <typename Type>
-+  hb_blob_t *sanitize_blob (hb_blob_t *blob)
-+  {
-+    bool sane;
-+
-+    init (blob);
-+
-+  retry:
-+    DEBUG_MSG_FUNC (SANITIZE, start, "start");
-+
-+    start_processing ();
-+
-+    if (unlikely (!start))
-+    {
-+      end_processing ();
-+      return blob;
-+    }
-+
-+    Type *t = reinterpret_cast<Type *> (const_cast<char *> (start));
-+
-+    sane = t->sanitize (this);
-+    if (sane)
-+    {
-+      if (edit_count)
-+      {
-+	DEBUG_MSG_FUNC (SANITIZE, start, "passed first round with %d edits; going for second round", edit_count);
-+
-+        /* sanitize again to ensure no toe-stepping */
-+        edit_count = 0;
-+	sane = t->sanitize (this);
-+	if (edit_count) {
-+	  DEBUG_MSG_FUNC (SANITIZE, start, "requested %d edits in second round; FAILLING", edit_count);
-+	  sane = false;
-+	}
-+      }
-+    }
-+    else
-+    {
-+      if (edit_count && !writable) {
-+        start = hb_blob_get_data_writable (blob, nullptr);
-+	end = start + blob->length;
-+
-+	if (start)
-+	{
-+	  writable = true;
-+	  /* ok, we made it writable by relocating.  try again */
-+	  DEBUG_MSG_FUNC (SANITIZE, start, "retry");
-+	  goto retry;
-+	}
-+      }
-+    }
-+
-+    end_processing ();
-+
-+    DEBUG_MSG_FUNC (SANITIZE, start, sane ? "PASSED" : "FAILED");
-+    if (sane)
-+    {
-+      hb_blob_make_immutable (blob);
-+      return blob;
-+    }
-+    else
-+    {
-+      hb_blob_destroy (blob);
-+      return hb_blob_get_empty ();
-+    }
-+  }
-+
-+  template <typename Type>
-+  hb_blob_t *reference_table (const hb_face_t *face, hb_tag_t tableTag = Type::tableTag)
-+  {
-+    if (!num_glyphs_set)
-+      set_num_glyphs (hb_face_get_glyph_count (face));
-+    return sanitize_blob<Type> (hb_face_reference_table (face, tableTag));
-+  }
-+
-+  mutable unsigned int debug_depth;
-+  const char *start, *end;
-+  mutable int max_ops;
-+  private:
-+  bool writable;
-+  unsigned int edit_count;
-+  hb_blob_t *blob;
-+  unsigned int num_glyphs;
-+  bool  num_glyphs_set;
-+};
-+
-+struct hb_sanitize_with_object_t
-+{
-+  template <typename T>
-+  hb_sanitize_with_object_t (hb_sanitize_context_t *c, const T& obj) : c (c)
-+  { c->set_object (obj); }
-+  ~hb_sanitize_with_object_t ()
-+  { c->reset_object (); }
-+
-+  private:
-+  hb_sanitize_context_t *c;
-+};
-+
-+
-+#endif /* HB_SANITIZE_HH */
-diff --git a/gfx/harfbuzz/src/hb-serialize.hh b/gfx/harfbuzz/src/hb-serialize.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-serialize.hh
-@@ -0,0 +1,473 @@
-+/*
-+ * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
-+ * Copyright © 2012,2018  Google, Inc.
-+ * Copyright © 2019  Facebook, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Red Hat Author(s): Behdad Esfahbod
-+ * Google Author(s): Behdad Esfahbod
-+ * Facebook Author(s): Behdad Esfahbod
-+ */
-+
-+#ifndef HB_SERIALIZE_HH
-+#define HB_SERIALIZE_HH
-+
-+#include "hb.hh"
-+#include "hb-blob.hh"
-+#include "hb-map.hh"
-+#include "hb-pool.hh"
-+
-+
-+/*
-+ * Serialize
-+ */
-+
-+struct hb_serialize_context_t
-+{
-+  typedef unsigned objidx_t;
-+
-+  struct range_t
-+  {
-+    char *head, *tail;
-+  };
-+
-+  struct object_t : range_t
-+  {
-+    void fini () { links.fini (); }
-+
-+    bool operator == (const object_t &o) const
-+    {
-+      return (tail - head == o.tail - o.head)
-+	  && (links.length == o.links.length)
-+	  && 0 == hb_memcmp (head, o.head, tail - head)
-+	  && links.as_bytes () == o.links.as_bytes ();
-+    }
-+    uint32_t hash () const
-+    {
-+      return hb_bytes_t (head, tail - head).hash () ^
-+	     links.as_bytes ().hash ();
-+    }
-+
-+    struct link_t
-+    {
-+      bool is_wide: 1;
-+      unsigned position : 31;
-+      unsigned bias;
-+      objidx_t objidx;
-+    };
-+
-+    hb_vector_t<link_t> links;
-+    object_t *next;
-+  };
-+
-+  range_t snapshot () { range_t s = {head, tail} ; return s; }
-+
-+
-+  hb_serialize_context_t (void *start_, unsigned int size) :
-+    start ((char *) start_),
-+    end (start + size),
-+    current (nullptr)
-+  { reset (); }
-+  ~hb_serialize_context_t () { fini (); }
-+
-+  void fini ()
-+  {
-+    ++ hb_iter (packed)
-+    | hb_apply ([] (object_t *_) { _->fini (); })
-+    ;
-+    packed.fini ();
-+    this->packed_map.fini ();
-+
-+    while (current)
-+    {
-+      auto *_ = current;
-+      current = current->next;
-+      _->fini ();
-+    }
-+    object_pool.fini ();
-+  }
-+
-+  bool in_error () const { return !this->successful; }
-+
-+  void reset ()
-+  {
-+    this->successful = true;
-+    this->ran_out_of_room = false;
-+    this->head = this->start;
-+    this->tail = this->end;
-+    this->debug_depth = 0;
-+
-+    fini ();
-+    this->packed.push (nullptr);
-+  }
-+
-+  bool check_success (bool success)
-+  { return this->successful && (success || (err_other_error (), false)); }
-+
-+  template <typename T1, typename T2>
-+  bool check_equal (T1 &&v1, T2 &&v2)
-+  { return check_success (v1 == v2); }
-+
-+  template <typename T1, typename T2>
-+  bool check_assign (T1 &v1, T2 &&v2)
-+  { return check_equal (v1 = v2, v2); }
-+
-+  template <typename T> bool propagate_error (T &&obj)
-+  { return check_success (!hb_deref (obj).in_error ()); }
-+
-+  template <typename T1, typename... Ts> bool propagate_error (T1 &&o1, Ts&&... os)
-+  { return propagate_error (hb_forward<T1> (o1)) &&
-+	   propagate_error (hb_forward<Ts> (os)...); }
-+
-+  /* To be called around main operation. */
-+  template <typename Type>
-+  Type *start_serialize ()
-+  {
-+    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, +1,
-+		     "start [%p..%p] (%lu bytes)",
-+		     this->start, this->end,
-+		     (unsigned long) (this->end - this->start));
-+
-+    assert (!current);
-+    return push<Type> ();
-+  }
-+  void end_serialize ()
-+  {
-+    DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1,
-+		     "end [%p..%p] serialized %u bytes; %s",
-+		     this->start, this->end,
-+		     (unsigned) (this->head - this->start),
-+		     this->successful ? "successful" : "UNSUCCESSFUL");
-+
-+    propagate_error (packed, packed_map);
-+
-+    if (unlikely (!current)) return;
-+    assert (!current->next);
-+
-+    /* Only "pack" if there exist other objects... Otherwise, don't bother.
-+     * Saves a move. */
-+    if (packed.length <= 1)
-+      return;
-+
-+    pop_pack ();
-+
-+    resolve_links ();
-+  }
-+
-+  template <typename Type = void>
-+  Type *push ()
-+  {
-+    object_t *obj = object_pool.alloc ();
-+    if (unlikely (!obj))
-+      check_success (false);
-+    else
-+    {
-+      obj->head = head;
-+      obj->tail = tail;
-+      obj->next = current;
-+      current = obj;
-+    }
-+    return start_embed<Type> ();
-+  }
-+  void pop_discard ()
-+  {
-+    object_t *obj = current;
-+    if (unlikely (!obj)) return;
-+    current = current->next;
-+    revert (*obj);
-+    object_pool.free (obj);
-+  }
-+  objidx_t pop_pack ()
-+  {
-+    object_t *obj = current;
-+    if (unlikely (!obj)) return 0;
-+    current = current->next;
-+    obj->tail = head;
-+    obj->next = nullptr;
-+    unsigned len = obj->tail - obj->head;
-+    head = obj->head; /* Rewind head. */
-+
-+    if (!len)
-+    {
-+      assert (!obj->links.length);
-+      return 0;
-+    }
-+
-+    objidx_t objidx = packed_map.get (obj);
-+    if (objidx)
-+    {
-+      obj->fini ();
-+      return objidx;
-+    }
-+
-+    tail -= len;
-+    memmove (tail, obj->head, len);
-+
-+    obj->head = tail;
-+    obj->tail = tail + len;
-+
-+    packed.push (obj);
-+
-+    if (unlikely (packed.in_error ()))
-+      return 0;
-+
-+    objidx = packed.length - 1;
-+
-+    packed_map.set (obj, objidx);
-+
-+    return objidx;
-+  }
-+
-+  void revert (range_t snap)
-+  {
-+    assert (snap.head <= head);
-+    assert (tail <= snap.tail);
-+    head = snap.head;
-+    tail = snap.tail;
-+    discard_stale_objects ();
-+  }
-+
-+  void discard_stale_objects ()
-+  {
-+    while (packed.length > 1 &&
-+	   packed.tail ()->head < tail)
-+    {
-+      packed_map.del (packed.tail ());
-+      assert (!packed.tail ()->next);
-+      packed.tail ()->fini ();
-+      packed.pop ();
-+    }
-+    if (packed.length > 1)
-+      assert (packed.tail ()->head == tail);
-+  }
-+
-+  template <typename T>
-+  void add_link (T &ofs, objidx_t objidx, const void *base = nullptr)
-+  {
-+    static_assert (sizeof (T) == 2 || sizeof (T) == 4, "");
-+
-+    if (!objidx)
-+      return;
-+
-+    assert (current);
-+    assert (current->head <= (const char *) &ofs);
-+
-+    if (!base)
-+      base = current->head;
-+    else
-+      assert (current->head <= (const char *) base);
-+
-+    auto& link = *current->links.push ();
-+    link.is_wide = sizeof (T) == 4;
-+    link.position = (const char *) &ofs - current->head;
-+    link.bias = (const char *) base - current->head;
-+    link.objidx = objidx;
-+  }
-+
-+  void resolve_links ()
-+  {
-+    if (unlikely (in_error ())) return;
-+
-+    assert (!current);
-+    assert (packed.length > 1);
-+
-+    for (const object_t* parent : ++hb_iter (packed))
-+    {
-+      for (const object_t::link_t &link : parent->links)
-+      {
-+	const object_t* child = packed[link.objidx];
-+	assert (link.bias <= (size_t) (parent->tail - parent->head));
-+	unsigned offset = (child->head - parent->head) - link.bias;
-+
-+	if (link.is_wide)
-+	{
-+	  auto &off = * ((BEInt<uint32_t, 4> *) (parent->head + link.position));
-+	  assert (0 == off);
-+	  check_assign (off, offset);
-+	}
-+	else
-+	{
-+	  auto &off = * ((BEInt<uint16_t, 2> *) (parent->head + link.position));
-+	  assert (0 == off);
-+	  check_assign (off, offset);
-+	}
-+      }
-+    }
-+  }
-+
-+  unsigned int length () const { return this->head - current->head; }
-+
-+  void align (unsigned int alignment)
-+  {
-+    unsigned int l = length () % alignment;
-+    if (l)
-+      allocate_size<void> (alignment - l);
-+  }
-+
-+  template <typename Type = void>
-+  Type *start_embed (const Type *obj HB_UNUSED = nullptr) const
-+  { return reinterpret_cast<Type *> (this->head); }
-+  template <typename Type>
-+  Type *start_embed (const Type &obj) const
-+  { return start_embed (hb_addressof (obj)); }
-+
-+  /* Following two functions exist to allow setting breakpoint on. */
-+  void err_ran_out_of_room () { this->ran_out_of_room = true; }
-+  void err_other_error () { this->successful = false; }
-+
-+  template <typename Type>
-+  Type *allocate_size (unsigned int size)
-+  {
-+    if (unlikely (!this->successful)) return nullptr;
-+
-+    if (this->tail - this->head < ptrdiff_t (size))
-+    {
-+      err_ran_out_of_room ();
-+      this->successful = false;
-+      return nullptr;
-+    }
-+    memset (this->head, 0, size);
-+    char *ret = this->head;
-+    this->head += size;
-+    return reinterpret_cast<Type *> (ret);
-+  }
-+
-+  template <typename Type>
-+  Type *allocate_min ()
-+  {
-+    return this->allocate_size<Type> (Type::min_size);
-+  }
-+
-+  template <typename Type>
-+  Type *embed (const Type *obj)
-+  {
-+    unsigned int size = obj->get_size ();
-+    Type *ret = this->allocate_size<Type> (size);
-+    if (unlikely (!ret)) return nullptr;
-+    memcpy (ret, obj, size);
-+    return ret;
-+  }
-+  template <typename Type>
-+  Type *embed (const Type &obj)
-+  { return embed (hb_addressof (obj)); }
-+
-+  template <typename Type, typename ...Ts> auto
-+  _copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN
-+  (Type *, src.copy (this, hb_forward<Ts> (ds)...))
-+
-+  template <typename Type> auto
-+  _copy (const Type &src, hb_priority<0>) -> decltype (&(src = src))
-+  {
-+    Type *ret = this->allocate_size<Type> (sizeof (Type));
-+    if (unlikely (!ret)) return nullptr;
-+    *ret = src;
-+    return ret;
-+  }
-+
-+  /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
-+   * instead of memcpy(). */
-+  template <typename Type, typename ...Ts>
-+  Type *copy (const Type &src, Ts&&... ds)
-+  { return _copy (src, hb_prioritize, hb_forward<Ts> (ds)...); }
-+  template <typename Type, typename ...Ts>
-+  Type *copy (const Type *src, Ts&&... ds)
-+  { return copy (*src, hb_forward<Ts> (ds)...); }
-+
-+  template <typename Type>
-+  hb_serialize_context_t& operator << (const Type &obj) & { embed (obj); return *this; }
-+
-+  template <typename Type>
-+  Type *extend_size (Type *obj, unsigned int size)
-+  {
-+    assert (this->start <= (char *) obj);
-+    assert ((char *) obj <= this->head);
-+    assert ((char *) obj + size >= this->head);
-+    if (unlikely (!this->allocate_size<Type> (((char *) obj) + size - this->head))) return nullptr;
-+    return reinterpret_cast<Type *> (obj);
-+  }
-+  template <typename Type>
-+  Type *extend_size (Type &obj, unsigned int size)
-+  { return extend_size (hb_addressof (obj), size); }
-+
-+  template <typename Type>
-+  Type *extend_min (Type *obj) { return extend_size (obj, obj->min_size); }
-+  template <typename Type>
-+  Type *extend_min (Type &obj) { return extend_min (hb_addressof (obj)); }
-+
-+  template <typename Type, typename ...Ts>
-+  Type *extend (Type *obj, Ts&&... ds)
-+  { return extend_size (obj, obj->get_size (hb_forward<Ts> (ds)...)); }
-+  template <typename Type, typename ...Ts>
-+  Type *extend (Type &obj, Ts&&... ds)
-+  { return extend (hb_addressof (obj), hb_forward<Ts> (ds)...); }
-+
-+  /* Output routines. */
-+  hb_bytes_t copy_bytes () const
-+  {
-+    assert (this->successful);
-+    /* Copy both items from head side and tail side... */
-+    unsigned int len = (this->head - this->start)
-+		     + (this->end  - this->tail);
-+    char *p = (char *) malloc (len);
-+    if (p)
-+    {
-+      memcpy (p, this->start, this->head - this->start);
-+      memcpy (p + (this->head - this->start), this->tail, this->end - this->tail);
-+    }
-+    else
-+      return hb_bytes_t ();
-+    return hb_bytes_t (p, len);
-+  }
-+  template <typename Type>
-+  Type *copy () const
-+  { return reinterpret_cast<Type *> ((char *) copy_bytes ().arrayZ); }
-+  hb_blob_t *copy_blob () const
-+  {
-+    hb_bytes_t b = copy_bytes ();
-+    return hb_blob_create (b.arrayZ, b.length,
-+			   HB_MEMORY_MODE_WRITABLE,
-+			   (char *) b.arrayZ, free);
-+  }
-+
-+  public: /* TODO Make private. */
-+  char *start, *head, *tail, *end;
-+  unsigned int debug_depth;
-+  bool successful;
-+  bool ran_out_of_room;
-+
-+  private:
-+
-+  /* Object memory pool. */
-+  hb_pool_t<object_t> object_pool;
-+
-+  /* Stack of currently under construction objects. */
-+  object_t *current;
-+
-+  /* Stack of packed objects.  Object 0 is always nil object. */
-+  hb_vector_t<object_t *> packed;
-+
-+  /* Map view of packed objects. */
-+  hb_hashmap_t<const object_t *, objidx_t, nullptr, 0> packed_map;
-+};
-+
-+
-+#endif /* HB_SERIALIZE_HH */
-diff --git a/gfx/harfbuzz/src/hb-set.cc b/gfx/harfbuzz/src/hb-set.cc
---- a/gfx/harfbuzz/src/hb-set.cc
-+++ b/gfx/harfbuzz/src/hb-set.cc
-@@ -384,30 +384,32 @@ hb_set_subtract (hb_set_t       *set,
-  **/
- void
- hb_set_symmetric_difference (hb_set_t       *set,
- 			     const hb_set_t *other)
- {
-   set->symmetric_difference (other);
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_set_invert:
-  * @set: a set.
-  *
-  * 
-  *
-  * Since: 0.9.10
-  *
-  * Deprecated: 1.6.1
-  **/
- void
- hb_set_invert (hb_set_t *set HB_UNUSED)
- {
- }
-+#endif
- 
- /**
-  * hb_set_get_population:
-  * @set: a set.
-  *
-  * Returns the number of numbers in the set.
-  *
-  * Return value: set population.
-diff --git a/gfx/harfbuzz/src/hb-set.hh b/gfx/harfbuzz/src/hb-set.hh
---- a/gfx/harfbuzz/src/hb-set.hh
-+++ b/gfx/harfbuzz/src/hb-set.hh
-@@ -23,28 +23,29 @@
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #ifndef HB_SET_HH
- #define HB_SET_HH
- 
- #include "hb.hh"
-+#include "hb-machinery.hh"
- 
- 
- /*
-  * hb_set_t
-  */
- 
- /* TODO Keep a free-list so we can free pages that are completely zeroed.  At that
-  * point maybe also use a sentinel value for "all-1" pages? */
- 
- struct hb_set_t
- {
--  HB_NO_COPY_ASSIGN (hb_set_t);
-+  HB_DELETE_COPY_ASSIGN (hb_set_t);
-   hb_set_t ()  { init (); }
-   ~hb_set_t () { fini (); }
- 
-   struct page_map_t
-   {
-     int cmp (const page_map_t &o) const { return (int) o.major - (int) major; }
- 
-     uint32_t major;
-@@ -64,17 +65,17 @@ struct hb_set_t
-       for (unsigned int i = 0; i < len (); i++)
-         if (v[i])
- 	  return false;
-       return true;
-     }
- 
-     void add (hb_codepoint_t g) { elt (g) |= mask (g); }
-     void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
--    bool has (hb_codepoint_t g) const { return !!(elt (g) & mask (g)); }
-+    bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
- 
-     void add_range (hb_codepoint_t a, hb_codepoint_t b)
-     {
-       elt_t *la = &elt (a);
-       elt_t *lb = &elt (b);
-       if (la == lb)
-         *la |= (mask (b) << 1) - mask(a);
-       else
-@@ -181,17 +182,17 @@ struct hb_set_t
- 
-     vector_t v;
-   };
-   static_assert (page_t::PAGE_BITS == sizeof (page_t) * 8, "");
- 
-   hb_object_header_t header;
-   bool successful; /* Allocations successful */
-   mutable unsigned int population;
--  hb_vector_t<page_map_t> page_map;
-+  hb_sorted_vector_t<page_map_t> page_map;
-   hb_vector_t<page_t> pages;
- 
-   void init_shallow ()
-   {
-     successful = true;
-     population = 0;
-     page_map.init ();
-     pages.init ();
-@@ -222,21 +223,28 @@ struct hb_set_t
-     {
-       pages.resize (page_map.length);
-       successful = false;
-       return false;
-     }
-     return true;
-   }
- 
-+  void reset ()
-+  {
-+    if (unlikely (hb_object_is_immutable (this)))
-+      return;
-+    clear ();
-+    successful = true;
-+  }
-+
-   void clear ()
-   {
-     if (unlikely (hb_object_is_immutable (this)))
-       return;
--    successful = true;
-     population = 0;
-     page_map.resize (0);
-     pages.resize (0);
-   }
-   bool is_empty () const
-   {
-     unsigned int count = pages.length;
-     for (unsigned int i = 0; i < count; i++)
-@@ -296,17 +304,17 @@ struct hb_set_t
-       unsigned int m = get_major (g);
-       page_t *page = page_for_insert (g); if (unlikely (!page)) return;
-       unsigned int start = major_start (m);
-       unsigned int end = major_start (m + 1);
-       do
-       {
- 	page->add (g);
- 
--	array = (const T *) ((const char *) array + stride);
-+	array = &StructAtOffsetUnaligned<T> (array, stride);
- 	count--;
-       }
-       while (count && (g = *array, start <= g && g < end));
-     }
-   }
- 
-   /* Might return false if array looks unsorted.
-    * Used for faster rejection of corrupt data. */
-@@ -352,25 +360,36 @@ struct hb_set_t
-   void del_range (hb_codepoint_t a, hb_codepoint_t b)
-   {
-     /* TODO perform op even if !successful. */
-     /* TODO Optimize, like add_range(). */
-     if (unlikely (!successful)) return;
-     for (unsigned int i = a; i < b + 1; i++)
-       del (i);
-   }
--  bool has (hb_codepoint_t g) const
-+  bool get (hb_codepoint_t g) const
-   {
-     const page_t *page = page_for (g);
-     if (!page)
-       return false;
--    return page->has (g);
-+    return page->get (g);
-   }
--  bool intersects (hb_codepoint_t first,
--			  hb_codepoint_t last) const
-+
-+  /* Has interface. */
-+  static constexpr bool SENTINEL = false;
-+  typedef bool value_t;
-+  value_t operator [] (hb_codepoint_t k) const { return get (k); }
-+  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
-+  /* Predicate. */
-+  bool operator () (hb_codepoint_t k) const { return has (k); }
-+
-+  /* Sink interface. */
-+  hb_set_t& operator << (hb_codepoint_t v) { add (v); return *this; }
-+
-+  bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
-   {
-     hb_codepoint_t c = first - 1;
-     return next (&c) && c <= last;
-   }
-   void set (const hb_set_t *other)
-   {
-     if (unlikely (!successful)) return;
-     unsigned int count = other->pages.length;
-@@ -417,18 +436,18 @@ struct hb_set_t
-     hb_codepoint_t c = INVALID;
-     while (next (&c))
-       if (!larger_set->has (c))
-         return false;
- 
-     return true;
-   }
- 
--  template <class Op>
--  void process (const hb_set_t *other)
-+  template <typename Op>
-+  void process (const Op& op, const hb_set_t *other)
-   {
-     if (unlikely (!successful)) return;
- 
-     dirty ();
- 
-     unsigned int na = pages.length;
-     unsigned int nb = other->pages.length;
-     unsigned int next_page = na;
-@@ -472,17 +491,17 @@ struct hb_set_t
-     for (; a && b; )
-     {
-       if (page_map[a - 1].major == other->page_map[b - 1].major)
-       {
- 	a--;
- 	b--;
- 	count--;
- 	page_map[count] = page_map[a];
--	Op::process (page_at (count).v, page_at (a).v, other->page_at (b).v);
-+	page_at (count).v = op (page_at (a).v, other->page_at (b).v);
-       }
-       else if (page_map[a - 1].major > other->page_map[b - 1].major)
-       {
- 	a--;
- 	if (Op::passthru_left)
- 	{
- 	  count--;
- 	  page_map[count] = page_map[a];
-@@ -518,29 +537,29 @@ struct hb_set_t
-       }
-     assert (!count);
-     if (pages.length > newCount)
-       resize (newCount);
-   }
- 
-   void union_ (const hb_set_t *other)
-   {
--    process<HbOpOr> (other);
-+    process (hb_bitwise_or, other);
-   }
-   void intersect (const hb_set_t *other)
-   {
--    process<HbOpAnd> (other);
-+    process (hb_bitwise_and, other);
-   }
-   void subtract (const hb_set_t *other)
-   {
--    process<HbOpMinus> (other);
-+    process (hb_bitwise_sub, other);
-   }
-   void symmetric_difference (const hb_set_t *other)
-   {
--    process<HbOpXor> (other);
-+    process (hb_bitwise_xor, other);
-   }
-   bool next (hb_codepoint_t *codepoint) const
-   {
-     if (unlikely (*codepoint == INVALID)) {
-       *codepoint = get_min ();
-       return *codepoint != INVALID;
-     }
- 
-@@ -666,37 +685,39 @@ struct hb_set_t
-     return INVALID;
-   }
- 
-   static constexpr hb_codepoint_t INVALID = HB_SET_VALUE_INVALID;
- 
-   /*
-    * Iterator implementation.
-    */
--  struct const_iter_t : hb_sorted_iter_t<const_iter_t, const hb_codepoint_t>
-+  struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
-   {
--    const_iter_t (const hb_set_t &s_) :
--      s (s_), v (INVALID), l (s.get_population () + 1) { __next__ (); }
-+    static constexpr bool is_sorted_iterator = true;
-+    iter_t (const hb_set_t &s_ = Null(hb_set_t)) :
-+      s (&s_), v (INVALID), l (s->get_population () + 1) { __next__ (); }
- 
--    typedef hb_codepoint_t __item_type__;
-+    typedef hb_codepoint_t __item_t__;
-     hb_codepoint_t __item__ () const { return v; }
-     bool __more__ () const { return v != INVALID; }
--    void __next__ () { s.next (&v); if (l) l--; }
--    void __prev__ () { s.previous (&v); }
--    unsigned __len__ () { return l; }
-+    void __next__ () { s->next (&v); if (l) l--; }
-+    void __prev__ () { s->previous (&v); }
-+    unsigned __len__ () const { return l; }
-+    iter_t end () const { return iter_t (*s); }
-+    bool operator != (const iter_t& o) const
-+    { return s != o.s || v != o.v; }
- 
-     protected:
--    const hb_set_t &s;
-+    const hb_set_t *s;
-     hb_codepoint_t v;
-     unsigned l;
-   };
--  const_iter_t const_iter () const { return const_iter_t (*this); }
--  operator const_iter_t () const { return const_iter (); }
--  typedef const_iter_t iter_t;
--  iter_t iter () const { return const_iter (); }
-+  iter_t iter () const { return iter_t (*this); }
-+  operator iter_t () const { return iter (); }
- 
-   protected:
- 
-   page_t *page_for_insert (hb_codepoint_t g)
-   {
-     page_map_t map = {get_major (g), pages.length};
-     unsigned int i;
-     if (!page_map.bfind (map, &i, HB_BFIND_NOT_FOUND_STORE_CLOSEST))
-diff --git a/gfx/harfbuzz/src/hb-shaper-list.hh b/gfx/harfbuzz/src/hb-shaper-list.hh
---- a/gfx/harfbuzz/src/hb-shaper-list.hh
-+++ b/gfx/harfbuzz/src/hb-shaper-list.hh
-@@ -40,17 +40,13 @@ HB_SHAPER_IMPLEMENT (ot) /* <--- This is
- #ifdef HAVE_UNISCRIBE
- HB_SHAPER_IMPLEMENT (uniscribe)
- #endif
- #ifdef HAVE_DIRECTWRITE
- HB_SHAPER_IMPLEMENT (directwrite)
- #endif
- #ifdef HAVE_CORETEXT
- HB_SHAPER_IMPLEMENT (coretext)
--
--/* Only picks up fonts that have a "mort" or "morx" table.
--   Probably going to be removed https://github.com/harfbuzz/harfbuzz/issues/1478 */
--HB_SHAPER_IMPLEMENT (coretext_aat)
- #endif
- 
- #ifdef HAVE_FALLBACK
- HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
- #endif
-diff --git a/gfx/harfbuzz/src/hb-static.cc b/gfx/harfbuzz/src/hb-static.cc
---- a/gfx/harfbuzz/src/hb-static.cc
-+++ b/gfx/harfbuzz/src/hb-static.cc
-@@ -32,16 +32,17 @@
- #include "hb-aat-layout-common.hh"
- #include "hb-aat-layout-feat-table.hh"
- #include "hb-ot-layout-common.hh"
- #include "hb-ot-cmap-table.hh"
- #include "hb-ot-head-table.hh"
- #include "hb-ot-maxp-table.hh"
- 
- #ifndef HB_NO_VISIBILITY
-+#include "hb-ot-name-language-static.hh"
- 
- hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
- /*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
- 
- DEFINE_NULL_NAMESPACE_BYTES (OT, Index) =  {0xFF,0xFF};
- DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
- DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
- DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
-diff --git a/gfx/harfbuzz/src/hb-subset-cff-common.cc b/gfx/harfbuzz/src/hb-subset-cff-common.cc
---- a/gfx/harfbuzz/src/hb-subset-cff-common.cc
-+++ b/gfx/harfbuzz/src/hb-subset-cff-common.cc
-@@ -155,23 +155,23 @@ serialize_fdselect_3_4 (hb_serialize_con
- 			  const unsigned int num_glyphs,
- 			  const FDSelect &src,
- 			  unsigned int size,
- 			  const hb_vector_t<code_pair_t> &fdselect_ranges)
- {
-   TRACE_SERIALIZE (this);
-   FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
-   if (unlikely (p == nullptr)) return_trace (false);
--  p->nRanges ().set (fdselect_ranges.length);
-+  p->nRanges () = fdselect_ranges.length;
-   for (unsigned int i = 0; i < fdselect_ranges.length; i++)
-   {
--    p->ranges[i].first.set (fdselect_ranges[i].glyph);
--    p->ranges[i].fd.set (fdselect_ranges[i].code);
-+    p->ranges[i].first = fdselect_ranges[i].glyph;
-+    p->ranges[i].fd = fdselect_ranges[i].code;
-   }
--  p->sentinel().set (num_glyphs);
-+  p->sentinel() = num_glyphs;
-   return_trace (true);
- }
- 
- /**
-  * hb_serialize_cff_fdselect
-  * Serialize a subset FDSelect format planned above.
-  **/
- bool
-@@ -181,17 +181,17 @@ hb_serialize_cff_fdselect (hb_serialize_
- 			  unsigned int fd_count,
- 			  unsigned int fdselect_format,
- 			  unsigned int size,
- 			  const hb_vector_t<code_pair_t> &fdselect_ranges)
- {
-   TRACE_SERIALIZE (this);
-   FDSelect  *p = c->allocate_min<FDSelect> ();
-   if (unlikely (p == nullptr)) return_trace (false);
--  p->format.set (fdselect_format);
-+  p->format = fdselect_format;
-   size -= FDSelect::min_size;
- 
-   switch (fdselect_format)
-   {
- #if CFF_SERIALIZE_FDSELECT_0
-     case 0:
-     {
-       FDSelect0 *p = c->allocate_size<FDSelect0> (size);
-@@ -200,17 +200,17 @@ hb_serialize_cff_fdselect (hb_serialize_
-       unsigned int  fd = fdselect_ranges[range_index++].code;
-       for (unsigned int i = 0; i < num_glyphs; i++)
-       {
- 	if ((range_index < fdselect_ranges.len) &&
- 	    (i >= fdselect_ranges[range_index].glyph))
- 	{
- 	  fd = fdselect_ranges[range_index++].code;
- 	}
--	p->fds[i].set (fd);
-+	p->fds[i] = fd;
-       }
-       break;
-     }
- #endif /* CFF_SERIALIZE_FDSELECT_0 */
- 
-     case 3:
-       return serialize_fdselect_3_4<FDSelect3> (c,
- 						num_glyphs,
-diff --git a/gfx/harfbuzz/src/hb-subset-cff-common.hh b/gfx/harfbuzz/src/hb-subset-cff-common.hh
---- a/gfx/harfbuzz/src/hb-subset-cff-common.hh
-+++ b/gfx/harfbuzz/src/hb-subset-cff-common.hh
-@@ -204,17 +204,17 @@ struct cff_font_dict_op_serializer_t : o
-       /* serialize the private dict size & offset as 2-byte & 4-byte integers */
-       if (unlikely (!UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) ||
- 		    !UnsizedByteStr::serialize_int4 (c, privateDictInfo.offset)))
- 	return_trace (false);
- 
-       /* serialize the opcode */
-       HBUINT8 *p = c->allocate_size<HBUINT8> (1);
-       if (unlikely (p == nullptr)) return_trace (false);
--      p->set (OpCode_Private);
-+      *p = OpCode_Private;
- 
-       return_trace (true);
-     }
-     else
-     {
-       HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
-       if (unlikely (d == nullptr)) return_trace (false);
-       memcpy (d, &opstr.str[0], opstr.str.length);
-diff --git a/gfx/harfbuzz/src/hb-subset-cff1.cc b/gfx/harfbuzz/src/hb-subset-cff1.cc
---- a/gfx/harfbuzz/src/hb-subset-cff1.cc
-+++ b/gfx/harfbuzz/src/hb-subset-cff1.cc
-@@ -27,16 +27,18 @@
- #include "hb-open-type.hh"
- #include "hb-ot-cff1-table.hh"
- #include "hb-set.h"
- #include "hb-subset-cff1.hh"
- #include "hb-subset-plan.hh"
- #include "hb-subset-cff-common.hh"
- #include "hb-cff1-interp-cs.hh"
- 
-+#ifndef HB_NO_SUBSET_CFF
-+
- using namespace CFF;
- 
- struct remap_sid_t : remap_t
- {
-   unsigned int add (unsigned int sid)
-   {
-     if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
-       return offset_sid (remap_t::add (unoffset_sid (sid)));
-@@ -142,17 +144,17 @@ struct cff1_top_dict_op_serializer_t : c
-       case OpCode_Private:
- 	{
- 	  if (unlikely (!UnsizedByteStr::serialize_int2 (c, mod.offsets.privateDictInfo.size)))
- 	    return_trace (false);
- 	  if (unlikely (!UnsizedByteStr::serialize_int4 (c, mod.offsets.privateDictInfo.offset)))
- 	    return_trace (false);
- 	  HBUINT8 *p = c->allocate_size<HBUINT8> (1);
- 	  if (unlikely (p == nullptr)) return_trace (false);
--	  p->set (OpCode_Private);
-+	  *p = OpCode_Private;
- 	}
- 	break;
- 
-       case OpCode_version:
-       case OpCode_Notice:
-       case OpCode_Copyright:
-       case OpCode_FullName:
-       case OpCode_FamilyName:
-@@ -346,17 +348,17 @@ struct cff1_cs_opset_subr_subset_t : cff
- {
-   static void process_op (op_code_t op, cff1_cs_interp_env_t &env, subr_subset_param_t& param)
-   {
-     switch (op) {
- 
-       case OpCode_return:
- 	param.current_parsed_str->add_op (op, env.str_ref);
- 	param.current_parsed_str->set_parsed ();
--	env.returnFromSubr ();
-+	env.return_from_subr ();
- 	param.set_current_str (env, false);
- 	break;
- 
-       case OpCode_endchar:
- 	param.current_parsed_str->add_op (op, env.str_ref);
- 	param.current_parsed_str->set_parsed ();
- 	SUPER::process_op (op, env, param);
- 	break;
-@@ -377,30 +379,30 @@ struct cff1_cs_opset_subr_subset_t : cff
-   }
- 
-   protected:
-   static void process_call_subr (op_code_t op, cs_type_t type,
- 				 cff1_cs_interp_env_t &env, subr_subset_param_t& param,
- 				 cff1_biased_subrs_t& subrs, hb_set_t *closure)
-   {
-     byte_str_ref_t    str_ref = env.str_ref;
--    env.callSubr (subrs, type);
-+    env.call_subr (subrs, type);
-     param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
-     hb_set_add (closure, env.context.subr_num);
-     param.set_current_str (env, true);
-   }
- 
-   private:
-   typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
- };
- 
- struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t, OpCode_endchar>
- {
--  cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc, const hb_subset_plan_t *plan)
--    : subr_subsetter_t (acc, plan) {}
-+  cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
-+    : subr_subsetter_t (acc_, plan_) {}
- 
-   static void finalize_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
-   {
-     /* insert width at the beginning of the charstring as necessary */
-     if (env.has_width)
-       charstring.set_prefix (env.width);
- 
-     /* subroutines/charstring left on the call stack are legally left unmarked
-@@ -887,37 +889,37 @@ static inline bool _write_cff1 (const cf
- {
-   hb_serialize_context_t c (dest, dest_sz);
- 
-   OT::cff1 *cff = c.start_serialize<OT::cff1> ();
-   if (unlikely (!c.extend_min (*cff)))
-     return false;
- 
-   /* header */
--  cff->version.major.set (0x01);
--  cff->version.minor.set (0x00);
--  cff->nameIndex.set (cff->min_size);
--  cff->offSize.set (4); /* unused? */
-+  cff->version.major = 0x01;
-+  cff->version.minor = 0x00;
-+  cff->nameIndex = cff->min_size;
-+  cff->offSize = 4; /* unused? */
- 
-   /* name INDEX */
-   {
-     assert (cff->nameIndex == (unsigned) (c.head - c.start));
-     CFF1NameIndex *dest = c.start_embed<CFF1NameIndex> ();
-     if (unlikely (dest == nullptr)) return false;
-     if (unlikely (!dest->serialize (&c, *acc.nameIndex)))
-     {
-       DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF name INDEX");
-       return false;
-     }
-   }
- 
-   /* top dict INDEX */
-   {
-     assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start));
--    CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict> > ();
-+    CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict>> ();
-     if (dest == nullptr) return false;
-     cff1_top_dict_op_serializer_t topSzr;
-     top_dict_modifiers_t  modifier (plan.offsets, plan.topDictModSIDs);
-     if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize,
- 				    &plan.topdict_mod, 1,
- 				    plan.topdict_sizes, topSzr, modifier)))
-     {
-       DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
-@@ -1059,17 +1061,17 @@ static inline bool _write_cff1 (const cf
-   }
- 
-   assert (c.head == c.end);
-   c.end_serialize ();
- 
-   return true;
- }
- 
--static bool
-+static inline bool
- _hb_subset_cff1 (const OT::cff1::accelerator_subset_t  &acc,
- 		const char		*data,
- 		hb_subset_plan_t	*plan,
- 		hb_blob_t		**prime /* OUT */)
- {
-   cff_subset_plan cff_plan;
- 
-   if (unlikely (!cff_plan.create (acc, plan)))
-@@ -1113,8 +1115,10 @@ hb_subset_cff1 (hb_subset_plan_t *plan,
-   acc.init(plan->source);
-   bool result = likely (acc.is_valid ()) &&
- 			_hb_subset_cff1 (acc, data, plan, prime);
-   hb_blob_destroy (cff_blob);
-   acc.fini ();
- 
-   return result;
- }
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-subset-cff2.cc b/gfx/harfbuzz/src/hb-subset-cff2.cc
---- a/gfx/harfbuzz/src/hb-subset-cff2.cc
-+++ b/gfx/harfbuzz/src/hb-subset-cff2.cc
-@@ -27,16 +27,18 @@
- #include "hb-open-type.hh"
- #include "hb-ot-cff2-table.hh"
- #include "hb-set.h"
- #include "hb-subset-cff2.hh"
- #include "hb-subset-plan.hh"
- #include "hb-subset-cff-common.hh"
- #include "hb-cff2-interp-cs.hh"
- 
-+#ifndef HB_NO_SUBSET_CFF
-+
- using namespace CFF;
- 
- struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t
- {
-   cff2_sub_table_offsets_t ()
-     : cff_sub_table_offsets_t (),
-       varStoreOffset (0)
-   {}
-@@ -178,17 +180,17 @@ struct cff2_cs_opset_flatten_t : cff2_cs
- struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t>
- {
-   static void process_op (op_code_t op, cff2_cs_interp_env_t &env, subr_subset_param_t& param)
-   {
-     switch (op) {
- 
-       case OpCode_return:
- 	param.current_parsed_str->set_parsed ();
--	env.returnFromSubr ();
-+	env.return_from_subr ();
- 	param.set_current_str (env, false);
- 	break;
- 
-       case OpCode_endchar:
- 	param.current_parsed_str->set_parsed ();
- 	SUPER::process_op (op, env, param);
- 	break;
- 
-@@ -208,30 +210,30 @@ struct cff2_cs_opset_subr_subset_t : cff
-   }
- 
-   protected:
-   static void process_call_subr (op_code_t op, cs_type_t type,
- 				 cff2_cs_interp_env_t &env, subr_subset_param_t& param,
- 				 cff2_biased_subrs_t& subrs, hb_set_t *closure)
-   {
-     byte_str_ref_t    str_ref = env.str_ref;
--    env.callSubr (subrs, type);
-+    env.call_subr (subrs, type);
-     param.current_parsed_str->add_call_op (op, str_ref, env.context.subr_num);
-     hb_set_add (closure, env.context.subr_num);
-     param.set_current_str (env, true);
-   }
- 
-   private:
-   typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
- };
- 
- struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_subr_subset_t>
- {
--  cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc, const hb_subset_plan_t *plan)
--    : subr_subsetter_t (acc, plan) {}
-+  cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
-+    : subr_subsetter_t (acc_, plan_) {}
- 
-   static void finalize_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
-   {
-     /* vsindex is inserted at the beginning of the charstring as necessary */
-     if (env.seen_vsindex ())
-     {
-       number_t  ivs;
-       ivs.set_int ((int)env.get_ivs ());
-@@ -446,24 +448,24 @@ static inline bool _write_cff2 (const cf
- {
-   hb_serialize_context_t c (dest, dest_sz);
- 
-   OT::cff2 *cff2 = c.start_serialize<OT::cff2> ();
-   if (unlikely (!c.extend_min (*cff2)))
-     return false;
- 
-   /* header */
--  cff2->version.major.set (0x02);
--  cff2->version.minor.set (0x00);
--  cff2->topDict.set (OT::cff2::static_size);
-+  cff2->version.major = 0x02;
-+  cff2->version.minor = 0x00;
-+  cff2->topDict = OT::cff2::static_size;
- 
-   /* top dict */
-   {
-     assert (cff2->topDict == (unsigned) (c.head - c.start));
--    cff2->topDictSize.set (plan.offsets.topDictInfo.size);
-+    cff2->topDictSize = plan.offsets.topDictInfo.size;
-     TopDict &dict = cff2 + cff2->topDict;
-     cff2_top_dict_op_serializer_t topSzr;
-     if (unlikely (!dict.serialize (&c, acc.topDict, topSzr, plan.offsets)))
-     {
-       DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 top dict");
-       return false;
-     }
-   }
-@@ -566,17 +568,17 @@ static inline bool _write_cff2 (const cf
-   }
- 
-   assert (c.head == c.end);
-   c.end_serialize ();
- 
-   return true;
- }
- 
--static bool
-+static inline bool
- _hb_subset_cff2 (const OT::cff2::accelerator_subset_t  &acc,
- 		const char		      *data,
- 		hb_subset_plan_t		*plan,
- 		hb_blob_t		       **prime /* OUT */)
- {
-   cff2_subset_plan cff2_plan;
- 
-   if (unlikely (!cff2_plan.create (acc, plan)))
-@@ -621,8 +623,10 @@ hb_subset_cff2 (hb_subset_plan_t *plan,
-   bool result = likely (acc.is_valid ()) &&
- 		_hb_subset_cff2 (acc, data, plan, prime);
- 
-   hb_blob_destroy (cff2_blob);
-   acc.fini ();
- 
-   return result;
- }
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-subset-glyf.cc b/gfx/harfbuzz/src/hb-subset-glyf.cc
-deleted file mode 100644
---- a/gfx/harfbuzz/src/hb-subset-glyf.cc
-+++ /dev/null
-@@ -1,346 +0,0 @@
--/*
-- * Copyright © 2018  Google, Inc.
-- *
-- *  This is part of HarfBuzz, a text shaping library.
-- *
-- * Permission is hereby granted, without written agreement and without
-- * license or royalty fees, to use, copy, modify, and distribute this
-- * software and its documentation for any purpose, provided that the
-- * above copyright notice and the following two paragraphs appear in
-- * all copies of this software.
-- *
-- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-- * DAMAGE.
-- *
-- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-- *
-- * Google Author(s): Garret Rieger, Roderick Sheeter
-- */
--
--#include "hb-open-type.hh"
--#include "hb-ot-glyf-table.hh"
--#include "hb-set.h"
--#include "hb-subset-glyf.hh"
--
--struct loca_data_t
--{
--  bool          is_short;
--  void         *data;
--  unsigned int  size;
--
--  inline bool
--  _write_loca_entry (unsigned int  id,
--                     unsigned int  offset)
--  {
--    unsigned int entry_size = is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32);
--    if ((id + 1) * entry_size <= size)
--    {
--      if (is_short) {
--        ((OT::HBUINT16*) data) [id].set (offset / 2);
--      } else {
--        ((OT::HBUINT32*) data) [id].set (offset);
--      }
--      return true;
--    }
--
--    // Offset was not written because the write is out of bounds.
--    DEBUG_MSG(SUBSET,
--              nullptr,
--              "WARNING: Attempted to write an out of bounds loca entry at index %d. Loca size is %d.",
--              id,
--              size);
--    return false;
--  }
--};
--
--/**
-- * If hints are being dropped find the range which in glyf at which
-- * the hinting instructions are located. Add them to the instruction_ranges
-- * vector.
-- */
--static bool
--_add_instructions_range (const OT::glyf::accelerator_t &glyf,
--                         hb_codepoint_t                 glyph_id,
--                         unsigned int                   glyph_start_offset,
--                         unsigned int                   glyph_end_offset,
--                         bool                           drop_hints,
--                         hb_vector_t<unsigned int>     *instruction_ranges /* OUT */)
--{
--  if (!instruction_ranges->resize (instruction_ranges->length + 2))
--  {
--    DEBUG_MSG(SUBSET, nullptr, "Failed to resize instruction_ranges.");
--    return false;
--  }
--  unsigned int *instruction_start = &(*instruction_ranges)[instruction_ranges->length - 2];
--  *instruction_start = 0;
--  unsigned int *instruction_end = &(*instruction_ranges)[instruction_ranges->length - 1];
--  *instruction_end = 0;
--
--  if (drop_hints)
--  {
--    if (unlikely (!glyf.get_instruction_offsets (glyph_start_offset, glyph_end_offset,
--                                                 instruction_start, instruction_end)))
--    {
--      DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", glyph_id);
--      return false;
--    }
--  }
--
--  return true;
--}
--
--static bool
--_calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
--                                     const hb_subset_plan_t        *plan,
--                                     loca_data_t                   *loca_data, /* OUT */
--				     unsigned int                  *glyf_size /* OUT */,
--				     hb_vector_t<unsigned int>     *instruction_ranges /* OUT */)
--{
--  unsigned int total = 0;
--
--  hb_codepoint_t next_glyph = HB_SET_VALUE_INVALID;
--  while (plan->glyphset ()->next (&next_glyph))
--  {
--    unsigned int start_offset, end_offset;
--    if (unlikely (!(glyf.get_offsets (next_glyph, &start_offset, &end_offset) &&
--		    glyf.remove_padding (start_offset, &end_offset))))
--    {
--      DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
--      start_offset = end_offset = 0;
--    }
--
--    bool is_zero_length = end_offset - start_offset < OT::glyf::GlyphHeader::static_size;
--    if (!_add_instructions_range (glyf,
--                                  next_glyph,
--                                  start_offset,
--                                  end_offset,
--                                  plan->drop_hints && !is_zero_length,
--                                  instruction_ranges))
--      return false;
--
--    if (is_zero_length)
--      continue; /* 0-length glyph */
--
--    total += end_offset - start_offset
--             - ((*instruction_ranges)[instruction_ranges->length - 1]
--                - (*instruction_ranges)[instruction_ranges->length - 2]);
--    /* round2 so short loca will work */
--    total += total % 2;
--  }
--
--  *glyf_size = total;
--  loca_data->is_short = (total <= 131070);
--  loca_data->size = (plan->num_output_glyphs () + 1)
--      * (loca_data->is_short ? sizeof (OT::HBUINT16) : sizeof (OT::HBUINT32));
--
--  DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
--	    total,
--	    loca_data->size,
--	    loca_data->is_short ? "short" : "long");
--  return true;
--}
--
--static void
--_update_components (const hb_subset_plan_t *plan,
--		    char                   *glyph_start,
--		    unsigned int            length)
--{
--  OT::glyf::CompositeGlyphHeader::Iterator iterator;
--  if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start,
--						    length,
--						    &iterator))
--  {
--    do
--    {
--      hb_codepoint_t new_gid;
--      if (!plan->new_gid_for_old_gid (iterator.current->glyphIndex,
--				      &new_gid))
--	continue;
--
--      ((OT::glyf::CompositeGlyphHeader *) iterator.current)->glyphIndex.set (new_gid);
--    } while (iterator.move_to_next ());
--  }
--}
--
--static bool _remove_composite_instruction_flag (char *glyf_prime, unsigned int length)
--{
--  /* remove WE_HAVE_INSTRUCTIONS from flags in dest */
--  OT::glyf::CompositeGlyphHeader::Iterator composite_it;
--  if (unlikely (!OT::glyf::CompositeGlyphHeader::get_iterator (glyf_prime, length, &composite_it))) return false;
--  const OT::glyf::CompositeGlyphHeader *glyph;
--  do {
--    glyph = composite_it.current;
--    OT::HBUINT16 *flags = const_cast<OT::HBUINT16 *> (&glyph->flags);
--    flags->set ( (uint16_t) *flags & ~OT::glyf::CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS);
--  } while (composite_it.move_to_next ());
--  return true;
--}
--
--static bool
--_write_glyf_and_loca_prime (const hb_subset_plan_t        *plan,
--			    const OT::glyf::accelerator_t &glyf,
--			    const char                    *glyf_data,
--			    hb_vector_t<unsigned int>     &instruction_ranges,
--			    unsigned int                   glyf_prime_size,
--			    char                          *glyf_prime_data /* OUT */,
--			    loca_data_t                   *loca_prime /* OUT */)
--{
--  char *glyf_prime_data_next = glyf_prime_data;
--
--  bool success = true;
--
--
--  unsigned int i = 0;
--  hb_codepoint_t new_gid;
--  for (new_gid = 0; new_gid < plan->num_output_glyphs (); new_gid++)
--  {
--    hb_codepoint_t old_gid;
--    if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
--    {
--      // Empty glyph, add a loca entry and carry on.
--      loca_prime->_write_loca_entry (new_gid,
--                                     glyf_prime_data_next - glyf_prime_data);
--      continue;
--    }
--
--
--    unsigned int start_offset, end_offset;
--    if (unlikely (!(glyf.get_offsets (old_gid, &start_offset, &end_offset) &&
--		    glyf.remove_padding (start_offset, &end_offset))))
--      end_offset = start_offset = 0;
--
--    unsigned int instruction_start = instruction_ranges[i * 2];
--    unsigned int instruction_end = instruction_ranges[i * 2 + 1];
--
--    int length = end_offset - start_offset - (instruction_end - instruction_start);
--
--    if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
--    {
--      DEBUG_MSG(SUBSET,
--                nullptr,
--                "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
--                i, length);
--      return false;
--    }
--
--    if (instruction_start == instruction_end)
--      memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
--    else
--    {
--      memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset);
--      memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end);
--      /* if the instructions end at the end this was a composite glyph, else simple */
--      if (instruction_end == end_offset)
--      {
--	if (unlikely (!_remove_composite_instruction_flag (glyf_prime_data_next, length))) return false;
--      }
--      else
--	/* zero instruction length, which is just before instruction_start */
--	memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
--    }
--
--    success = success && loca_prime->_write_loca_entry (new_gid,
--                                                        glyf_prime_data_next - glyf_prime_data);
--    _update_components (plan, glyf_prime_data_next, length);
--
--    // TODO: don't align to two bytes if using long loca.
--    glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca.
--
--    i++;
--  }
--
--  // loca table has n+1 entries where the last entry signifies the end location of the last
--  // glyph.
--  success = success && loca_prime->_write_loca_entry (new_gid,
--                                                      glyf_prime_data_next - glyf_prime_data);
--  return success;
--}
--
--static bool
--_hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
--			  const char                     *glyf_data,
--			  hb_subset_plan_t               *plan,
--			  bool                           *use_short_loca,
--			  hb_blob_t                     **glyf_prime_blob /* OUT */,
--			  hb_blob_t                     **loca_prime_blob /* OUT */)
--{
--  // TODO(grieger): Sanity check allocation size for the new table.
--  loca_data_t loca_prime;
--  unsigned int glyf_prime_size;
--  hb_vector_t<unsigned int> instruction_ranges;
--  instruction_ranges.init ();
--
--  if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
--                                                      plan,
--                                                      &loca_prime,
--						      &glyf_prime_size,
--						      &instruction_ranges))) {
--    instruction_ranges.fini ();
--    return false;
--  }
--  *use_short_loca = loca_prime.is_short;
--
--  char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
--  loca_prime.data = (void *) calloc (1, loca_prime.size);
--  if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
--					     instruction_ranges,
--					     glyf_prime_size, glyf_prime_data,
--					     &loca_prime))) {
--    free (glyf_prime_data);
--    free (loca_prime.data);
--    instruction_ranges.fini ();
--    return false;
--  }
--  instruction_ranges.fini ();
--
--  *glyf_prime_blob = hb_blob_create (glyf_prime_data,
--                                     glyf_prime_size,
--                                     HB_MEMORY_MODE_READONLY,
--                                     glyf_prime_data,
--                                     free);
--  *loca_prime_blob = hb_blob_create ((char *) loca_prime.data,
--                                     loca_prime.size,
--                                     HB_MEMORY_MODE_READONLY,
--                                     loca_prime.data,
--                                     free);
--  return true;
--}
--
--/**
-- * hb_subset_glyf:
-- * Subsets the glyph table according to a provided plan.
-- *
-- * Return value: subsetted glyf table.
-- *
-- * Since: 1.7.5
-- **/
--bool
--hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
--			 bool             *use_short_loca, /* OUT */
--			 hb_blob_t       **glyf_prime, /* OUT */
--			 hb_blob_t       **loca_prime /* OUT */)
--{
--  hb_blob_t *glyf_blob = hb_sanitize_context_t ().reference_table<OT::glyf> (plan->source);
--  const char *glyf_data = hb_blob_get_data (glyf_blob, nullptr);
--
--  OT::glyf::accelerator_t glyf;
--  glyf.init (plan->source);
--  bool result = _hb_subset_glyf_and_loca (glyf,
--					  glyf_data,
--					  plan,
--					  use_short_loca,
--					  glyf_prime,
--					  loca_prime);
--
--  hb_blob_destroy (glyf_blob);
--  glyf.fini ();
--
--  return result;
--}
-diff --git a/gfx/harfbuzz/src/hb-subset-glyf.hh b/gfx/harfbuzz/src/hb-subset-glyf.hh
-deleted file mode 100644
---- a/gfx/harfbuzz/src/hb-subset-glyf.hh
-+++ /dev/null
-@@ -1,40 +0,0 @@
--/*
-- * Copyright © 2018  Google, Inc.
-- *
-- *  This is part of HarfBuzz, a text shaping library.
-- *
-- * Permission is hereby granted, without written agreement and without
-- * license or royalty fees, to use, copy, modify, and distribute this
-- * software and its documentation for any purpose, provided that the
-- * above copyright notice and the following two paragraphs appear in
-- * all copies of this software.
-- *
-- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-- * DAMAGE.
-- *
-- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-- * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-- *
-- * Google Author(s): Garret Rieger
-- */
--
--#ifndef HB_SUBSET_GLYF_HH
--#define HB_SUBSET_GLYF_HH
--
--#include "hb.hh"
--
--#include "hb-subset.hh"
--
--HB_INTERNAL bool
--hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
--			 bool             *use_short_loca, /* OUT */
--			 hb_blob_t       **glyf_prime      /* OUT */,
--			 hb_blob_t       **loca_prime      /* OUT */);
--
--#endif /* HB_SUBSET_GLYF_HH */
-diff --git a/gfx/harfbuzz/src/hb-subset-input.cc b/gfx/harfbuzz/src/hb-subset-input.cc
---- a/gfx/harfbuzz/src/hb-subset-input.cc
-+++ b/gfx/harfbuzz/src/hb-subset-input.cc
-@@ -39,21 +39,55 @@ hb_subset_input_create_or_fail ()
- {
-   hb_subset_input_t *input = hb_object_create<hb_subset_input_t>();
- 
-   if (unlikely (!input))
-     return nullptr;
- 
-   input->unicodes = hb_set_create ();
-   input->glyphs = hb_set_create ();
-+  input->name_ids = hb_set_create ();
-+  hb_set_add_range (input->name_ids, 0, 6);
-+  input->drop_tables = hb_set_create ();
-   input->drop_hints = false;
--  input->drop_layout = true;
-   input->desubroutinize = false;
-   input->retain_gids = false;
- 
-+  hb_tag_t default_drop_tables[] = {
-+    // Layout disabled by default
-+    HB_TAG ('G', 'S', 'U', 'B'),
-+    HB_TAG ('G', 'P', 'O', 'S'),
-+    HB_TAG ('G', 'D', 'E', 'F'),
-+    HB_TAG ('m', 'o', 'r', 'x'),
-+    HB_TAG ('m', 'o', 'r', 't'),
-+    HB_TAG ('k', 'e', 'r', 'x'),
-+    HB_TAG ('k', 'e', 'r', 'n'),
-+
-+    // Copied from fontTools:
-+    HB_TAG ('B', 'A', 'S', 'E'),
-+    HB_TAG ('J', 'S', 'T', 'F'),
-+    HB_TAG ('D', 'S', 'I', 'G'),
-+    HB_TAG ('E', 'B', 'D', 'T'),
-+    HB_TAG ('E', 'B', 'L', 'C'),
-+    HB_TAG ('E', 'B', 'S', 'C'),
-+    HB_TAG ('S', 'V', 'G', ' '),
-+    HB_TAG ('P', 'C', 'L', 'T'),
-+    HB_TAG ('L', 'T', 'S', 'H'),
-+    // Graphite tables
-+    HB_TAG ('F', 'e', 'a', 't'),
-+    HB_TAG ('G', 'l', 'a', 't'),
-+    HB_TAG ('G', 'l', 'o', 'c'),
-+    HB_TAG ('S', 'i', 'l', 'f'),
-+    HB_TAG ('S', 'i', 'l', 'l'),
-+    // Colour
-+    HB_TAG ('s', 'b', 'i', 'x')
-+  };
-+
-+  input->drop_tables->add_array (default_drop_tables, ARRAY_LENGTH (default_drop_tables));
-+
-   return input;
- }
- 
- /**
-  * hb_subset_input_reference: (skip)
-  * @subset_input: a subset_input.
-  *
-  *
-@@ -76,16 +110,18 @@ hb_subset_input_reference (hb_subset_inp
-  **/
- void
- hb_subset_input_destroy (hb_subset_input_t *subset_input)
- {
-   if (!hb_object_destroy (subset_input)) return;
- 
-   hb_set_destroy (subset_input->unicodes);
-   hb_set_destroy (subset_input->glyphs);
-+  hb_set_destroy (subset_input->name_ids);
-+  hb_set_destroy (subset_input->drop_tables);
- 
-   free (subset_input);
- }
- 
- /**
-  * hb_subset_input_unicode_set:
-  * @subset_input: a subset_input.
-  *
-@@ -104,70 +140,69 @@ hb_subset_input_unicode_set (hb_subset_i
-  * Since: 1.8.0
-  **/
- HB_EXTERN hb_set_t *
- hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
- {
-   return subset_input->glyphs;
- }
- 
-+HB_EXTERN hb_set_t *
-+hb_subset_input_nameid_set (hb_subset_input_t *subset_input)
-+{
-+  return subset_input->name_ids;
-+}
-+
-+HB_EXTERN hb_set_t *
-+hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input)
-+{
-+  return subset_input->drop_tables;
-+}
-+
- HB_EXTERN void
- hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
- 				hb_bool_t drop_hints)
- {
-   subset_input->drop_hints = drop_hints;
- }
- 
- HB_EXTERN hb_bool_t
- hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input)
- {
-   return subset_input->drop_hints;
- }
- 
- HB_EXTERN void
--hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
--				 hb_bool_t drop_layout)
--{
--  subset_input->drop_layout = drop_layout;
--}
--
--HB_EXTERN hb_bool_t
--hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input)
--{
--  return subset_input->drop_layout;
--}
--
--HB_EXTERN void
- hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
-         hb_bool_t desubroutinize)
- {
-   subset_input->desubroutinize = desubroutinize;
- }
- 
- HB_EXTERN hb_bool_t
- hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input)
- {
-   return subset_input->desubroutinize;
- }
- 
- /**
-  * hb_subset_input_set_retain_gids:
-  * @subset_input: a subset_input.
-  * @retain_gids: If true the subsetter will not renumber glyph ids.
-- * Since: REPLACEME
-+ * Since: 2.4.0
-  **/
- HB_EXTERN void
- hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
- 				 hb_bool_t retain_gids)
- {
-   subset_input->retain_gids = retain_gids;
- }
- 
- /**
-  * hb_subset_input_get_retain_gids:
-  * Returns: value of retain_gids.
-- * Since: REPLACEME
-+ * Since: 2.4.0
-  **/
- HB_EXTERN hb_bool_t
- hb_subset_input_get_retain_gids (hb_subset_input_t *subset_input)
- {
-   return subset_input->retain_gids;
- }
-diff --git a/gfx/harfbuzz/src/hb-subset-input.hh b/gfx/harfbuzz/src/hb-subset-input.hh
---- a/gfx/harfbuzz/src/hb-subset-input.hh
-+++ b/gfx/harfbuzz/src/hb-subset-input.hh
-@@ -35,24 +35,25 @@
- #include "hb-font.hh"
- 
- struct hb_subset_input_t
- {
-   hb_object_header_t header;
- 
-   hb_set_t *unicodes;
-   hb_set_t *glyphs;
-+  hb_set_t *name_ids;
-+  hb_set_t *drop_tables;
- 
--  bool drop_hints : 1;
--  bool drop_layout : 1;
--  bool desubroutinize : 1;
--  bool retain_gids : 1;
-+  bool drop_hints;
-+  bool desubroutinize;
-+  bool retain_gids;
-   /* TODO
-    *
-    * features
-    * lookups
--   * nameIDs
-+   * name_ids
-    * ...
-    */
- };
- 
- 
- #endif /* HB_SUBSET_INPUT_HH */
-diff --git a/gfx/harfbuzz/src/hb-subset-plan.cc b/gfx/harfbuzz/src/hb-subset-plan.cc
---- a/gfx/harfbuzz/src/hb-subset-plan.cc
-+++ b/gfx/harfbuzz/src/hb-subset-plan.cc
-@@ -26,18 +26,20 @@
- 
- #include "hb-subset-plan.hh"
- #include "hb-map.hh"
- #include "hb-set.hh"
- 
- #include "hb-ot-cmap-table.hh"
- #include "hb-ot-glyf-table.hh"
- #include "hb-ot-cff1-table.hh"
-+#include "hb-ot-var-fvar-table.hh"
-+#include "hb-ot-stat-table.hh"
- 
--static void
-+static inline void
- _add_gid_and_children (const OT::glyf::accelerator_t &glyf,
- 		       hb_codepoint_t gid,
- 		       hb_set_t *gids_to_retain)
- {
-   if (hb_set_has (gids_to_retain, gid))
-     // Already visited this gid, ignore.
-     return;
- 
-@@ -48,145 +50,171 @@ static void
-   {
-     do
-     {
-       _add_gid_and_children (glyf, (hb_codepoint_t) composite.current->glyphIndex, gids_to_retain);
-     } while (composite.move_to_next());
-   }
- }
- 
--static void
-+#ifndef HB_NO_SUBSET_CFF
-+static inline void
- _add_cff_seac_components (const OT::cff1::accelerator_t &cff,
-            hb_codepoint_t gid,
-            hb_set_t *gids_to_retain)
- {
-   hb_codepoint_t base_gid, accent_gid;
-   if (cff.get_seac_components (gid, &base_gid, &accent_gid))
-   {
-     hb_set_add (gids_to_retain, base_gid);
-     hb_set_add (gids_to_retain, accent_gid);
-   }
- }
-+#endif
- 
--static void
-+#ifndef HB_NO_SUBSET_LAYOUT
-+static inline void
- _gsub_closure (hb_face_t *face, hb_set_t *gids_to_retain)
- {
-   hb_set_t lookup_indices;
-   hb_ot_layout_collect_lookups (face,
- 				HB_OT_TAG_GSUB,
- 				nullptr,
- 				nullptr,
- 				nullptr,
- 				&lookup_indices);
-   hb_ot_layout_lookups_substitute_closure (face,
- 					   &lookup_indices,
- 					   gids_to_retain);
- }
-+#endif
- 
--static void
-+static inline void
- _remove_invalid_gids (hb_set_t *glyphs,
- 		      unsigned int num_glyphs)
- {
-   hb_codepoint_t gid = HB_SET_VALUE_INVALID;
-   while (glyphs->next (&gid))
-   {
-     if (gid >= num_glyphs)
-       glyphs->del (gid);
-   }
- }
- 
--static hb_set_t *
--_populate_gids_to_retain (hb_face_t *face,
-+static void
-+_populate_gids_to_retain (hb_subset_plan_t* plan,
- 			  const hb_set_t *unicodes,
-                           const hb_set_t *input_glyphs_to_retain,
--			  bool close_over_gsub,
--			  hb_set_t *unicodes_to_retain,
--			  hb_map_t *codepoint_to_glyph)
-+			  bool close_over_gsub)
- {
-   OT::cmap::accelerator_t cmap;
-   OT::glyf::accelerator_t glyf;
-   OT::cff1::accelerator_t cff;
--  cmap.init (face);
--  glyf.init (face);
--  cff.init (face);
-+  cmap.init (plan->source);
-+  glyf.init (plan->source);
-+  cff.init (plan->source);
- 
--  hb_set_t *initial_gids_to_retain = hb_set_create ();
--  initial_gids_to_retain->add (0); // Not-def
--  hb_set_union (initial_gids_to_retain, input_glyphs_to_retain);
-+  plan->_glyphset_gsub->add (0); // Not-def
-+  hb_set_union (plan->_glyphset_gsub, input_glyphs_to_retain);
- 
-   hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-   while (unicodes->next (&cp))
-   {
-     hb_codepoint_t gid;
-     if (!cmap.get_nominal_glyph (cp, &gid))
-     {
-       DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
-       continue;
-     }
--    unicodes_to_retain->add (cp);
--    codepoint_to_glyph->set (cp, gid);
--    initial_gids_to_retain->add (gid);
-+    plan->unicodes->add (cp);
-+    plan->codepoint_to_glyph->set (cp, gid);
-+    plan->_glyphset_gsub->add (gid);
-   }
- 
-+#ifndef HB_NO_SUBSET_LAYOUT
-   if (close_over_gsub)
-     // Add all glyphs needed for GSUB substitutions.
--    _gsub_closure (face, initial_gids_to_retain);
-+    _gsub_closure (plan->source, plan->_glyphset_gsub);
-+#endif
-+  _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
- 
-   // Populate a full set of glyphs to retain by adding all referenced
-   // composite glyphs.
-   hb_codepoint_t gid = HB_SET_VALUE_INVALID;
--  hb_set_t *all_gids_to_retain = hb_set_create ();
--  while (initial_gids_to_retain->next (&gid))
-+  while (plan->_glyphset_gsub->next (&gid))
-   {
--    _add_gid_and_children (glyf, gid, all_gids_to_retain);
-+    _add_gid_and_children (glyf, gid, plan->_glyphset);
-+#ifndef HB_NO_SUBSET_CFF
-     if (cff.is_valid ())
--      _add_cff_seac_components (cff, gid, all_gids_to_retain);
-+      _add_cff_seac_components (cff, gid, plan->_glyphset);
-+#endif
-   }
--  hb_set_destroy (initial_gids_to_retain);
- 
--  _remove_invalid_gids (all_gids_to_retain, face->get_num_glyphs ());
--
-+  _remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
- 
-   cff.fini ();
-   glyf.fini ();
-   cmap.fini ();
--
--  return all_gids_to_retain;
- }
- 
- static void
--_create_old_gid_to_new_gid_map (const hb_face_t                   *face,
--                                bool                               retain_gids,
--				hb_set_t                          *all_gids_to_retain,
--                                hb_map_t                          *glyph_map, /* OUT */
--                                hb_map_t                          *reverse_glyph_map, /* OUT */
--                                unsigned int                      *num_glyphs /* OUT */)
-+_create_old_gid_to_new_gid_map (const hb_face_t *face,
-+                                bool             retain_gids,
-+				const hb_set_t  *all_gids_to_retain,
-+                                hb_map_t        *glyph_map, /* OUT */
-+                                hb_map_t        *reverse_glyph_map, /* OUT */
-+                                unsigned int    *num_glyphs /* OUT */)
- {
--  hb_codepoint_t gid = HB_SET_VALUE_INVALID;
--  unsigned int length = 0;
--  for (unsigned int i = 0; all_gids_to_retain->next (&gid); i++) {
--    if (!retain_gids)
--    {
--      glyph_map->set (gid, i);
--      reverse_glyph_map->set (i, gid);
-+  if (!retain_gids)
-+  {
-+    + hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
-+    | hb_sink (reverse_glyph_map)
-+    ;
-+    *num_glyphs = reverse_glyph_map->get_population ();
-+  } else {
-+    + hb_iter (all_gids_to_retain)
-+    | hb_map ([] (hb_codepoint_t _) {
-+		return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _);
-+	      })
-+    | hb_sink (reverse_glyph_map)
-+    ;
-+
-+    unsigned max_glyph =
-+    + hb_iter (all_gids_to_retain)
-+    | hb_reduce (hb_max, 0)
-+    ;
-+    *num_glyphs = max_glyph + 1;
-+  }
-+
-+  + reverse_glyph_map->iter ()
-+  | hb_map (&hb_pair_t<hb_codepoint_t, hb_codepoint_t>::reverse)
-+  | hb_sink (glyph_map)
-+  ;
-+}
-+
-+static void
-+_nameid_closure (hb_face_t           *face,
-+                 hb_set_t            *nameids)
-+{
-+  hb_tag_t table_tags[32];
-+  unsigned count = ARRAY_LENGTH (table_tags);
-+  hb_face_get_table_tags (face, 0, &count, table_tags);
-+  for (unsigned int i = 0; i < count; i++)
-+  {
-+    hb_tag_t tag = table_tags[i];
-+    switch (tag) {
-+      case HB_OT_TAG_STAT:
-+        face->table.STAT->collect_name_ids (nameids);
-+        break;
-+      case HB_OT_TAG_fvar:
-+        face->table.fvar->collect_name_ids (nameids);
-+        break;
-+      default:
-+        break;
-     }
--    else
--    {
--      glyph_map->set (gid, gid);
--      reverse_glyph_map->set (gid, gid);
--    }
--    ++length;
--  }
--  if (!retain_gids || length == 0)
--  {
--    *num_glyphs = length;
--  }
--  else
--  {
--    *num_glyphs = face->get_num_glyphs ();
-   }
- }
- 
- /**
-  * hb_subset_plan_create:
-  * Computes a plan for subsetting the supplied face according
-  * to a provided input. The plan describes
-  * which tables and glyphs should be retained.
-@@ -197,30 +225,35 @@ static void
-  **/
- hb_subset_plan_t *
- hb_subset_plan_create (hb_face_t           *face,
- 		       hb_subset_input_t   *input)
- {
-   hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
- 
-   plan->drop_hints = input->drop_hints;
--  plan->drop_layout = input->drop_layout;
-   plan->desubroutinize = input->desubroutinize;
--  plan->unicodes = hb_set_create();
-+  plan->retain_gids = input->retain_gids;
-+  plan->unicodes = hb_set_create ();
-+  plan->name_ids = hb_set_reference (input->name_ids);
-+  _nameid_closure (face, plan->name_ids);
-+  plan->drop_tables = hb_set_reference (input->drop_tables);
-   plan->source = hb_face_reference (face);
-   plan->dest = hb_face_builder_create ();
--  plan->codepoint_to_glyph = hb_map_create();
--  plan->glyph_map = hb_map_create();
--  plan->reverse_glyph_map = hb_map_create();
--  plan->_glyphset = _populate_gids_to_retain (face,
--                                              input->unicodes,
--                                              input->glyphs,
--                                              !plan->drop_layout,
--                                              plan->unicodes,
--                                              plan->codepoint_to_glyph);
-+
-+  plan->_glyphset = hb_set_create ();
-+  plan->_glyphset_gsub = hb_set_create ();
-+  plan->codepoint_to_glyph = hb_map_create ();
-+  plan->glyph_map = hb_map_create ();
-+  plan->reverse_glyph_map = hb_map_create ();
-+
-+  _populate_gids_to_retain (plan,
-+                            input->unicodes,
-+                            input->glyphs,
-+                            !input->drop_tables->has (HB_OT_TAG_GSUB));
- 
-   _create_old_gid_to_new_gid_map (face,
-                                   input->retain_gids,
- 				  plan->_glyphset,
- 				  plan->glyph_map,
-                                   plan->reverse_glyph_map,
-                                   &plan->_num_output_glyphs);
- 
-@@ -233,17 +266,20 @@ hb_subset_plan_create (hb_face_t        
-  * Since: 1.7.5
-  **/
- void
- hb_subset_plan_destroy (hb_subset_plan_t *plan)
- {
-   if (!hb_object_destroy (plan)) return;
- 
-   hb_set_destroy (plan->unicodes);
-+  hb_set_destroy (plan->name_ids);
-+  hb_set_destroy (plan->drop_tables);
-   hb_face_destroy (plan->source);
-   hb_face_destroy (plan->dest);
-   hb_map_destroy (plan->codepoint_to_glyph);
-   hb_map_destroy (plan->glyph_map);
-   hb_map_destroy (plan->reverse_glyph_map);
-   hb_set_destroy (plan->_glyphset);
-+  hb_set_destroy (plan->_glyphset_gsub);
- 
-   free (plan);
- }
-diff --git a/gfx/harfbuzz/src/hb-subset-plan.hh b/gfx/harfbuzz/src/hb-subset-plan.hh
---- a/gfx/harfbuzz/src/hb-subset-plan.hh
-+++ b/gfx/harfbuzz/src/hb-subset-plan.hh
-@@ -35,48 +35,66 @@
- #include "hb-map.hh"
- #include "hb-set.hh"
- 
- struct hb_subset_plan_t
- {
-   hb_object_header_t header;
- 
-   bool drop_hints : 1;
--  bool drop_layout : 1;
-   bool desubroutinize : 1;
-+  bool retain_gids : 1;
- 
-   // For each cp that we'd like to retain maps to the corresponding gid.
-   hb_set_t *unicodes;
- 
-+  // name_ids we would like to retain
-+  hb_set_t *name_ids;
-+
-+  // Tables which should be dropped.
-+  hb_set_t *drop_tables;
-+
-   // The glyph subset
-   hb_map_t *codepoint_to_glyph;
- 
-   // Old -> New glyph id mapping
-   hb_map_t *glyph_map;
-   hb_map_t *reverse_glyph_map;
- 
-   // Plan is only good for a specific source/dest so keep them with it
-   hb_face_t *source;
-   hb_face_t *dest;
- 
-   unsigned int _num_output_glyphs;
-   hb_set_t *_glyphset;
-+  hb_set_t *_glyphset_gsub;
- 
-  public:
- 
-   /*
-    * The set of input glyph ids which will be retained in the subset.
-+   * Does NOT include ids kept due to retain_gids. You probably want to use
-+   * glyph_map/reverse_glyph_map.
-    */
-   inline const hb_set_t *
-   glyphset () const
-   {
-     return _glyphset;
-   }
- 
-   /*
-+   * The set of input glyph ids which will be retained in the subset.
-+   */
-+  inline const hb_set_t *
-+  glyphset_gsub () const
-+  {
-+    return _glyphset_gsub;
-+  }
-+
-+  /*
-    * The total number of output glyphs in the final subset.
-    */
-   inline unsigned int
-   num_output_glyphs () const
-   {
-     return _num_output_glyphs;
-   }
- 
-diff --git a/gfx/harfbuzz/src/hb-subset.cc b/gfx/harfbuzz/src/hb-subset.cc
---- a/gfx/harfbuzz/src/hb-subset.cc
-+++ b/gfx/harfbuzz/src/hb-subset.cc
-@@ -23,93 +23,105 @@
-  *
-  * Google Author(s): Garret Rieger, Rod Sheeter, Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- #include "hb-open-type.hh"
- 
- #include "hb-subset.hh"
--#include "hb-subset-glyf.hh"
- 
- #include "hb-open-file.hh"
- #include "hb-ot-cmap-table.hh"
- #include "hb-ot-glyf-table.hh"
- #include "hb-ot-hdmx-table.hh"
- #include "hb-ot-head-table.hh"
- #include "hb-ot-hhea-table.hh"
- #include "hb-ot-hmtx-table.hh"
- #include "hb-ot-maxp-table.hh"
- #include "hb-ot-os2-table.hh"
- #include "hb-ot-post-table.hh"
- #include "hb-ot-cff1-table.hh"
- #include "hb-ot-cff2-table.hh"
- #include "hb-ot-vorg-table.hh"
-+#include "hb-ot-name-table.hh"
- #include "hb-ot-layout-gsub-table.hh"
- #include "hb-ot-layout-gpos-table.hh"
- 
- 
--static unsigned int
-+HB_UNUSED static inline unsigned int
-+_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
-+				  unsigned int table_len);
-+static inline unsigned int
- _plan_estimate_subset_table_size (hb_subset_plan_t *plan,
- 				  unsigned int table_len)
- {
-   unsigned int src_glyphs = plan->source->get_num_glyphs ();
-   unsigned int dst_glyphs = plan->glyphset ()->get_population ();
- 
-   if (unlikely (!src_glyphs))
-     return 512 + table_len;
- 
-   return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
- }
- 
- template<typename TableType>
- static bool
- _subset2 (hb_subset_plan_t *plan)
- {
-+  bool result = true;
-   hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
-   const TableType *table = source_blob->as<TableType> ();
- 
-   hb_tag_t tag = TableType::tableTag;
--  hb_bool_t result = false;
-   if (source_blob->data)
-   {
-     hb_vector_t<char> buf;
-+    /* TODO Not all tables are glyph-related.  'name' table size for example should not be
-+     * affected by number of glyphs.  Accommodate that. */
-     unsigned int buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
-     DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
-     if (unlikely (!buf.alloc (buf_size)))
-     {
-       DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
-       return false;
-     }
-   retry:
-     hb_serialize_context_t serializer ((void *) buf, buf_size);
-+    serializer.start_serialize<TableType> ();
-     hb_subset_context_t c (plan, &serializer);
--    result = table->subset (&c);
--    if (serializer.in_error ())
-+    bool needed = table->subset (&c);
-+    if (serializer.ran_out_of_room)
-     {
-       buf_size += (buf_size >> 1) + 32;
-       DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
-       if (unlikely (!buf.alloc (buf_size)))
-       {
- 	DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
- 	return false;
-       }
-       goto retry;
-     }
-+    serializer.end_serialize ();
-+
-+    result = !serializer.in_error ();
-+
-     if (result)
-     {
--      hb_blob_t *dest_blob = serializer.copy_blob ();
--      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
--      result = c.plan->add_table (tag, dest_blob);
--      hb_blob_destroy (dest_blob);
--    }
--    else
--    {
--      DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
--      result = true;
-+      if (needed)
-+      {
-+	hb_blob_t *dest_blob = serializer.copy_blob ();
-+	DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
-+	result = c.plan->add_table (tag, dest_blob);
-+	hb_blob_destroy (dest_blob);
-+      }
-+      else
-+      {
-+	DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
-+      }
-     }
-   }
-   else
-     DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
- 
-   hb_blob_destroy (source_blob);
-   DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
-   return result;
-@@ -138,20 +150,23 @@ static bool
- static bool
- _subset_table (hb_subset_plan_t *plan,
- 	       hb_tag_t          tag)
- {
-   DEBUG_MSG(SUBSET, nullptr, "begin subset %c%c%c%c", HB_UNTAG (tag));
-   bool result = true;
-   switch (tag) {
-     case HB_OT_TAG_glyf:
--      result = _subset<const OT::glyf> (plan);
-+      result = _subset2<const OT::glyf> (plan);
-       break;
-     case HB_OT_TAG_hdmx:
--      result = _subset<const OT::hdmx> (plan);
-+      result = _subset2<const OT::hdmx> (plan);
-+      break;
-+    case HB_OT_TAG_name:
-+      result = _subset2<const OT::name> (plan);
-       break;
-     case HB_OT_TAG_head:
-       // TODO that won't work well if there is no glyf
-       DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
-       result = true;
-       break;
-     case HB_OT_TAG_hhea:
-       DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
-@@ -175,34 +190,40 @@ static bool
-       result = _subset<const OT::cmap> (plan);
-       break;
-     case HB_OT_TAG_OS2:
-       result = _subset<const OT::OS2> (plan);
-       break;
-     case HB_OT_TAG_post:
-       result = _subset<const OT::post> (plan);
-       break;
-+
-+#ifndef HB_NO_SUBSET_CFF
-     case HB_OT_TAG_cff1:
-       result = _subset<const OT::cff1> (plan);
-       break;
-     case HB_OT_TAG_cff2:
-       result = _subset<const OT::cff2> (plan);
-       break;
-     case HB_OT_TAG_VORG:
-       result = _subset<const OT::VORG> (plan);
-       break;
-+#endif
-+
-+#ifndef HB_NO_SUBSET_LAYOUT
-     case HB_OT_TAG_GDEF:
-       result = _subset2<const OT::GDEF> (plan);
-       break;
-     case HB_OT_TAG_GSUB:
-       result = _subset2<const OT::GSUB> (plan);
-       break;
-     case HB_OT_TAG_GPOS:
-       result = _subset2<const OT::GPOS> (plan);
-       break;
-+#endif
- 
-     default:
-       hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
-       if (likely (source_table))
- 	result = plan->add_table (tag, source_table);
-       else
- 	result = false;
-       hb_blob_destroy (source_table);
-@@ -210,49 +231,40 @@ static bool
-   }
-   DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG (tag), result ? "ok" : "FAILED");
-   return result;
- }
- 
- static bool
- _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
- {
-+  if (plan->drop_tables->has (tag))
-+    return true;
-+
-   switch (tag) {
-     case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */
-     case HB_TAG ('c', 'v', 't', ' '): /* hint table, fallthrough */
-     case HB_TAG ('f', 'p', 'g', 'm'): /* hint table, fallthrough */
-     case HB_TAG ('p', 'r', 'e', 'p'): /* hint table, fallthrough */
-     case HB_TAG ('h', 'd', 'm', 'x'): /* hint table, fallthrough */
-     case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
-       return plan->drop_hints;
-+
-+#ifdef HB_NO_SUBSET_LAYOUT
-     // Drop Layout Tables if requested.
-     case HB_OT_TAG_GDEF:
-     case HB_OT_TAG_GPOS:
-     case HB_OT_TAG_GSUB:
--      return plan->drop_layout;
--    // Drop these tables below by default, list pulled
--    // from fontTools:
--    case HB_TAG ('B', 'A', 'S', 'E'):
--    case HB_TAG ('J', 'S', 'T', 'F'):
--    case HB_TAG ('D', 'S', 'I', 'G'):
--    case HB_TAG ('E', 'B', 'D', 'T'):
--    case HB_TAG ('E', 'B', 'L', 'C'):
--    case HB_TAG ('E', 'B', 'S', 'C'):
--    case HB_TAG ('S', 'V', 'G', ' '):
--    case HB_TAG ('P', 'C', 'L', 'T'):
--    case HB_TAG ('L', 'T', 'S', 'H'):
--    // Graphite tables:
--    case HB_TAG ('F', 'e', 'a', 't'):
--    case HB_TAG ('G', 'l', 'a', 't'):
--    case HB_TAG ('G', 'l', 'o', 'c'):
--    case HB_TAG ('S', 'i', 'l', 'f'):
--    case HB_TAG ('S', 'i', 'l', 'l'):
--    // Colour
--    case HB_TAG ('s', 'b', 'i', 'x'):
-+    case HB_TAG ('m', 'o', 'r', 'x'):
-+    case HB_TAG ('m', 'o', 'r', 't'):
-+    case HB_TAG ('k', 'e', 'r', 'x'):
-+    case HB_TAG ('k', 'e', 'r', 'n'):
-       return true;
-+#endif
-+
-     default:
-       return false;
-   }
- }
- 
- /**
-  * hb_subset:
-  * @source: font face data to be subset.
-diff --git a/gfx/harfbuzz/src/hb-subset.h b/gfx/harfbuzz/src/hb-subset.h
---- a/gfx/harfbuzz/src/hb-subset.h
-+++ b/gfx/harfbuzz/src/hb-subset.h
-@@ -49,29 +49,29 @@ HB_EXTERN void
- hb_subset_input_destroy (hb_subset_input_t *subset_input);
- 
- HB_EXTERN hb_set_t *
- hb_subset_input_unicode_set (hb_subset_input_t *subset_input);
- 
- HB_EXTERN hb_set_t *
- hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
- 
-+HB_EXTERN hb_set_t *
-+hb_subset_input_nameid_set (hb_subset_input_t *subset_input);
-+
-+HB_EXTERN hb_set_t *
-+hb_subset_input_drop_tables_set (hb_subset_input_t *subset_input);
-+
- HB_EXTERN void
- hb_subset_input_set_drop_hints (hb_subset_input_t *subset_input,
- 				hb_bool_t drop_hints);
- HB_EXTERN hb_bool_t
- hb_subset_input_get_drop_hints (hb_subset_input_t *subset_input);
- 
- HB_EXTERN void
--hb_subset_input_set_drop_layout (hb_subset_input_t *subset_input,
--				 hb_bool_t drop_layout);
--HB_EXTERN hb_bool_t
--hb_subset_input_get_drop_layout (hb_subset_input_t *subset_input);
--
--HB_EXTERN void
- hb_subset_input_set_desubroutinize (hb_subset_input_t *subset_input,
-         hb_bool_t desubroutinize);
- HB_EXTERN hb_bool_t
- hb_subset_input_get_desubroutinize (hb_subset_input_t *subset_input);
- 
- HB_EXTERN void
- hb_subset_input_set_retain_gids (hb_subset_input_t *subset_input,
- 				 hb_bool_t retain_gids);
-diff --git a/gfx/harfbuzz/src/hb-subset.hh b/gfx/harfbuzz/src/hb-subset.hh
---- a/gfx/harfbuzz/src/hb-subset.hh
-+++ b/gfx/harfbuzz/src/hb-subset.hh
-@@ -35,19 +35,29 @@
- #include "hb-machinery.hh"
- #include "hb-subset-input.hh"
- #include "hb-subset-plan.hh"
- 
- struct hb_subset_context_t :
-        hb_dispatch_context_t<hb_subset_context_t, bool, HB_DEBUG_SUBSET>
- {
-   const char *get_name () { return "SUBSET"; }
--  template <typename T>
--  bool dispatch (const T &obj) { return obj.subset (this); }
--  static bool default_return_value () { return true; }
-+  static return_t default_return_value () { return true; }
-+
-+  private:
-+  template <typename T, typename ...Ts> auto
-+  _dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
-+  ( obj.subset (this, hb_forward<Ts> (ds)...) )
-+  template <typename T, typename ...Ts> auto
-+  _dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
-+  ( obj.dispatch (this, hb_forward<Ts> (ds)...) )
-+  public:
-+  template <typename T, typename ...Ts> auto
-+  dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
-+  ( _dispatch (obj, hb_prioritize, hb_forward<Ts> (ds)...) )
- 
-   hb_subset_plan_t *plan;
-   hb_serialize_context_t *serializer;
-   unsigned int debug_depth;
- 
-   hb_subset_context_t (hb_subset_plan_t *plan_,
- 		       hb_serialize_context_t *serializer_) :
- 			plan (plan_),
-diff --git a/gfx/harfbuzz/src/hb-ucd-table.hh b/gfx/harfbuzz/src/hb-ucd-table.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-ucd-table.hh
-@@ -0,0 +1,5160 @@
-+/* == Start of generated table == */
-+/*
-+ * The following table is generated by running:
-+ *
-+ *   ./gen-ucd-table.py ucd.nonunihan.grouped.xml
-+ *
-+ * on file with this description: Unicode 12.1.0
-+ */
-+
-+#ifndef HB_UCD_TABLE_HH
-+#define HB_UCD_TABLE_HH
-+
-+
-+#include "hb.hh"
-+
-+static const hb_script_t
-+_hb_ucd_sc_map[138] =
-+{
-+                   HB_SCRIPT_COMMON,              HB_SCRIPT_INHERITED,
-+                  HB_SCRIPT_UNKNOWN,                 HB_SCRIPT_ARABIC,
-+                 HB_SCRIPT_ARMENIAN,                HB_SCRIPT_BENGALI,
-+                 HB_SCRIPT_CYRILLIC,             HB_SCRIPT_DEVANAGARI,
-+                 HB_SCRIPT_GEORGIAN,                  HB_SCRIPT_GREEK,
-+                 HB_SCRIPT_GUJARATI,               HB_SCRIPT_GURMUKHI,
-+                   HB_SCRIPT_HANGUL,                    HB_SCRIPT_HAN,
-+                   HB_SCRIPT_HEBREW,               HB_SCRIPT_HIRAGANA,
-+                  HB_SCRIPT_KANNADA,               HB_SCRIPT_KATAKANA,
-+                      HB_SCRIPT_LAO,                  HB_SCRIPT_LATIN,
-+                HB_SCRIPT_MALAYALAM,                  HB_SCRIPT_ORIYA,
-+                    HB_SCRIPT_TAMIL,                 HB_SCRIPT_TELUGU,
-+                     HB_SCRIPT_THAI,                HB_SCRIPT_TIBETAN,
-+                 HB_SCRIPT_BOPOMOFO,                HB_SCRIPT_BRAILLE,
-+       HB_SCRIPT_CANADIAN_SYLLABICS,               HB_SCRIPT_CHEROKEE,
-+                 HB_SCRIPT_ETHIOPIC,                  HB_SCRIPT_KHMER,
-+                HB_SCRIPT_MONGOLIAN,                HB_SCRIPT_MYANMAR,
-+                    HB_SCRIPT_OGHAM,                  HB_SCRIPT_RUNIC,
-+                  HB_SCRIPT_SINHALA,                 HB_SCRIPT_SYRIAC,
-+                   HB_SCRIPT_THAANA,                     HB_SCRIPT_YI,
-+                  HB_SCRIPT_DESERET,                 HB_SCRIPT_GOTHIC,
-+               HB_SCRIPT_OLD_ITALIC,                  HB_SCRIPT_BUHID,
-+                  HB_SCRIPT_HANUNOO,                HB_SCRIPT_TAGALOG,
-+                 HB_SCRIPT_TAGBANWA,                HB_SCRIPT_CYPRIOT,
-+                    HB_SCRIPT_LIMBU,               HB_SCRIPT_LINEAR_B,
-+                  HB_SCRIPT_OSMANYA,                HB_SCRIPT_SHAVIAN,
-+                   HB_SCRIPT_TAI_LE,               HB_SCRIPT_UGARITIC,
-+                 HB_SCRIPT_BUGINESE,                 HB_SCRIPT_COPTIC,
-+               HB_SCRIPT_GLAGOLITIC,             HB_SCRIPT_KHAROSHTHI,
-+              HB_SCRIPT_NEW_TAI_LUE,            HB_SCRIPT_OLD_PERSIAN,
-+             HB_SCRIPT_SYLOTI_NAGRI,               HB_SCRIPT_TIFINAGH,
-+                 HB_SCRIPT_BALINESE,              HB_SCRIPT_CUNEIFORM,
-+                      HB_SCRIPT_NKO,               HB_SCRIPT_PHAGS_PA,
-+               HB_SCRIPT_PHOENICIAN,                 HB_SCRIPT_CARIAN,
-+                     HB_SCRIPT_CHAM,               HB_SCRIPT_KAYAH_LI,
-+                   HB_SCRIPT_LEPCHA,                 HB_SCRIPT_LYCIAN,
-+                   HB_SCRIPT_LYDIAN,               HB_SCRIPT_OL_CHIKI,
-+                   HB_SCRIPT_REJANG,             HB_SCRIPT_SAURASHTRA,
-+                HB_SCRIPT_SUNDANESE,                    HB_SCRIPT_VAI,
-+                  HB_SCRIPT_AVESTAN,                  HB_SCRIPT_BAMUM,
-+     HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,       HB_SCRIPT_IMPERIAL_ARAMAIC,
-+    HB_SCRIPT_INSCRIPTIONAL_PAHLAVI, HB_SCRIPT_INSCRIPTIONAL_PARTHIAN,
-+                 HB_SCRIPT_JAVANESE,                 HB_SCRIPT_KAITHI,
-+                     HB_SCRIPT_LISU,           HB_SCRIPT_MEETEI_MAYEK,
-+        HB_SCRIPT_OLD_SOUTH_ARABIAN,             HB_SCRIPT_OLD_TURKIC,
-+                HB_SCRIPT_SAMARITAN,               HB_SCRIPT_TAI_THAM,
-+                 HB_SCRIPT_TAI_VIET,                  HB_SCRIPT_BATAK,
-+                   HB_SCRIPT_BRAHMI,                HB_SCRIPT_MANDAIC,
-+                   HB_SCRIPT_CHAKMA,       HB_SCRIPT_MEROITIC_CURSIVE,
-+     HB_SCRIPT_MEROITIC_HIEROGLYPHS,                   HB_SCRIPT_MIAO,
-+                  HB_SCRIPT_SHARADA,           HB_SCRIPT_SORA_SOMPENG,
-+                    HB_SCRIPT_TAKRI,              HB_SCRIPT_BASSA_VAH,
-+       HB_SCRIPT_CAUCASIAN_ALBANIAN,               HB_SCRIPT_DUPLOYAN,
-+                  HB_SCRIPT_ELBASAN,                HB_SCRIPT_GRANTHA,
-+                   HB_SCRIPT_KHOJKI,              HB_SCRIPT_KHUDAWADI,
-+                 HB_SCRIPT_LINEAR_A,               HB_SCRIPT_MAHAJANI,
-+               HB_SCRIPT_MANICHAEAN,          HB_SCRIPT_MENDE_KIKAKUI,
-+                     HB_SCRIPT_MODI,                    HB_SCRIPT_MRO,
-+                HB_SCRIPT_NABATAEAN,      HB_SCRIPT_OLD_NORTH_ARABIAN,
-+               HB_SCRIPT_OLD_PERMIC,           HB_SCRIPT_PAHAWH_HMONG,
-+                HB_SCRIPT_PALMYRENE,            HB_SCRIPT_PAU_CIN_HAU,
-+          HB_SCRIPT_PSALTER_PAHLAVI,                HB_SCRIPT_SIDDHAM,
-+                  HB_SCRIPT_TIRHUTA,            HB_SCRIPT_WARANG_CITI,
-+                     HB_SCRIPT_AHOM,  HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
-+                   HB_SCRIPT_HATRAN,                HB_SCRIPT_MULTANI,
-+            HB_SCRIPT_OLD_HUNGARIAN,            HB_SCRIPT_SIGNWRITING,
-+                    HB_SCRIPT_ADLAM,              HB_SCRIPT_BHAIKSUKI,
-+                  HB_SCRIPT_MARCHEN,                  HB_SCRIPT_OSAGE,
-+                   HB_SCRIPT_TANGUT,                   HB_SCRIPT_NEWA,
-+};
-+static const hb_codepoint_t
-+_hb_ucd_dm1_map[935] =
-+{
-+   0x003Bu, 0x004Bu, 0x0060u, 0x00B4u, 0x00B7u, 0x00C5u, 0x02B9u, 0x0300u,
-+   0x0301u, 0x0313u, 0x0385u, 0x0386u, 0x0388u, 0x0389u, 0x038Au, 0x038Cu,
-+   0x038Eu, 0x038Fu, 0x0390u, 0x03A9u, 0x03ACu, 0x03ADu, 0x03AEu, 0x03AFu,
-+   0x03B0u, 0x03B9u, 0x03CCu, 0x03CDu, 0x03CEu, 0x2002u, 0x2003u, 0x3008u,
-+   0x3009u, 0x349Eu, 0x34B9u, 0x34BBu, 0x34DFu, 0x3515u, 0x36EEu, 0x36FCu,
-+   0x3781u, 0x382Fu, 0x3862u, 0x387Cu, 0x38C7u, 0x38E3u, 0x391Cu, 0x393Au,
-+   0x3A2Eu, 0x3A6Cu, 0x3AE4u, 0x3B08u, 0x3B19u, 0x3B49u, 0x3B9Du, 0x3C18u,
-+   0x3C4Eu, 0x3D33u, 0x3D96u, 0x3EACu, 0x3EB8u, 0x3F1Bu, 0x3FFCu, 0x4008u,
-+   0x4018u, 0x4039u, 0x4046u, 0x4096u, 0x40E3u, 0x412Fu, 0x4202u, 0x4227u,
-+   0x42A0u, 0x4301u, 0x4334u, 0x4359u, 0x43D5u, 0x43D9u, 0x440Bu, 0x446Bu,
-+   0x452Bu, 0x455Du, 0x4561u, 0x456Bu, 0x45D7u, 0x45F9u, 0x4635u, 0x46BEu,
-+   0x46C7u, 0x4995u, 0x49E6u, 0x4A6Eu, 0x4A76u, 0x4AB2u, 0x4B33u, 0x4BCEu,
-+   0x4CCEu, 0x4CEDu, 0x4CF8u, 0x4D56u, 0x4E0Du, 0x4E26u, 0x4E32u, 0x4E38u,
-+   0x4E39u, 0x4E3Du, 0x4E41u, 0x4E82u, 0x4E86u, 0x4EAEu, 0x4EC0u, 0x4ECCu,
-+   0x4EE4u, 0x4F60u, 0x4F80u, 0x4F86u, 0x4F8Bu, 0x4FAEu, 0x4FBBu, 0x4FBFu,
-+   0x5002u, 0x502Bu, 0x507Au, 0x5099u, 0x50CFu, 0x50DAu, 0x50E7u, 0x5140u,
-+   0x5145u, 0x514Du, 0x5154u, 0x5164u, 0x5167u, 0x5168u, 0x5169u, 0x516Du,
-+   0x5177u, 0x5180u, 0x518Du, 0x5192u, 0x5195u, 0x5197u, 0x51A4u, 0x51ACu,
-+   0x51B5u, 0x51B7u, 0x51C9u, 0x51CCu, 0x51DCu, 0x51DEu, 0x51F5u, 0x5203u,
-+   0x5207u, 0x5217u, 0x5229u, 0x523Au, 0x523Bu, 0x5246u, 0x5272u, 0x5277u,
-+   0x5289u, 0x529Bu, 0x52A3u, 0x52B3u, 0x52C7u, 0x52C9u, 0x52D2u, 0x52DEu,
-+   0x52E4u, 0x52F5u, 0x52FAu, 0x5305u, 0x5306u, 0x5317u, 0x533Fu, 0x5349u,
-+   0x5351u, 0x535Au, 0x5373u, 0x5375u, 0x537Du, 0x537Fu, 0x53C3u, 0x53CAu,
-+   0x53DFu, 0x53E5u, 0x53EBu, 0x53F1u, 0x5406u, 0x540Fu, 0x541Du, 0x5438u,
-+   0x5442u, 0x5448u, 0x5468u, 0x549Eu, 0x54A2u, 0x54BDu, 0x54F6u, 0x5510u,
-+   0x5553u, 0x5555u, 0x5563u, 0x5584u, 0x5587u, 0x5599u, 0x559Du, 0x55ABu,
-+   0x55B3u, 0x55C0u, 0x55C2u, 0x55E2u, 0x5606u, 0x5651u, 0x5668u, 0x5674u,
-+   0x56F9u, 0x5716u, 0x5717u, 0x578Bu, 0x57CEu, 0x57F4u, 0x580Du, 0x5831u,
-+   0x5832u, 0x5840u, 0x585Au, 0x585Eu, 0x58A8u, 0x58ACu, 0x58B3u, 0x58D8u,
-+   0x58DFu, 0x58EEu, 0x58F2u, 0x58F7u, 0x5906u, 0x591Au, 0x5922u, 0x5944u,
-+   0x5948u, 0x5951u, 0x5954u, 0x5962u, 0x5973u, 0x59D8u, 0x59ECu, 0x5A1Bu,
-+   0x5A27u, 0x5A62u, 0x5A66u, 0x5AB5u, 0x5B08u, 0x5B28u, 0x5B3Eu, 0x5B85u,
-+   0x5BC3u, 0x5BD8u, 0x5BE7u, 0x5BEEu, 0x5BF3u, 0x5BFFu, 0x5C06u, 0x5C22u,
-+   0x5C3Fu, 0x5C60u, 0x5C62u, 0x5C64u, 0x5C65u, 0x5C6Eu, 0x5C8Du, 0x5CC0u,
-+   0x5D19u, 0x5D43u, 0x5D50u, 0x5D6Bu, 0x5D6Eu, 0x5D7Cu, 0x5DB2u, 0x5DBAu,
-+   0x5DE1u, 0x5DE2u, 0x5DFDu, 0x5E28u, 0x5E3Du, 0x5E69u, 0x5E74u, 0x5EA6u,
-+   0x5EB0u, 0x5EB3u, 0x5EB6u, 0x5EC9u, 0x5ECAu, 0x5ED2u, 0x5ED3u, 0x5ED9u,
-+   0x5EECu, 0x5EFEu, 0x5F04u, 0x5F22u, 0x5F53u, 0x5F62u, 0x5F69u, 0x5F6Bu,
-+   0x5F8Bu, 0x5F9Au, 0x5FA9u, 0x5FADu, 0x5FCDu, 0x5FD7u, 0x5FF5u, 0x5FF9u,
-+   0x6012u, 0x601Cu, 0x6075u, 0x6081u, 0x6094u, 0x60C7u, 0x60D8u, 0x60E1u,
-+   0x6108u, 0x6144u, 0x6148u, 0x614Cu, 0x614Eu, 0x6160u, 0x6168u, 0x617Au,
-+   0x618Eu, 0x6190u, 0x61A4u, 0x61AFu, 0x61B2u, 0x61DEu, 0x61F2u, 0x61F6u,
-+   0x6200u, 0x6210u, 0x621Bu, 0x622Eu, 0x6234u, 0x625Du, 0x62B1u, 0x62C9u,
-+   0x62CFu, 0x62D3u, 0x62D4u, 0x62FCu, 0x62FEu, 0x633Du, 0x6350u, 0x6368u,
-+   0x637Bu, 0x6383u, 0x63A0u, 0x63A9u, 0x63C4u, 0x63C5u, 0x63E4u, 0x641Cu,
-+   0x6422u, 0x6452u, 0x6469u, 0x6477u, 0x647Eu, 0x649Au, 0x649Du, 0x64C4u,
-+   0x654Fu, 0x6556u, 0x656Cu, 0x6578u, 0x6599u, 0x65C5u, 0x65E2u, 0x65E3u,
-+   0x6613u, 0x6649u, 0x6674u, 0x6688u, 0x6691u, 0x669Cu, 0x66B4u, 0x66C6u,
-+   0x66F4u, 0x66F8u, 0x6700u, 0x6717u, 0x671Bu, 0x6721u, 0x674Eu, 0x6753u,
-+   0x6756u, 0x675Eu, 0x677Bu, 0x6785u, 0x6797u, 0x67F3u, 0x67FAu, 0x6817u,
-+   0x681Fu, 0x6852u, 0x6881u, 0x6885u, 0x688Eu, 0x68A8u, 0x6914u, 0x6942u,
-+   0x69A3u, 0x69EAu, 0x6A02u, 0x6A13u, 0x6AA8u, 0x6AD3u, 0x6ADBu, 0x6B04u,
-+   0x6B21u, 0x6B54u, 0x6B72u, 0x6B77u, 0x6B79u, 0x6B9Fu, 0x6BAEu, 0x6BBAu,
-+   0x6BBBu, 0x6C4Eu, 0x6C67u, 0x6C88u, 0x6CBFu, 0x6CCCu, 0x6CCDu, 0x6CE5u,
-+   0x6D16u, 0x6D1Bu, 0x6D1Eu, 0x6D34u, 0x6D3Eu, 0x6D41u, 0x6D69u, 0x6D6Au,
-+   0x6D77u, 0x6D78u, 0x6D85u, 0x6DCBu, 0x6DDAu, 0x6DEAu, 0x6DF9u, 0x6E1Au,
-+   0x6E2Fu, 0x6E6Eu, 0x6E9Cu, 0x6EBAu, 0x6EC7u, 0x6ECBu, 0x6ED1u, 0x6EDBu,
-+   0x6F0Fu, 0x6F22u, 0x6F23u, 0x6F6Eu, 0x6FC6u, 0x6FEBu, 0x6FFEu, 0x701Bu,
-+   0x701Eu, 0x7039u, 0x704Au, 0x7070u, 0x7077u, 0x707Du, 0x7099u, 0x70ADu,
-+   0x70C8u, 0x70D9u, 0x7145u, 0x7149u, 0x716Eu, 0x719Cu, 0x71CEu, 0x71D0u,
-+   0x7210u, 0x721Bu, 0x7228u, 0x722Bu, 0x7235u, 0x7250u, 0x7262u, 0x7280u,
-+   0x7295u, 0x72AFu, 0x72C0u, 0x72FCu, 0x732Au, 0x7375u, 0x737Au, 0x7387u,
-+   0x738Bu, 0x73A5u, 0x73B2u, 0x73DEu, 0x7406u, 0x7409u, 0x7422u, 0x7447u,
-+   0x745Cu, 0x7469u, 0x7471u, 0x7485u, 0x7489u, 0x7498u, 0x74CAu, 0x7506u,
-+   0x7524u, 0x753Bu, 0x753Eu, 0x7559u, 0x7565u, 0x7570u, 0x75E2u, 0x7610u,
-+   0x761Du, 0x761Fu, 0x7642u, 0x7669u, 0x76CAu, 0x76DBu, 0x76E7u, 0x76F4u,
-+   0x7701u, 0x771Eu, 0x771Fu, 0x7740u, 0x774Au, 0x778Bu, 0x77A7u, 0x784Eu,
-+   0x786Bu, 0x788Cu, 0x7891u, 0x78CAu, 0x78CCu, 0x78FBu, 0x792Au, 0x793Cu,
-+   0x793Eu, 0x7948u, 0x7949u, 0x7950u, 0x7956u, 0x795Du, 0x795Eu, 0x7965u,
-+   0x797Fu, 0x798Du, 0x798Eu, 0x798Fu, 0x79AEu, 0x79CAu, 0x79EBu, 0x7A1Cu,
-+   0x7A40u, 0x7A4Au, 0x7A4Fu, 0x7A81u, 0x7AB1u, 0x7ACBu, 0x7AEEu, 0x7B20u,
-+   0x7BC0u, 0x7BC6u, 0x7BC9u, 0x7C3Eu, 0x7C60u, 0x7C7Bu, 0x7C92u, 0x7CBEu,
-+   0x7CD2u, 0x7CD6u, 0x7CE3u, 0x7CE7u, 0x7CE8u, 0x7D00u, 0x7D10u, 0x7D22u,
-+   0x7D2Fu, 0x7D5Bu, 0x7D63u, 0x7DA0u, 0x7DBEu, 0x7DC7u, 0x7DF4u, 0x7E02u,
-+   0x7E09u, 0x7E37u, 0x7E41u, 0x7E45u, 0x7F3Eu, 0x7F72u, 0x7F79u, 0x7F7Au,
-+   0x7F85u, 0x7F95u, 0x7F9Au, 0x7FBDu, 0x7FFAu, 0x8001u, 0x8005u, 0x8046u,
-+   0x8060u, 0x806Fu, 0x8070u, 0x807Eu, 0x808Bu, 0x80ADu, 0x80B2u, 0x8103u,
-+   0x813Eu, 0x81D8u, 0x81E8u, 0x81EDu, 0x8201u, 0x8204u, 0x8218u, 0x826Fu,
-+   0x8279u, 0x828Bu, 0x8291u, 0x829Du, 0x82B1u, 0x82B3u, 0x82BDu, 0x82E5u,
-+   0x82E6u, 0x831Du, 0x8323u, 0x8336u, 0x8352u, 0x8353u, 0x8363u, 0x83ADu,
-+   0x83BDu, 0x83C9u, 0x83CAu, 0x83CCu, 0x83DCu, 0x83E7u, 0x83EFu, 0x83F1u,
-+   0x843Du, 0x8449u, 0x8457u, 0x84EEu, 0x84F1u, 0x84F3u, 0x84FCu, 0x8516u,
-+   0x8564u, 0x85CDu, 0x85FAu, 0x8606u, 0x8612u, 0x862Du, 0x863Fu, 0x8650u,
-+   0x865Cu, 0x8667u, 0x8669u, 0x8688u, 0x86A9u, 0x86E2u, 0x870Eu, 0x8728u,
-+   0x876Bu, 0x8779u, 0x8786u, 0x87BAu, 0x87E1u, 0x8801u, 0x881Fu, 0x884Cu,
-+   0x8860u, 0x8863u, 0x88C2u, 0x88CFu, 0x88D7u, 0x88DEu, 0x88E1u, 0x88F8u,
-+   0x88FAu, 0x8910u, 0x8941u, 0x8964u, 0x8986u, 0x898Bu, 0x8996u, 0x8AA0u,
-+   0x8AAAu, 0x8ABFu, 0x8ACBu, 0x8AD2u, 0x8AD6u, 0x8AEDu, 0x8AF8u, 0x8AFEu,
-+   0x8B01u, 0x8B39u, 0x8B58u, 0x8B80u, 0x8B8Au, 0x8C48u, 0x8C55u, 0x8CABu,
-+   0x8CC1u, 0x8CC2u, 0x8CC8u, 0x8CD3u, 0x8D08u, 0x8D1Bu, 0x8D77u, 0x8DBCu,
-+   0x8DCBu, 0x8DEFu, 0x8DF0u, 0x8ECAu, 0x8ED4u, 0x8F26u, 0x8F2Au, 0x8F38u,
-+   0x8F3Bu, 0x8F62u, 0x8F9Eu, 0x8FB0u, 0x8FB6u, 0x9023u, 0x9038u, 0x9072u,
-+   0x907Cu, 0x908Fu, 0x9094u, 0x90CEu, 0x90DEu, 0x90F1u, 0x90FDu, 0x9111u,
-+   0x911Bu, 0x916Au, 0x9199u, 0x91B4u, 0x91CCu, 0x91CFu, 0x91D1u, 0x9234u,
-+   0x9238u, 0x9276u, 0x927Cu, 0x92D7u, 0x92D8u, 0x9304u, 0x934Au, 0x93F9u,
-+   0x9415u, 0x958Bu, 0x95ADu, 0x95B7u, 0x962Eu, 0x964Bu, 0x964Du, 0x9675u,
-+   0x9678u, 0x967Cu, 0x9686u, 0x96A3u, 0x96B7u, 0x96B8u, 0x96C3u, 0x96E2u,
-+   0x96E3u, 0x96F6u, 0x96F7u, 0x9723u, 0x9732u, 0x9748u, 0x9756u, 0x97DBu,
-+   0x97E0u, 0x97FFu, 0x980Bu, 0x9818u, 0x9829u, 0x983Bu, 0x985Eu, 0x98E2u,
-+   0x98EFu, 0x98FCu, 0x9928u, 0x9929u, 0x99A7u, 0x99C2u, 0x99F1u, 0x99FEu,
-+   0x9A6Au, 0x9B12u, 0x9B6Fu, 0x9C40u, 0x9C57u, 0x9CFDu, 0x9D67u, 0x9DB4u,
-+   0x9DFAu, 0x9E1Eu, 0x9E7Fu, 0x9E97u, 0x9E9Fu, 0x9EBBu, 0x9ECEu, 0x9EF9u,
-+   0x9EFEu, 0x9F05u, 0x9F0Fu, 0x9F16u, 0x9F3Bu, 0x9F43u, 0x9F8Du, 0x9F8Eu,
-+   0x9F9Cu,0x20122u,0x2051Cu,0x20525u,0x2054Bu,0x2063Au,0x20804u,0x208DEu,
-+  0x20A2Cu,0x20B63u,0x214E4u,0x216A8u,0x216EAu,0x219C8u,0x21B18u,0x21D0Bu,
-+  0x21DE4u,0x21DE6u,0x22183u,0x2219Fu,0x22331u,0x226D4u,0x22844u,0x2284Au,
-+  0x22B0Cu,0x22BF1u,0x2300Au,0x232B8u,0x2335Fu,0x23393u,0x2339Cu,0x233C3u,
-+  0x233D5u,0x2346Du,0x236A3u,0x238A7u,0x23A8Du,0x23AFAu,0x23CBCu,0x23D1Eu,
-+  0x23ED1u,0x23F5Eu,0x23F8Eu,0x24263u,0x242EEu,0x243ABu,0x24608u,0x24735u,
-+  0x24814u,0x24C36u,0x24C92u,0x24FA1u,0x24FB8u,0x25044u,0x250F2u,0x250F3u,
-+  0x25119u,0x25133u,0x25249u,0x2541Du,0x25626u,0x2569Au,0x256C5u,0x2597Cu,
-+  0x25AA7u,0x25BABu,0x25C80u,0x25CD0u,0x25F86u,0x261DAu,0x26228u,0x26247u,
-+  0x262D9u,0x2633Eu,0x264DAu,0x26523u,0x265A8u,0x267A7u,0x267B5u,0x26B3Cu,
-+  0x26C36u,0x26CD5u,0x26D6Bu,0x26F2Cu,0x26FB1u,0x270D2u,0x273CAu,0x27667u,
-+  0x278AEu,0x27966u,0x27CA8u,0x27ED3u,0x27F2Fu,0x285D2u,0x285EDu,0x2872Eu,
-+  0x28BFAu,0x28D77u,0x29145u,0x291DFu,0x2921Au,0x2940Au,0x29496u,0x295B6u,
-+  0x29B30u,0x2A0CEu,0x2A105u,0x2A20Eu,0x2A291u,0x2A392u,0x2A600u,
-+};
-+static const uint64_t
-+_hb_ucd_dm2_map[1025] =
-+{
-+     HB_CODEPOINT_ENCODE3 (0x003Cu, 0x0338u, 0x226Eu),   HB_CODEPOINT_ENCODE3 (0x003Du, 0x0338u, 0x2260u),
-+     HB_CODEPOINT_ENCODE3 (0x003Eu, 0x0338u, 0x226Fu),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0300u, 0x00C0u),
-+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0301u, 0x00C1u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0302u, 0x00C2u),
-+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0303u, 0x00C3u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0304u, 0x0100u),
-+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0306u, 0x0102u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0307u, 0x0226u),
-+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0308u, 0x00C4u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0309u, 0x1EA2u),
-+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Au, 0x00C5u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Cu, 0x01CDu),
-+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Fu, 0x0200u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0311u, 0x0202u),
-+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0323u, 0x1EA0u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0325u, 0x1E00u),
-+     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0328u, 0x0104u),   HB_CODEPOINT_ENCODE3 (0x0042u, 0x0307u, 0x1E02u),
-+     HB_CODEPOINT_ENCODE3 (0x0042u, 0x0323u, 0x1E04u),   HB_CODEPOINT_ENCODE3 (0x0042u, 0x0331u, 0x1E06u),
-+     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0301u, 0x0106u),   HB_CODEPOINT_ENCODE3 (0x0043u, 0x0302u, 0x0108u),
-+     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0307u, 0x010Au),   HB_CODEPOINT_ENCODE3 (0x0043u, 0x030Cu, 0x010Cu),
-+     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0327u, 0x00C7u),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x0307u, 0x1E0Au),
-+     HB_CODEPOINT_ENCODE3 (0x0044u, 0x030Cu, 0x010Eu),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x0323u, 0x1E0Cu),
-+     HB_CODEPOINT_ENCODE3 (0x0044u, 0x0327u, 0x1E10u),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x032Du, 0x1E12u),
-+     HB_CODEPOINT_ENCODE3 (0x0044u, 0x0331u, 0x1E0Eu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0300u, 0x00C8u),
-+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0301u, 0x00C9u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0302u, 0x00CAu),
-+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0303u, 0x1EBCu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0304u, 0x0112u),
-+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0306u, 0x0114u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0307u, 0x0116u),
-+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0308u, 0x00CBu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0309u, 0x1EBAu),
-+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Cu, 0x011Au),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Fu, 0x0204u),
-+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0311u, 0x0206u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0323u, 0x1EB8u),
-+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0327u, 0x0228u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0328u, 0x0118u),
-+     HB_CODEPOINT_ENCODE3 (0x0045u, 0x032Du, 0x1E18u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0330u, 0x1E1Au),
-+     HB_CODEPOINT_ENCODE3 (0x0046u, 0x0307u, 0x1E1Eu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0301u, 0x01F4u),
-+     HB_CODEPOINT_ENCODE3 (0x0047u, 0x0302u, 0x011Cu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0304u, 0x1E20u),
-+     HB_CODEPOINT_ENCODE3 (0x0047u, 0x0306u, 0x011Eu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0307u, 0x0120u),
-+     HB_CODEPOINT_ENCODE3 (0x0047u, 0x030Cu, 0x01E6u),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0327u, 0x0122u),
-+     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0302u, 0x0124u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x0307u, 0x1E22u),
-+     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0308u, 0x1E26u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x030Cu, 0x021Eu),
-+     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0323u, 0x1E24u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x0327u, 0x1E28u),
-+     HB_CODEPOINT_ENCODE3 (0x0048u, 0x032Eu, 0x1E2Au),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0300u, 0x00CCu),
-+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0301u, 0x00CDu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0302u, 0x00CEu),
-+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0303u, 0x0128u),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0304u, 0x012Au),
-+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0306u, 0x012Cu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0307u, 0x0130u),
-+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0308u, 0x00CFu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0309u, 0x1EC8u),
-+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Cu, 0x01CFu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Fu, 0x0208u),
-+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0311u, 0x020Au),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0323u, 0x1ECAu),
-+     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0328u, 0x012Eu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0330u, 0x1E2Cu),
-+     HB_CODEPOINT_ENCODE3 (0x004Au, 0x0302u, 0x0134u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0301u, 0x1E30u),
-+     HB_CODEPOINT_ENCODE3 (0x004Bu, 0x030Cu, 0x01E8u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0323u, 0x1E32u),
-+     HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0327u, 0x0136u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0331u, 0x1E34u),
-+     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0301u, 0x0139u),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x030Cu, 0x013Du),
-+     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0323u, 0x1E36u),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0327u, 0x013Bu),
-+     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x032Du, 0x1E3Cu),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0331u, 0x1E3Au),
-+     HB_CODEPOINT_ENCODE3 (0x004Du, 0x0301u, 0x1E3Eu),   HB_CODEPOINT_ENCODE3 (0x004Du, 0x0307u, 0x1E40u),
-+     HB_CODEPOINT_ENCODE3 (0x004Du, 0x0323u, 0x1E42u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0300u, 0x01F8u),
-+     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0301u, 0x0143u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0303u, 0x00D1u),
-+     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0307u, 0x1E44u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x030Cu, 0x0147u),
-+     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0323u, 0x1E46u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0327u, 0x0145u),
-+     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x032Du, 0x1E4Au),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0331u, 0x1E48u),
-+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0300u, 0x00D2u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0301u, 0x00D3u),
-+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0302u, 0x00D4u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0303u, 0x00D5u),
-+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0304u, 0x014Cu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0306u, 0x014Eu),
-+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0307u, 0x022Eu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0308u, 0x00D6u),
-+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0309u, 0x1ECEu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Bu, 0x0150u),
-+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Cu, 0x01D1u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Fu, 0x020Cu),
-+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0311u, 0x020Eu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x031Bu, 0x01A0u),
-+     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0323u, 0x1ECCu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0328u, 0x01EAu),
-+     HB_CODEPOINT_ENCODE3 (0x0050u, 0x0301u, 0x1E54u),   HB_CODEPOINT_ENCODE3 (0x0050u, 0x0307u, 0x1E56u),
-+     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0301u, 0x0154u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0307u, 0x1E58u),
-+     HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Cu, 0x0158u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Fu, 0x0210u),
-+     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0311u, 0x0212u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0323u, 0x1E5Au),
-+     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0327u, 0x0156u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0331u, 0x1E5Eu),
-+     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0301u, 0x015Au),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x0302u, 0x015Cu),
-+     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0307u, 0x1E60u),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x030Cu, 0x0160u),
-+     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0323u, 0x1E62u),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x0326u, 0x0218u),
-+     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0327u, 0x015Eu),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0307u, 0x1E6Au),
-+     HB_CODEPOINT_ENCODE3 (0x0054u, 0x030Cu, 0x0164u),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0323u, 0x1E6Cu),
-+     HB_CODEPOINT_ENCODE3 (0x0054u, 0x0326u, 0x021Au),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0327u, 0x0162u),
-+     HB_CODEPOINT_ENCODE3 (0x0054u, 0x032Du, 0x1E70u),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0331u, 0x1E6Eu),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0300u, 0x00D9u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0301u, 0x00DAu),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0302u, 0x00DBu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0303u, 0x0168u),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0304u, 0x016Au),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0306u, 0x016Cu),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0308u, 0x00DCu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0309u, 0x1EE6u),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Au, 0x016Eu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Bu, 0x0170u),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Cu, 0x01D3u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Fu, 0x0214u),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0311u, 0x0216u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x031Bu, 0x01AFu),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0323u, 0x1EE4u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0324u, 0x1E72u),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0328u, 0x0172u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x032Du, 0x1E76u),
-+     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0330u, 0x1E74u),   HB_CODEPOINT_ENCODE3 (0x0056u, 0x0303u, 0x1E7Cu),
-+     HB_CODEPOINT_ENCODE3 (0x0056u, 0x0323u, 0x1E7Eu),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0300u, 0x1E80u),
-+     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0301u, 0x1E82u),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0302u, 0x0174u),
-+     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0307u, 0x1E86u),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0308u, 0x1E84u),
-+     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0323u, 0x1E88u),   HB_CODEPOINT_ENCODE3 (0x0058u, 0x0307u, 0x1E8Au),
-+     HB_CODEPOINT_ENCODE3 (0x0058u, 0x0308u, 0x1E8Cu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0300u, 0x1EF2u),
-+     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0301u, 0x00DDu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0302u, 0x0176u),
-+     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0303u, 0x1EF8u),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0304u, 0x0232u),
-+     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0307u, 0x1E8Eu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0308u, 0x0178u),
-+     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0309u, 0x1EF6u),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0323u, 0x1EF4u),
-+     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0301u, 0x0179u),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x0302u, 0x1E90u),
-+     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0307u, 0x017Bu),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x030Cu, 0x017Du),
-+     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0323u, 0x1E92u),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x0331u, 0x1E94u),
-+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0300u, 0x00E0u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0301u, 0x00E1u),
-+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0302u, 0x00E2u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0303u, 0x00E3u),
-+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0304u, 0x0101u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0306u, 0x0103u),
-+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0307u, 0x0227u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0308u, 0x00E4u),
-+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0309u, 0x1EA3u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Au, 0x00E5u),
-+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Cu, 0x01CEu),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Fu, 0x0201u),
-+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0311u, 0x0203u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0323u, 0x1EA1u),
-+     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0325u, 0x1E01u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0328u, 0x0105u),
-+     HB_CODEPOINT_ENCODE3 (0x0062u, 0x0307u, 0x1E03u),   HB_CODEPOINT_ENCODE3 (0x0062u, 0x0323u, 0x1E05u),
-+     HB_CODEPOINT_ENCODE3 (0x0062u, 0x0331u, 0x1E07u),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0301u, 0x0107u),
-+     HB_CODEPOINT_ENCODE3 (0x0063u, 0x0302u, 0x0109u),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0307u, 0x010Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0063u, 0x030Cu, 0x010Du),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0327u, 0x00E7u),
-+     HB_CODEPOINT_ENCODE3 (0x0064u, 0x0307u, 0x1E0Bu),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x030Cu, 0x010Fu),
-+     HB_CODEPOINT_ENCODE3 (0x0064u, 0x0323u, 0x1E0Du),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x0327u, 0x1E11u),
-+     HB_CODEPOINT_ENCODE3 (0x0064u, 0x032Du, 0x1E13u),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x0331u, 0x1E0Fu),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0300u, 0x00E8u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0301u, 0x00E9u),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0302u, 0x00EAu),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0303u, 0x1EBDu),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0304u, 0x0113u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0306u, 0x0115u),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0307u, 0x0117u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0308u, 0x00EBu),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0309u, 0x1EBBu),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Cu, 0x011Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Fu, 0x0205u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0311u, 0x0207u),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0323u, 0x1EB9u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0327u, 0x0229u),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0328u, 0x0119u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x032Du, 0x1E19u),
-+     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0330u, 0x1E1Bu),   HB_CODEPOINT_ENCODE3 (0x0066u, 0x0307u, 0x1E1Fu),
-+     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0301u, 0x01F5u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x0302u, 0x011Du),
-+     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0304u, 0x1E21u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x0306u, 0x011Fu),
-+     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0307u, 0x0121u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x030Cu, 0x01E7u),
-+     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0327u, 0x0123u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0302u, 0x0125u),
-+     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0307u, 0x1E23u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0308u, 0x1E27u),
-+     HB_CODEPOINT_ENCODE3 (0x0068u, 0x030Cu, 0x021Fu),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0323u, 0x1E25u),
-+     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0327u, 0x1E29u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x032Eu, 0x1E2Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0331u, 0x1E96u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0300u, 0x00ECu),
-+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0301u, 0x00EDu),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0302u, 0x00EEu),
-+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0303u, 0x0129u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0304u, 0x012Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0306u, 0x012Du),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0308u, 0x00EFu),
-+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0309u, 0x1EC9u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Cu, 0x01D0u),
-+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Fu, 0x0209u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0311u, 0x020Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0323u, 0x1ECBu),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0328u, 0x012Fu),
-+     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0330u, 0x1E2Du),   HB_CODEPOINT_ENCODE3 (0x006Au, 0x0302u, 0x0135u),
-+     HB_CODEPOINT_ENCODE3 (0x006Au, 0x030Cu, 0x01F0u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0301u, 0x1E31u),
-+     HB_CODEPOINT_ENCODE3 (0x006Bu, 0x030Cu, 0x01E9u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0323u, 0x1E33u),
-+     HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0327u, 0x0137u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0331u, 0x1E35u),
-+     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0301u, 0x013Au),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x030Cu, 0x013Eu),
-+     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0323u, 0x1E37u),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0327u, 0x013Cu),
-+     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x032Du, 0x1E3Du),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0331u, 0x1E3Bu),
-+     HB_CODEPOINT_ENCODE3 (0x006Du, 0x0301u, 0x1E3Fu),   HB_CODEPOINT_ENCODE3 (0x006Du, 0x0307u, 0x1E41u),
-+     HB_CODEPOINT_ENCODE3 (0x006Du, 0x0323u, 0x1E43u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0300u, 0x01F9u),
-+     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0301u, 0x0144u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0303u, 0x00F1u),
-+     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0307u, 0x1E45u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x030Cu, 0x0148u),
-+     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0323u, 0x1E47u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0327u, 0x0146u),
-+     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x032Du, 0x1E4Bu),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0331u, 0x1E49u),
-+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0300u, 0x00F2u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0301u, 0x00F3u),
-+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0302u, 0x00F4u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0303u, 0x00F5u),
-+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0304u, 0x014Du),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0306u, 0x014Fu),
-+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0307u, 0x022Fu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0308u, 0x00F6u),
-+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0309u, 0x1ECFu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Bu, 0x0151u),
-+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Cu, 0x01D2u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Fu, 0x020Du),
-+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0311u, 0x020Fu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x031Bu, 0x01A1u),
-+     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0323u, 0x1ECDu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0328u, 0x01EBu),
-+     HB_CODEPOINT_ENCODE3 (0x0070u, 0x0301u, 0x1E55u),   HB_CODEPOINT_ENCODE3 (0x0070u, 0x0307u, 0x1E57u),
-+     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0301u, 0x0155u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0307u, 0x1E59u),
-+     HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Cu, 0x0159u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Fu, 0x0211u),
-+     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0311u, 0x0213u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0323u, 0x1E5Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0327u, 0x0157u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0331u, 0x1E5Fu),
-+     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0301u, 0x015Bu),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x0302u, 0x015Du),
-+     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0307u, 0x1E61u),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x030Cu, 0x0161u),
-+     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0323u, 0x1E63u),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x0326u, 0x0219u),
-+     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0327u, 0x015Fu),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x0307u, 0x1E6Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0308u, 0x1E97u),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x030Cu, 0x0165u),
-+     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0323u, 0x1E6Du),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x0326u, 0x021Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0327u, 0x0163u),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x032Du, 0x1E71u),
-+     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0331u, 0x1E6Fu),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0300u, 0x00F9u),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0301u, 0x00FAu),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0302u, 0x00FBu),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0303u, 0x0169u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0304u, 0x016Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0306u, 0x016Du),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0308u, 0x00FCu),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0309u, 0x1EE7u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Au, 0x016Fu),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Bu, 0x0171u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Cu, 0x01D4u),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Fu, 0x0215u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0311u, 0x0217u),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x031Bu, 0x01B0u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0323u, 0x1EE5u),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0324u, 0x1E73u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0328u, 0x0173u),
-+     HB_CODEPOINT_ENCODE3 (0x0075u, 0x032Du, 0x1E77u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0330u, 0x1E75u),
-+     HB_CODEPOINT_ENCODE3 (0x0076u, 0x0303u, 0x1E7Du),   HB_CODEPOINT_ENCODE3 (0x0076u, 0x0323u, 0x1E7Fu),
-+     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0300u, 0x1E81u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x0301u, 0x1E83u),
-+     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0302u, 0x0175u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x0307u, 0x1E87u),
-+     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0308u, 0x1E85u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x030Au, 0x1E98u),
-+     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0323u, 0x1E89u),   HB_CODEPOINT_ENCODE3 (0x0078u, 0x0307u, 0x1E8Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0078u, 0x0308u, 0x1E8Du),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0300u, 0x1EF3u),
-+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0301u, 0x00FDu),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0302u, 0x0177u),
-+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0303u, 0x1EF9u),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0304u, 0x0233u),
-+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0307u, 0x1E8Fu),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0308u, 0x00FFu),
-+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0309u, 0x1EF7u),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x030Au, 0x1E99u),
-+     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0323u, 0x1EF5u),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0301u, 0x017Au),
-+     HB_CODEPOINT_ENCODE3 (0x007Au, 0x0302u, 0x1E91u),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0307u, 0x017Cu),
-+     HB_CODEPOINT_ENCODE3 (0x007Au, 0x030Cu, 0x017Eu),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0323u, 0x1E93u),
-+     HB_CODEPOINT_ENCODE3 (0x007Au, 0x0331u, 0x1E95u),   HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0300u, 0x1FEDu),
-+     HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0301u, 0x0385u),   HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0342u, 0x1FC1u),
-+     HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0300u, 0x1EA6u),   HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0301u, 0x1EA4u),
-+     HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0303u, 0x1EAAu),   HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0309u, 0x1EA8u),
-+     HB_CODEPOINT_ENCODE3 (0x00C4u, 0x0304u, 0x01DEu),   HB_CODEPOINT_ENCODE3 (0x00C5u, 0x0301u, 0x01FAu),
-+     HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0301u, 0x01FCu),   HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0304u, 0x01E2u),
-+     HB_CODEPOINT_ENCODE3 (0x00C7u, 0x0301u, 0x1E08u),   HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0300u, 0x1EC0u),
-+     HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0301u, 0x1EBEu),   HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0303u, 0x1EC4u),
-+     HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0309u, 0x1EC2u),   HB_CODEPOINT_ENCODE3 (0x00CFu, 0x0301u, 0x1E2Eu),
-+     HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0300u, 0x1ED2u),   HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0301u, 0x1ED0u),
-+     HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0303u, 0x1ED6u),   HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0309u, 0x1ED4u),
-+     HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0301u, 0x1E4Cu),   HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0304u, 0x022Cu),
-+     HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0308u, 0x1E4Eu),   HB_CODEPOINT_ENCODE3 (0x00D6u, 0x0304u, 0x022Au),
-+     HB_CODEPOINT_ENCODE3 (0x00D8u, 0x0301u, 0x01FEu),   HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0300u, 0x01DBu),
-+     HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0301u, 0x01D7u),   HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0304u, 0x01D5u),
-+     HB_CODEPOINT_ENCODE3 (0x00DCu, 0x030Cu, 0x01D9u),   HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0300u, 0x1EA7u),
-+     HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0301u, 0x1EA5u),   HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0303u, 0x1EABu),
-+     HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0309u, 0x1EA9u),   HB_CODEPOINT_ENCODE3 (0x00E4u, 0x0304u, 0x01DFu),
-+     HB_CODEPOINT_ENCODE3 (0x00E5u, 0x0301u, 0x01FBu),   HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0301u, 0x01FDu),
-+     HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0304u, 0x01E3u),   HB_CODEPOINT_ENCODE3 (0x00E7u, 0x0301u, 0x1E09u),
-+     HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0300u, 0x1EC1u),   HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0301u, 0x1EBFu),
-+     HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0303u, 0x1EC5u),   HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0309u, 0x1EC3u),
-+     HB_CODEPOINT_ENCODE3 (0x00EFu, 0x0301u, 0x1E2Fu),   HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0300u, 0x1ED3u),
-+     HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0301u, 0x1ED1u),   HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0303u, 0x1ED7u),
-+     HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0309u, 0x1ED5u),   HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0301u, 0x1E4Du),
-+     HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0304u, 0x022Du),   HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0308u, 0x1E4Fu),
-+     HB_CODEPOINT_ENCODE3 (0x00F6u, 0x0304u, 0x022Bu),   HB_CODEPOINT_ENCODE3 (0x00F8u, 0x0301u, 0x01FFu),
-+     HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0300u, 0x01DCu),   HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0301u, 0x01D8u),
-+     HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0304u, 0x01D6u),   HB_CODEPOINT_ENCODE3 (0x00FCu, 0x030Cu, 0x01DAu),
-+     HB_CODEPOINT_ENCODE3 (0x0102u, 0x0300u, 0x1EB0u),   HB_CODEPOINT_ENCODE3 (0x0102u, 0x0301u, 0x1EAEu),
-+     HB_CODEPOINT_ENCODE3 (0x0102u, 0x0303u, 0x1EB4u),   HB_CODEPOINT_ENCODE3 (0x0102u, 0x0309u, 0x1EB2u),
-+     HB_CODEPOINT_ENCODE3 (0x0103u, 0x0300u, 0x1EB1u),   HB_CODEPOINT_ENCODE3 (0x0103u, 0x0301u, 0x1EAFu),
-+     HB_CODEPOINT_ENCODE3 (0x0103u, 0x0303u, 0x1EB5u),   HB_CODEPOINT_ENCODE3 (0x0103u, 0x0309u, 0x1EB3u),
-+     HB_CODEPOINT_ENCODE3 (0x0112u, 0x0300u, 0x1E14u),   HB_CODEPOINT_ENCODE3 (0x0112u, 0x0301u, 0x1E16u),
-+     HB_CODEPOINT_ENCODE3 (0x0113u, 0x0300u, 0x1E15u),   HB_CODEPOINT_ENCODE3 (0x0113u, 0x0301u, 0x1E17u),
-+     HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0300u, 0x1E50u),   HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0301u, 0x1E52u),
-+     HB_CODEPOINT_ENCODE3 (0x014Du, 0x0300u, 0x1E51u),   HB_CODEPOINT_ENCODE3 (0x014Du, 0x0301u, 0x1E53u),
-+     HB_CODEPOINT_ENCODE3 (0x015Au, 0x0307u, 0x1E64u),   HB_CODEPOINT_ENCODE3 (0x015Bu, 0x0307u, 0x1E65u),
-+     HB_CODEPOINT_ENCODE3 (0x0160u, 0x0307u, 0x1E66u),   HB_CODEPOINT_ENCODE3 (0x0161u, 0x0307u, 0x1E67u),
-+     HB_CODEPOINT_ENCODE3 (0x0168u, 0x0301u, 0x1E78u),   HB_CODEPOINT_ENCODE3 (0x0169u, 0x0301u, 0x1E79u),
-+     HB_CODEPOINT_ENCODE3 (0x016Au, 0x0308u, 0x1E7Au),   HB_CODEPOINT_ENCODE3 (0x016Bu, 0x0308u, 0x1E7Bu),
-+     HB_CODEPOINT_ENCODE3 (0x017Fu, 0x0307u, 0x1E9Bu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0300u, 0x1EDCu),
-+     HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0301u, 0x1EDAu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0303u, 0x1EE0u),
-+     HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0309u, 0x1EDEu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0323u, 0x1EE2u),
-+     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0300u, 0x1EDDu),   HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0301u, 0x1EDBu),
-+     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0303u, 0x1EE1u),   HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0309u, 0x1EDFu),
-+     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0323u, 0x1EE3u),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0300u, 0x1EEAu),
-+     HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0301u, 0x1EE8u),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0303u, 0x1EEEu),
-+     HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0309u, 0x1EECu),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0323u, 0x1EF0u),
-+     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0300u, 0x1EEBu),   HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0301u, 0x1EE9u),
-+     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0303u, 0x1EEFu),   HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0309u, 0x1EEDu),
-+     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0323u, 0x1EF1u),   HB_CODEPOINT_ENCODE3 (0x01B7u, 0x030Cu, 0x01EEu),
-+     HB_CODEPOINT_ENCODE3 (0x01EAu, 0x0304u, 0x01ECu),   HB_CODEPOINT_ENCODE3 (0x01EBu, 0x0304u, 0x01EDu),
-+     HB_CODEPOINT_ENCODE3 (0x0226u, 0x0304u, 0x01E0u),   HB_CODEPOINT_ENCODE3 (0x0227u, 0x0304u, 0x01E1u),
-+     HB_CODEPOINT_ENCODE3 (0x0228u, 0x0306u, 0x1E1Cu),   HB_CODEPOINT_ENCODE3 (0x0229u, 0x0306u, 0x1E1Du),
-+     HB_CODEPOINT_ENCODE3 (0x022Eu, 0x0304u, 0x0230u),   HB_CODEPOINT_ENCODE3 (0x022Fu, 0x0304u, 0x0231u),
-+     HB_CODEPOINT_ENCODE3 (0x0292u, 0x030Cu, 0x01EFu),   HB_CODEPOINT_ENCODE3 (0x0308u, 0x0301u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0300u, 0x1FBAu),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0301u, 0x0386u),
-+     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0304u, 0x1FB9u),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0306u, 0x1FB8u),
-+     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0313u, 0x1F08u),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0314u, 0x1F09u),
-+     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0345u, 0x1FBCu),   HB_CODEPOINT_ENCODE3 (0x0395u, 0x0300u, 0x1FC8u),
-+     HB_CODEPOINT_ENCODE3 (0x0395u, 0x0301u, 0x0388u),   HB_CODEPOINT_ENCODE3 (0x0395u, 0x0313u, 0x1F18u),
-+     HB_CODEPOINT_ENCODE3 (0x0395u, 0x0314u, 0x1F19u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0300u, 0x1FCAu),
-+     HB_CODEPOINT_ENCODE3 (0x0397u, 0x0301u, 0x0389u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0313u, 0x1F28u),
-+     HB_CODEPOINT_ENCODE3 (0x0397u, 0x0314u, 0x1F29u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0345u, 0x1FCCu),
-+     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0300u, 0x1FDAu),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0301u, 0x038Au),
-+     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0304u, 0x1FD9u),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0306u, 0x1FD8u),
-+     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0308u, 0x03AAu),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0313u, 0x1F38u),
-+     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0314u, 0x1F39u),   HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0300u, 0x1FF8u),
-+     HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0301u, 0x038Cu),   HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0313u, 0x1F48u),
-+     HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0314u, 0x1F49u),   HB_CODEPOINT_ENCODE3 (0x03A1u, 0x0314u, 0x1FECu),
-+     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0300u, 0x1FEAu),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0301u, 0x038Eu),
-+     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0304u, 0x1FE9u),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0306u, 0x1FE8u),
-+     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0308u, 0x03ABu),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0314u, 0x1F59u),
-+     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0300u, 0x1FFAu),   HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0301u, 0x038Fu),
-+     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0313u, 0x1F68u),   HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0314u, 0x1F69u),
-+     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0345u, 0x1FFCu),   HB_CODEPOINT_ENCODE3 (0x03ACu, 0x0345u, 0x1FB4u),
-+     HB_CODEPOINT_ENCODE3 (0x03AEu, 0x0345u, 0x1FC4u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0300u, 0x1F70u),
-+     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0301u, 0x03ACu),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0304u, 0x1FB1u),
-+     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0306u, 0x1FB0u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0313u, 0x1F00u),
-+     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0314u, 0x1F01u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0342u, 0x1FB6u),
-+     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0345u, 0x1FB3u),   HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0300u, 0x1F72u),
-+     HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0301u, 0x03ADu),   HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0313u, 0x1F10u),
-+     HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0314u, 0x1F11u),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0300u, 0x1F74u),
-+     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0301u, 0x03AEu),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0313u, 0x1F20u),
-+     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0314u, 0x1F21u),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0342u, 0x1FC6u),
-+     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0345u, 0x1FC3u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0300u, 0x1F76u),
-+     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0301u, 0x03AFu),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0304u, 0x1FD1u),
-+     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0306u, 0x1FD0u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0308u, 0x03CAu),
-+     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0313u, 0x1F30u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0314u, 0x1F31u),
-+     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0342u, 0x1FD6u),   HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0300u, 0x1F78u),
-+     HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0301u, 0x03CCu),   HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0313u, 0x1F40u),
-+     HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0314u, 0x1F41u),   HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0313u, 0x1FE4u),
-+     HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0314u, 0x1FE5u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0300u, 0x1F7Au),
-+     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0301u, 0x03CDu),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0304u, 0x1FE1u),
-+     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0306u, 0x1FE0u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0308u, 0x03CBu),
-+     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0313u, 0x1F50u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0314u, 0x1F51u),
-+     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0342u, 0x1FE6u),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0300u, 0x1F7Cu),
-+     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0301u, 0x03CEu),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0313u, 0x1F60u),
-+     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0314u, 0x1F61u),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0342u, 0x1FF6u),
-+     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0345u, 0x1FF3u),   HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0300u, 0x1FD2u),
-+     HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0301u, 0x0390u),   HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0342u, 0x1FD7u),
-+     HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0300u, 0x1FE2u),   HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0301u, 0x03B0u),
-+     HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0342u, 0x1FE7u),   HB_CODEPOINT_ENCODE3 (0x03CEu, 0x0345u, 0x1FF4u),
-+     HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0301u, 0x03D3u),   HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0308u, 0x03D4u),
-+     HB_CODEPOINT_ENCODE3 (0x0406u, 0x0308u, 0x0407u),   HB_CODEPOINT_ENCODE3 (0x0410u, 0x0306u, 0x04D0u),
-+     HB_CODEPOINT_ENCODE3 (0x0410u, 0x0308u, 0x04D2u),   HB_CODEPOINT_ENCODE3 (0x0413u, 0x0301u, 0x0403u),
-+     HB_CODEPOINT_ENCODE3 (0x0415u, 0x0300u, 0x0400u),   HB_CODEPOINT_ENCODE3 (0x0415u, 0x0306u, 0x04D6u),
-+     HB_CODEPOINT_ENCODE3 (0x0415u, 0x0308u, 0x0401u),   HB_CODEPOINT_ENCODE3 (0x0416u, 0x0306u, 0x04C1u),
-+     HB_CODEPOINT_ENCODE3 (0x0416u, 0x0308u, 0x04DCu),   HB_CODEPOINT_ENCODE3 (0x0417u, 0x0308u, 0x04DEu),
-+     HB_CODEPOINT_ENCODE3 (0x0418u, 0x0300u, 0x040Du),   HB_CODEPOINT_ENCODE3 (0x0418u, 0x0304u, 0x04E2u),
-+     HB_CODEPOINT_ENCODE3 (0x0418u, 0x0306u, 0x0419u),   HB_CODEPOINT_ENCODE3 (0x0418u, 0x0308u, 0x04E4u),
-+     HB_CODEPOINT_ENCODE3 (0x041Au, 0x0301u, 0x040Cu),   HB_CODEPOINT_ENCODE3 (0x041Eu, 0x0308u, 0x04E6u),
-+     HB_CODEPOINT_ENCODE3 (0x0423u, 0x0304u, 0x04EEu),   HB_CODEPOINT_ENCODE3 (0x0423u, 0x0306u, 0x040Eu),
-+     HB_CODEPOINT_ENCODE3 (0x0423u, 0x0308u, 0x04F0u),   HB_CODEPOINT_ENCODE3 (0x0423u, 0x030Bu, 0x04F2u),
-+     HB_CODEPOINT_ENCODE3 (0x0427u, 0x0308u, 0x04F4u),   HB_CODEPOINT_ENCODE3 (0x042Bu, 0x0308u, 0x04F8u),
-+     HB_CODEPOINT_ENCODE3 (0x042Du, 0x0308u, 0x04ECu),   HB_CODEPOINT_ENCODE3 (0x0430u, 0x0306u, 0x04D1u),
-+     HB_CODEPOINT_ENCODE3 (0x0430u, 0x0308u, 0x04D3u),   HB_CODEPOINT_ENCODE3 (0x0433u, 0x0301u, 0x0453u),
-+     HB_CODEPOINT_ENCODE3 (0x0435u, 0x0300u, 0x0450u),   HB_CODEPOINT_ENCODE3 (0x0435u, 0x0306u, 0x04D7u),
-+     HB_CODEPOINT_ENCODE3 (0x0435u, 0x0308u, 0x0451u),   HB_CODEPOINT_ENCODE3 (0x0436u, 0x0306u, 0x04C2u),
-+     HB_CODEPOINT_ENCODE3 (0x0436u, 0x0308u, 0x04DDu),   HB_CODEPOINT_ENCODE3 (0x0437u, 0x0308u, 0x04DFu),
-+     HB_CODEPOINT_ENCODE3 (0x0438u, 0x0300u, 0x045Du),   HB_CODEPOINT_ENCODE3 (0x0438u, 0x0304u, 0x04E3u),
-+     HB_CODEPOINT_ENCODE3 (0x0438u, 0x0306u, 0x0439u),   HB_CODEPOINT_ENCODE3 (0x0438u, 0x0308u, 0x04E5u),
-+     HB_CODEPOINT_ENCODE3 (0x043Au, 0x0301u, 0x045Cu),   HB_CODEPOINT_ENCODE3 (0x043Eu, 0x0308u, 0x04E7u),
-+     HB_CODEPOINT_ENCODE3 (0x0443u, 0x0304u, 0x04EFu),   HB_CODEPOINT_ENCODE3 (0x0443u, 0x0306u, 0x045Eu),
-+     HB_CODEPOINT_ENCODE3 (0x0443u, 0x0308u, 0x04F1u),   HB_CODEPOINT_ENCODE3 (0x0443u, 0x030Bu, 0x04F3u),
-+     HB_CODEPOINT_ENCODE3 (0x0447u, 0x0308u, 0x04F5u),   HB_CODEPOINT_ENCODE3 (0x044Bu, 0x0308u, 0x04F9u),
-+     HB_CODEPOINT_ENCODE3 (0x044Du, 0x0308u, 0x04EDu),   HB_CODEPOINT_ENCODE3 (0x0456u, 0x0308u, 0x0457u),
-+     HB_CODEPOINT_ENCODE3 (0x0474u, 0x030Fu, 0x0476u),   HB_CODEPOINT_ENCODE3 (0x0475u, 0x030Fu, 0x0477u),
-+     HB_CODEPOINT_ENCODE3 (0x04D8u, 0x0308u, 0x04DAu),   HB_CODEPOINT_ENCODE3 (0x04D9u, 0x0308u, 0x04DBu),
-+     HB_CODEPOINT_ENCODE3 (0x04E8u, 0x0308u, 0x04EAu),   HB_CODEPOINT_ENCODE3 (0x04E9u, 0x0308u, 0x04EBu),
-+     HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BFu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D2u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05D3u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D4u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05B9u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05D6u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D8u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05B4u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05DAu, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05DBu, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05DBu, 0x05BFu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05DCu, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05DEu, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E0u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05E1u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E3u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05E4u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E4u, 0x05BFu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05E6u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E7u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05E8u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05C1u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05E9u, 0x05C2u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x05EAu, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05F2u, 0x05B7u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0627u, 0x0653u, 0x0622u),   HB_CODEPOINT_ENCODE3 (0x0627u, 0x0654u, 0x0623u),
-+     HB_CODEPOINT_ENCODE3 (0x0627u, 0x0655u, 0x0625u),   HB_CODEPOINT_ENCODE3 (0x0648u, 0x0654u, 0x0624u),
-+     HB_CODEPOINT_ENCODE3 (0x064Au, 0x0654u, 0x0626u),   HB_CODEPOINT_ENCODE3 (0x06C1u, 0x0654u, 0x06C2u),
-+     HB_CODEPOINT_ENCODE3 (0x06D2u, 0x0654u, 0x06D3u),   HB_CODEPOINT_ENCODE3 (0x06D5u, 0x0654u, 0x06C0u),
-+     HB_CODEPOINT_ENCODE3 (0x0915u, 0x093Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0916u, 0x093Cu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0917u, 0x093Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x091Cu, 0x093Cu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0921u, 0x093Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0922u, 0x093Cu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0928u, 0x093Cu, 0x0929u),   HB_CODEPOINT_ENCODE3 (0x092Bu, 0x093Cu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x092Fu, 0x093Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0930u, 0x093Cu, 0x0931u),
-+     HB_CODEPOINT_ENCODE3 (0x0933u, 0x093Cu, 0x0934u),   HB_CODEPOINT_ENCODE3 (0x09A1u, 0x09BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x09A2u, 0x09BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x09AFu, 0x09BCu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x09C7u, 0x09BEu, 0x09CBu),   HB_CODEPOINT_ENCODE3 (0x09C7u, 0x09D7u, 0x09CCu),
-+     HB_CODEPOINT_ENCODE3 (0x0A16u, 0x0A3Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0A17u, 0x0A3Cu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0A1Cu, 0x0A3Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0A2Bu, 0x0A3Cu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0A32u, 0x0A3Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0A38u, 0x0A3Cu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0B21u, 0x0B3Cu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0B22u, 0x0B3Cu, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B3Eu, 0x0B4Bu),   HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B56u, 0x0B48u),
-+     HB_CODEPOINT_ENCODE3 (0x0B47u, 0x0B57u, 0x0B4Cu),   HB_CODEPOINT_ENCODE3 (0x0B92u, 0x0BD7u, 0x0B94u),
-+     HB_CODEPOINT_ENCODE3 (0x0BC6u, 0x0BBEu, 0x0BCAu),   HB_CODEPOINT_ENCODE3 (0x0BC6u, 0x0BD7u, 0x0BCCu),
-+     HB_CODEPOINT_ENCODE3 (0x0BC7u, 0x0BBEu, 0x0BCBu),   HB_CODEPOINT_ENCODE3 (0x0C46u, 0x0C56u, 0x0C48u),
-+     HB_CODEPOINT_ENCODE3 (0x0CBFu, 0x0CD5u, 0x0CC0u),   HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CC2u, 0x0CCAu),
-+     HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CD5u, 0x0CC7u),   HB_CODEPOINT_ENCODE3 (0x0CC6u, 0x0CD6u, 0x0CC8u),
-+     HB_CODEPOINT_ENCODE3 (0x0CCAu, 0x0CD5u, 0x0CCBu),   HB_CODEPOINT_ENCODE3 (0x0D46u, 0x0D3Eu, 0x0D4Au),
-+     HB_CODEPOINT_ENCODE3 (0x0D46u, 0x0D57u, 0x0D4Cu),   HB_CODEPOINT_ENCODE3 (0x0D47u, 0x0D3Eu, 0x0D4Bu),
-+     HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DCAu, 0x0DDAu),   HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DCFu, 0x0DDCu),
-+     HB_CODEPOINT_ENCODE3 (0x0DD9u, 0x0DDFu, 0x0DDEu),   HB_CODEPOINT_ENCODE3 (0x0DDCu, 0x0DCAu, 0x0DDDu),
-+     HB_CODEPOINT_ENCODE3 (0x0F40u, 0x0FB5u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F42u, 0x0FB7u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0F4Cu, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F51u, 0x0FB7u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0F56u, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F5Bu, 0x0FB7u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F72u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F74u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0F71u, 0x0F80u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F90u, 0x0FB5u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0F92u, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0F9Cu, 0x0FB7u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0FA1u, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0FA6u, 0x0FB7u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0FABu, 0x0FB7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x0FB2u, 0x0F80u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x0FB3u, 0x0F80u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x1025u, 0x102Eu, 0x1026u),
-+     HB_CODEPOINT_ENCODE3 (0x1B05u, 0x1B35u, 0x1B06u),   HB_CODEPOINT_ENCODE3 (0x1B07u, 0x1B35u, 0x1B08u),
-+     HB_CODEPOINT_ENCODE3 (0x1B09u, 0x1B35u, 0x1B0Au),   HB_CODEPOINT_ENCODE3 (0x1B0Bu, 0x1B35u, 0x1B0Cu),
-+     HB_CODEPOINT_ENCODE3 (0x1B0Du, 0x1B35u, 0x1B0Eu),   HB_CODEPOINT_ENCODE3 (0x1B11u, 0x1B35u, 0x1B12u),
-+     HB_CODEPOINT_ENCODE3 (0x1B3Au, 0x1B35u, 0x1B3Bu),   HB_CODEPOINT_ENCODE3 (0x1B3Cu, 0x1B35u, 0x1B3Du),
-+     HB_CODEPOINT_ENCODE3 (0x1B3Eu, 0x1B35u, 0x1B40u),   HB_CODEPOINT_ENCODE3 (0x1B3Fu, 0x1B35u, 0x1B41u),
-+     HB_CODEPOINT_ENCODE3 (0x1B42u, 0x1B35u, 0x1B43u),   HB_CODEPOINT_ENCODE3 (0x1E36u, 0x0304u, 0x1E38u),
-+     HB_CODEPOINT_ENCODE3 (0x1E37u, 0x0304u, 0x1E39u),   HB_CODEPOINT_ENCODE3 (0x1E5Au, 0x0304u, 0x1E5Cu),
-+     HB_CODEPOINT_ENCODE3 (0x1E5Bu, 0x0304u, 0x1E5Du),   HB_CODEPOINT_ENCODE3 (0x1E62u, 0x0307u, 0x1E68u),
-+     HB_CODEPOINT_ENCODE3 (0x1E63u, 0x0307u, 0x1E69u),   HB_CODEPOINT_ENCODE3 (0x1EA0u, 0x0302u, 0x1EACu),
-+     HB_CODEPOINT_ENCODE3 (0x1EA0u, 0x0306u, 0x1EB6u),   HB_CODEPOINT_ENCODE3 (0x1EA1u, 0x0302u, 0x1EADu),
-+     HB_CODEPOINT_ENCODE3 (0x1EA1u, 0x0306u, 0x1EB7u),   HB_CODEPOINT_ENCODE3 (0x1EB8u, 0x0302u, 0x1EC6u),
-+     HB_CODEPOINT_ENCODE3 (0x1EB9u, 0x0302u, 0x1EC7u),   HB_CODEPOINT_ENCODE3 (0x1ECCu, 0x0302u, 0x1ED8u),
-+     HB_CODEPOINT_ENCODE3 (0x1ECDu, 0x0302u, 0x1ED9u),   HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0300u, 0x1F02u),
-+     HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0301u, 0x1F04u),   HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0342u, 0x1F06u),
-+     HB_CODEPOINT_ENCODE3 (0x1F00u, 0x0345u, 0x1F80u),   HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0300u, 0x1F03u),
-+     HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0301u, 0x1F05u),   HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0342u, 0x1F07u),
-+     HB_CODEPOINT_ENCODE3 (0x1F01u, 0x0345u, 0x1F81u),   HB_CODEPOINT_ENCODE3 (0x1F02u, 0x0345u, 0x1F82u),
-+     HB_CODEPOINT_ENCODE3 (0x1F03u, 0x0345u, 0x1F83u),   HB_CODEPOINT_ENCODE3 (0x1F04u, 0x0345u, 0x1F84u),
-+     HB_CODEPOINT_ENCODE3 (0x1F05u, 0x0345u, 0x1F85u),   HB_CODEPOINT_ENCODE3 (0x1F06u, 0x0345u, 0x1F86u),
-+     HB_CODEPOINT_ENCODE3 (0x1F07u, 0x0345u, 0x1F87u),   HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0300u, 0x1F0Au),
-+     HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0301u, 0x1F0Cu),   HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0342u, 0x1F0Eu),
-+     HB_CODEPOINT_ENCODE3 (0x1F08u, 0x0345u, 0x1F88u),   HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0300u, 0x1F0Bu),
-+     HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0301u, 0x1F0Du),   HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0342u, 0x1F0Fu),
-+     HB_CODEPOINT_ENCODE3 (0x1F09u, 0x0345u, 0x1F89u),   HB_CODEPOINT_ENCODE3 (0x1F0Au, 0x0345u, 0x1F8Au),
-+     HB_CODEPOINT_ENCODE3 (0x1F0Bu, 0x0345u, 0x1F8Bu),   HB_CODEPOINT_ENCODE3 (0x1F0Cu, 0x0345u, 0x1F8Cu),
-+     HB_CODEPOINT_ENCODE3 (0x1F0Du, 0x0345u, 0x1F8Du),   HB_CODEPOINT_ENCODE3 (0x1F0Eu, 0x0345u, 0x1F8Eu),
-+     HB_CODEPOINT_ENCODE3 (0x1F0Fu, 0x0345u, 0x1F8Fu),   HB_CODEPOINT_ENCODE3 (0x1F10u, 0x0300u, 0x1F12u),
-+     HB_CODEPOINT_ENCODE3 (0x1F10u, 0x0301u, 0x1F14u),   HB_CODEPOINT_ENCODE3 (0x1F11u, 0x0300u, 0x1F13u),
-+     HB_CODEPOINT_ENCODE3 (0x1F11u, 0x0301u, 0x1F15u),   HB_CODEPOINT_ENCODE3 (0x1F18u, 0x0300u, 0x1F1Au),
-+     HB_CODEPOINT_ENCODE3 (0x1F18u, 0x0301u, 0x1F1Cu),   HB_CODEPOINT_ENCODE3 (0x1F19u, 0x0300u, 0x1F1Bu),
-+     HB_CODEPOINT_ENCODE3 (0x1F19u, 0x0301u, 0x1F1Du),   HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0300u, 0x1F22u),
-+     HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0301u, 0x1F24u),   HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0342u, 0x1F26u),
-+     HB_CODEPOINT_ENCODE3 (0x1F20u, 0x0345u, 0x1F90u),   HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0300u, 0x1F23u),
-+     HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0301u, 0x1F25u),   HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0342u, 0x1F27u),
-+     HB_CODEPOINT_ENCODE3 (0x1F21u, 0x0345u, 0x1F91u),   HB_CODEPOINT_ENCODE3 (0x1F22u, 0x0345u, 0x1F92u),
-+     HB_CODEPOINT_ENCODE3 (0x1F23u, 0x0345u, 0x1F93u),   HB_CODEPOINT_ENCODE3 (0x1F24u, 0x0345u, 0x1F94u),
-+     HB_CODEPOINT_ENCODE3 (0x1F25u, 0x0345u, 0x1F95u),   HB_CODEPOINT_ENCODE3 (0x1F26u, 0x0345u, 0x1F96u),
-+     HB_CODEPOINT_ENCODE3 (0x1F27u, 0x0345u, 0x1F97u),   HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0300u, 0x1F2Au),
-+     HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0301u, 0x1F2Cu),   HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0342u, 0x1F2Eu),
-+     HB_CODEPOINT_ENCODE3 (0x1F28u, 0x0345u, 0x1F98u),   HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0300u, 0x1F2Bu),
-+     HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0301u, 0x1F2Du),   HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0342u, 0x1F2Fu),
-+     HB_CODEPOINT_ENCODE3 (0x1F29u, 0x0345u, 0x1F99u),   HB_CODEPOINT_ENCODE3 (0x1F2Au, 0x0345u, 0x1F9Au),
-+     HB_CODEPOINT_ENCODE3 (0x1F2Bu, 0x0345u, 0x1F9Bu),   HB_CODEPOINT_ENCODE3 (0x1F2Cu, 0x0345u, 0x1F9Cu),
-+     HB_CODEPOINT_ENCODE3 (0x1F2Du, 0x0345u, 0x1F9Du),   HB_CODEPOINT_ENCODE3 (0x1F2Eu, 0x0345u, 0x1F9Eu),
-+     HB_CODEPOINT_ENCODE3 (0x1F2Fu, 0x0345u, 0x1F9Fu),   HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0300u, 0x1F32u),
-+     HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0301u, 0x1F34u),   HB_CODEPOINT_ENCODE3 (0x1F30u, 0x0342u, 0x1F36u),
-+     HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0300u, 0x1F33u),   HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0301u, 0x1F35u),
-+     HB_CODEPOINT_ENCODE3 (0x1F31u, 0x0342u, 0x1F37u),   HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0300u, 0x1F3Au),
-+     HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0301u, 0x1F3Cu),   HB_CODEPOINT_ENCODE3 (0x1F38u, 0x0342u, 0x1F3Eu),
-+     HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0300u, 0x1F3Bu),   HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0301u, 0x1F3Du),
-+     HB_CODEPOINT_ENCODE3 (0x1F39u, 0x0342u, 0x1F3Fu),   HB_CODEPOINT_ENCODE3 (0x1F40u, 0x0300u, 0x1F42u),
-+     HB_CODEPOINT_ENCODE3 (0x1F40u, 0x0301u, 0x1F44u),   HB_CODEPOINT_ENCODE3 (0x1F41u, 0x0300u, 0x1F43u),
-+     HB_CODEPOINT_ENCODE3 (0x1F41u, 0x0301u, 0x1F45u),   HB_CODEPOINT_ENCODE3 (0x1F48u, 0x0300u, 0x1F4Au),
-+     HB_CODEPOINT_ENCODE3 (0x1F48u, 0x0301u, 0x1F4Cu),   HB_CODEPOINT_ENCODE3 (0x1F49u, 0x0300u, 0x1F4Bu),
-+     HB_CODEPOINT_ENCODE3 (0x1F49u, 0x0301u, 0x1F4Du),   HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0300u, 0x1F52u),
-+     HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0301u, 0x1F54u),   HB_CODEPOINT_ENCODE3 (0x1F50u, 0x0342u, 0x1F56u),
-+     HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0300u, 0x1F53u),   HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0301u, 0x1F55u),
-+     HB_CODEPOINT_ENCODE3 (0x1F51u, 0x0342u, 0x1F57u),   HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0300u, 0x1F5Bu),
-+     HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0301u, 0x1F5Du),   HB_CODEPOINT_ENCODE3 (0x1F59u, 0x0342u, 0x1F5Fu),
-+     HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0300u, 0x1F62u),   HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0301u, 0x1F64u),
-+     HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0342u, 0x1F66u),   HB_CODEPOINT_ENCODE3 (0x1F60u, 0x0345u, 0x1FA0u),
-+     HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0300u, 0x1F63u),   HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0301u, 0x1F65u),
-+     HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0342u, 0x1F67u),   HB_CODEPOINT_ENCODE3 (0x1F61u, 0x0345u, 0x1FA1u),
-+     HB_CODEPOINT_ENCODE3 (0x1F62u, 0x0345u, 0x1FA2u),   HB_CODEPOINT_ENCODE3 (0x1F63u, 0x0345u, 0x1FA3u),
-+     HB_CODEPOINT_ENCODE3 (0x1F64u, 0x0345u, 0x1FA4u),   HB_CODEPOINT_ENCODE3 (0x1F65u, 0x0345u, 0x1FA5u),
-+     HB_CODEPOINT_ENCODE3 (0x1F66u, 0x0345u, 0x1FA6u),   HB_CODEPOINT_ENCODE3 (0x1F67u, 0x0345u, 0x1FA7u),
-+     HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0300u, 0x1F6Au),   HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0301u, 0x1F6Cu),
-+     HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0342u, 0x1F6Eu),   HB_CODEPOINT_ENCODE3 (0x1F68u, 0x0345u, 0x1FA8u),
-+     HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0300u, 0x1F6Bu),   HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0301u, 0x1F6Du),
-+     HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0342u, 0x1F6Fu),   HB_CODEPOINT_ENCODE3 (0x1F69u, 0x0345u, 0x1FA9u),
-+     HB_CODEPOINT_ENCODE3 (0x1F6Au, 0x0345u, 0x1FAAu),   HB_CODEPOINT_ENCODE3 (0x1F6Bu, 0x0345u, 0x1FABu),
-+     HB_CODEPOINT_ENCODE3 (0x1F6Cu, 0x0345u, 0x1FACu),   HB_CODEPOINT_ENCODE3 (0x1F6Du, 0x0345u, 0x1FADu),
-+     HB_CODEPOINT_ENCODE3 (0x1F6Eu, 0x0345u, 0x1FAEu),   HB_CODEPOINT_ENCODE3 (0x1F6Fu, 0x0345u, 0x1FAFu),
-+     HB_CODEPOINT_ENCODE3 (0x1F70u, 0x0345u, 0x1FB2u),   HB_CODEPOINT_ENCODE3 (0x1F74u, 0x0345u, 0x1FC2u),
-+     HB_CODEPOINT_ENCODE3 (0x1F7Cu, 0x0345u, 0x1FF2u),   HB_CODEPOINT_ENCODE3 (0x1FB6u, 0x0345u, 0x1FB7u),
-+     HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0300u, 0x1FCDu),   HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0301u, 0x1FCEu),
-+     HB_CODEPOINT_ENCODE3 (0x1FBFu, 0x0342u, 0x1FCFu),   HB_CODEPOINT_ENCODE3 (0x1FC6u, 0x0345u, 0x1FC7u),
-+     HB_CODEPOINT_ENCODE3 (0x1FF6u, 0x0345u, 0x1FF7u),   HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0300u, 0x1FDDu),
-+     HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0301u, 0x1FDEu),   HB_CODEPOINT_ENCODE3 (0x1FFEu, 0x0342u, 0x1FDFu),
-+     HB_CODEPOINT_ENCODE3 (0x2190u, 0x0338u, 0x219Au),   HB_CODEPOINT_ENCODE3 (0x2192u, 0x0338u, 0x219Bu),
-+     HB_CODEPOINT_ENCODE3 (0x2194u, 0x0338u, 0x21AEu),   HB_CODEPOINT_ENCODE3 (0x21D0u, 0x0338u, 0x21CDu),
-+     HB_CODEPOINT_ENCODE3 (0x21D2u, 0x0338u, 0x21CFu),   HB_CODEPOINT_ENCODE3 (0x21D4u, 0x0338u, 0x21CEu),
-+     HB_CODEPOINT_ENCODE3 (0x2203u, 0x0338u, 0x2204u),   HB_CODEPOINT_ENCODE3 (0x2208u, 0x0338u, 0x2209u),
-+     HB_CODEPOINT_ENCODE3 (0x220Bu, 0x0338u, 0x220Cu),   HB_CODEPOINT_ENCODE3 (0x2223u, 0x0338u, 0x2224u),
-+     HB_CODEPOINT_ENCODE3 (0x2225u, 0x0338u, 0x2226u),   HB_CODEPOINT_ENCODE3 (0x223Cu, 0x0338u, 0x2241u),
-+     HB_CODEPOINT_ENCODE3 (0x2243u, 0x0338u, 0x2244u),   HB_CODEPOINT_ENCODE3 (0x2245u, 0x0338u, 0x2247u),
-+     HB_CODEPOINT_ENCODE3 (0x2248u, 0x0338u, 0x2249u),   HB_CODEPOINT_ENCODE3 (0x224Du, 0x0338u, 0x226Du),
-+     HB_CODEPOINT_ENCODE3 (0x2261u, 0x0338u, 0x2262u),   HB_CODEPOINT_ENCODE3 (0x2264u, 0x0338u, 0x2270u),
-+     HB_CODEPOINT_ENCODE3 (0x2265u, 0x0338u, 0x2271u),   HB_CODEPOINT_ENCODE3 (0x2272u, 0x0338u, 0x2274u),
-+     HB_CODEPOINT_ENCODE3 (0x2273u, 0x0338u, 0x2275u),   HB_CODEPOINT_ENCODE3 (0x2276u, 0x0338u, 0x2278u),
-+     HB_CODEPOINT_ENCODE3 (0x2277u, 0x0338u, 0x2279u),   HB_CODEPOINT_ENCODE3 (0x227Au, 0x0338u, 0x2280u),
-+     HB_CODEPOINT_ENCODE3 (0x227Bu, 0x0338u, 0x2281u),   HB_CODEPOINT_ENCODE3 (0x227Cu, 0x0338u, 0x22E0u),
-+     HB_CODEPOINT_ENCODE3 (0x227Du, 0x0338u, 0x22E1u),   HB_CODEPOINT_ENCODE3 (0x2282u, 0x0338u, 0x2284u),
-+     HB_CODEPOINT_ENCODE3 (0x2283u, 0x0338u, 0x2285u),   HB_CODEPOINT_ENCODE3 (0x2286u, 0x0338u, 0x2288u),
-+     HB_CODEPOINT_ENCODE3 (0x2287u, 0x0338u, 0x2289u),   HB_CODEPOINT_ENCODE3 (0x2291u, 0x0338u, 0x22E2u),
-+     HB_CODEPOINT_ENCODE3 (0x2292u, 0x0338u, 0x22E3u),   HB_CODEPOINT_ENCODE3 (0x22A2u, 0x0338u, 0x22ACu),
-+     HB_CODEPOINT_ENCODE3 (0x22A8u, 0x0338u, 0x22ADu),   HB_CODEPOINT_ENCODE3 (0x22A9u, 0x0338u, 0x22AEu),
-+     HB_CODEPOINT_ENCODE3 (0x22ABu, 0x0338u, 0x22AFu),   HB_CODEPOINT_ENCODE3 (0x22B2u, 0x0338u, 0x22EAu),
-+     HB_CODEPOINT_ENCODE3 (0x22B3u, 0x0338u, 0x22EBu),   HB_CODEPOINT_ENCODE3 (0x22B4u, 0x0338u, 0x22ECu),
-+     HB_CODEPOINT_ENCODE3 (0x22B5u, 0x0338u, 0x22EDu),   HB_CODEPOINT_ENCODE3 (0x2ADDu, 0x0338u, 0x0000u),
-+     HB_CODEPOINT_ENCODE3 (0x3046u, 0x3099u, 0x3094u),   HB_CODEPOINT_ENCODE3 (0x304Bu, 0x3099u, 0x304Cu),
-+     HB_CODEPOINT_ENCODE3 (0x304Du, 0x3099u, 0x304Eu),   HB_CODEPOINT_ENCODE3 (0x304Fu, 0x3099u, 0x3050u),
-+     HB_CODEPOINT_ENCODE3 (0x3051u, 0x3099u, 0x3052u),   HB_CODEPOINT_ENCODE3 (0x3053u, 0x3099u, 0x3054u),
-+     HB_CODEPOINT_ENCODE3 (0x3055u, 0x3099u, 0x3056u),   HB_CODEPOINT_ENCODE3 (0x3057u, 0x3099u, 0x3058u),
-+     HB_CODEPOINT_ENCODE3 (0x3059u, 0x3099u, 0x305Au),   HB_CODEPOINT_ENCODE3 (0x305Bu, 0x3099u, 0x305Cu),
-+     HB_CODEPOINT_ENCODE3 (0x305Du, 0x3099u, 0x305Eu),   HB_CODEPOINT_ENCODE3 (0x305Fu, 0x3099u, 0x3060u),
-+     HB_CODEPOINT_ENCODE3 (0x3061u, 0x3099u, 0x3062u),   HB_CODEPOINT_ENCODE3 (0x3064u, 0x3099u, 0x3065u),
-+     HB_CODEPOINT_ENCODE3 (0x3066u, 0x3099u, 0x3067u),   HB_CODEPOINT_ENCODE3 (0x3068u, 0x3099u, 0x3069u),
-+     HB_CODEPOINT_ENCODE3 (0x306Fu, 0x3099u, 0x3070u),   HB_CODEPOINT_ENCODE3 (0x306Fu, 0x309Au, 0x3071u),
-+     HB_CODEPOINT_ENCODE3 (0x3072u, 0x3099u, 0x3073u),   HB_CODEPOINT_ENCODE3 (0x3072u, 0x309Au, 0x3074u),
-+     HB_CODEPOINT_ENCODE3 (0x3075u, 0x3099u, 0x3076u),   HB_CODEPOINT_ENCODE3 (0x3075u, 0x309Au, 0x3077u),
-+     HB_CODEPOINT_ENCODE3 (0x3078u, 0x3099u, 0x3079u),   HB_CODEPOINT_ENCODE3 (0x3078u, 0x309Au, 0x307Au),
-+     HB_CODEPOINT_ENCODE3 (0x307Bu, 0x3099u, 0x307Cu),   HB_CODEPOINT_ENCODE3 (0x307Bu, 0x309Au, 0x307Du),
-+     HB_CODEPOINT_ENCODE3 (0x309Du, 0x3099u, 0x309Eu),   HB_CODEPOINT_ENCODE3 (0x30A6u, 0x3099u, 0x30F4u),
-+     HB_CODEPOINT_ENCODE3 (0x30ABu, 0x3099u, 0x30ACu),   HB_CODEPOINT_ENCODE3 (0x30ADu, 0x3099u, 0x30AEu),
-+     HB_CODEPOINT_ENCODE3 (0x30AFu, 0x3099u, 0x30B0u),   HB_CODEPOINT_ENCODE3 (0x30B1u, 0x3099u, 0x30B2u),
-+     HB_CODEPOINT_ENCODE3 (0x30B3u, 0x3099u, 0x30B4u),   HB_CODEPOINT_ENCODE3 (0x30B5u, 0x3099u, 0x30B6u),
-+     HB_CODEPOINT_ENCODE3 (0x30B7u, 0x3099u, 0x30B8u),   HB_CODEPOINT_ENCODE3 (0x30B9u, 0x3099u, 0x30BAu),
-+     HB_CODEPOINT_ENCODE3 (0x30BBu, 0x3099u, 0x30BCu),   HB_CODEPOINT_ENCODE3 (0x30BDu, 0x3099u, 0x30BEu),
-+     HB_CODEPOINT_ENCODE3 (0x30BFu, 0x3099u, 0x30C0u),   HB_CODEPOINT_ENCODE3 (0x30C1u, 0x3099u, 0x30C2u),
-+     HB_CODEPOINT_ENCODE3 (0x30C4u, 0x3099u, 0x30C5u),   HB_CODEPOINT_ENCODE3 (0x30C6u, 0x3099u, 0x30C7u),
-+     HB_CODEPOINT_ENCODE3 (0x30C8u, 0x3099u, 0x30C9u),   HB_CODEPOINT_ENCODE3 (0x30CFu, 0x3099u, 0x30D0u),
-+     HB_CODEPOINT_ENCODE3 (0x30CFu, 0x309Au, 0x30D1u),   HB_CODEPOINT_ENCODE3 (0x30D2u, 0x3099u, 0x30D3u),
-+     HB_CODEPOINT_ENCODE3 (0x30D2u, 0x309Au, 0x30D4u),   HB_CODEPOINT_ENCODE3 (0x30D5u, 0x3099u, 0x30D6u),
-+     HB_CODEPOINT_ENCODE3 (0x30D5u, 0x309Au, 0x30D7u),   HB_CODEPOINT_ENCODE3 (0x30D8u, 0x3099u, 0x30D9u),
-+     HB_CODEPOINT_ENCODE3 (0x30D8u, 0x309Au, 0x30DAu),   HB_CODEPOINT_ENCODE3 (0x30DBu, 0x3099u, 0x30DCu),
-+     HB_CODEPOINT_ENCODE3 (0x30DBu, 0x309Au, 0x30DDu),   HB_CODEPOINT_ENCODE3 (0x30EFu, 0x3099u, 0x30F7u),
-+     HB_CODEPOINT_ENCODE3 (0x30F0u, 0x3099u, 0x30F8u),   HB_CODEPOINT_ENCODE3 (0x30F1u, 0x3099u, 0x30F9u),
-+     HB_CODEPOINT_ENCODE3 (0x30F2u, 0x3099u, 0x30FAu),   HB_CODEPOINT_ENCODE3 (0x30FDu, 0x3099u, 0x30FEu),
-+     HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C1u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0xFB49u, 0x05C2u, 0x0000u),
-+  HB_CODEPOINT_ENCODE3 (0x11099u, 0x110BAu, 0x1109Au),HB_CODEPOINT_ENCODE3 (0x1109Bu, 0x110BAu, 0x1109Cu),
-+  HB_CODEPOINT_ENCODE3 (0x110A5u, 0x110BAu, 0x110ABu),HB_CODEPOINT_ENCODE3 (0x11131u, 0x11127u, 0x1112Eu),
-+  HB_CODEPOINT_ENCODE3 (0x11132u, 0x11127u, 0x1112Fu),HB_CODEPOINT_ENCODE3 (0x11347u, 0x1133Eu, 0x1134Bu),
-+  HB_CODEPOINT_ENCODE3 (0x11347u, 0x11357u, 0x1134Cu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114B0u, 0x114BCu),
-+  HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BAu, 0x114BBu),HB_CODEPOINT_ENCODE3 (0x114B9u, 0x114BDu, 0x114BEu),
-+  HB_CODEPOINT_ENCODE3 (0x115B8u, 0x115AFu, 0x115BAu),HB_CODEPOINT_ENCODE3 (0x115B9u, 0x115AFu, 0x115BBu),
-+   HB_CODEPOINT_ENCODE3 (0x1D157u, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D158u, 0x1D165u, 0x0000u),
-+   HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Eu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D16Fu, 0x0000u),
-+   HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D170u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D171u, 0x0000u),
-+   HB_CODEPOINT_ENCODE3 (0x1D15Fu, 0x1D172u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1B9u, 0x1D165u, 0x0000u),
-+   HB_CODEPOINT_ENCODE3 (0x1D1BAu, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Eu, 0x0000u),
-+   HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Fu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Eu, 0x0000u),
-+   HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Fu, 0x0000u),
-+};
-+
-+#ifndef HB_OPTIMIZE_SIZE
-+
-+static const uint8_t
-+_hb_ucd_u8[31814] =
-+{
-+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-+   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 28,
-+   29, 26, 30, 31, 32, 33, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 34, 35, 35, 35, 35,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 38, 39, 40,
-+   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
-+   26, 57, 58, 59, 59, 59, 59, 59, 26, 26, 60, 59, 59, 59, 59, 59,
-+   59, 59, 26, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 26, 62, 59, 63, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 64, 26, 65, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 66, 67, 59, 59, 59, 59, 68, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 69, 70, 71, 72, 73, 74, 59, 59,
-+   75, 76, 59, 59, 77, 59, 78, 79, 80, 81, 73, 82, 83, 84, 59, 59,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 85, 26, 26, 26, 26, 26, 26, 26, 86, 87, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 88, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 89, 59, 59, 59, 59, 59, 59, 26, 90, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   91, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 92,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 93,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   29, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 25, 25, 25, 21,
-+   21,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 22, 21, 18, 24, 16,
-+   24,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 22, 25, 18, 25,  0,
-+   29, 21, 23, 23, 23, 23, 26, 21, 24, 26,  7, 20, 25,  1, 26, 24,
-+   26, 25, 15, 15, 24,  5, 21, 21, 24, 15,  7, 19, 15, 15, 15, 21,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9, 25,  9,  9,  9,  9,  9,  9,  9,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5, 25,  5,  5,  5,  5,  5,  5,  5,  5,
-+    9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
-+    9,  5,  9,  5,  9,  5,  9,  5,  5,  9,  5,  9,  5,  9,  5,  9,
-+    5,  9,  5,  9,  5,  9,  5,  9,  5,  5,  9,  5,  9,  5,  9,  5,
-+    9,  5,  9,  5,  9,  5,  9,  5,  9,  9,  5,  9,  5,  9,  5,  5,
-+    5,  9,  9,  5,  9,  5,  9,  9,  5,  9,  9,  9,  5,  5,  9,  9,
-+    9,  9,  5,  9,  9,  5,  9,  9,  9,  5,  5,  5,  9,  9,  5,  9,
-+    9,  5,  9,  5,  9,  5,  9,  9,  5,  9,  5,  5,  9,  5,  9,  9,
-+    5,  9,  9,  9,  5,  9,  5,  9,  9,  5,  5,  7,  9,  5,  5,  5,
-+    7,  7,  7,  7,  9,  8,  5,  9,  8,  5,  9,  8,  5,  9,  5,  9,
-+    5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  5,  9,  5,
-+    5,  9,  8,  5,  9,  5,  9,  9,  9,  5,  9,  5,  9,  5,  9,  5,
-+    9,  5,  9,  5,  5,  5,  5,  5,  5,  5,  9,  9,  5,  9,  9,  5,
-+    5,  9,  5,  9,  9,  9,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
-+    5,  5,  5,  5,  7,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-+    6,  6, 24, 24, 24, 24,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-+    6,  6, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-+    6,  6,  6,  6,  6, 24, 24, 24, 24, 24, 24, 24,  6, 24,  6, 24,
-+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+    9,  5,  9,  5,  6, 24,  9,  5,  2,  2,  6,  5,  5,  5, 21,  9,
-+    2,  2,  2,  2, 24, 24,  9, 21,  9,  9,  9,  2,  9,  2,  9,  9,
-+    5,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  9,
-+    5,  5,  9,  9,  9,  5,  5,  5,  9,  5,  9,  5,  9,  5,  9,  5,
-+    5,  5,  5,  5,  9,  5, 25,  9,  5,  9,  9,  5,  5,  9,  9,  9,
-+    9,  5, 26, 12, 12, 12, 12, 12, 11, 11,  9,  5,  9,  5,  9,  5,
-+    9,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  5,
-+    2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  2,  2,  6, 21, 21, 21, 21, 21, 21,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5, 21, 17,  2,  2, 26, 26, 23,
-+    2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 17, 12,
-+   21, 12, 12, 21, 12, 12, 21, 12,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  7,
-+    7,  7,  7, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    1,  1,  1,  1,  1,  1, 25, 25, 25, 21, 21, 23, 21, 21, 26, 26,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21,  1,  2, 21, 21,
-+    6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21,  7,  7,
-+   12,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7, 21,  7, 12, 12, 12, 12, 12, 12, 12,  1, 26, 12,
-+   12, 12, 12, 12, 12,  6,  6, 12, 12, 26, 12, 12, 12, 12,  7,  7,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7,  7,  7, 26, 26,  7,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,  1,
-+    7, 12,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12,  6,  6, 26, 21, 21, 21,  6,  2,  2, 12, 23, 23,
-+    7,  7,  7,  7,  7,  7, 12, 12, 12, 12,  6, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12,  6, 12, 12, 12,  6, 12, 12, 12, 12, 12,  2,  2,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12,  2,  2, 21,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,
-+    2,  2,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12,  1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 10, 12,  7, 10, 10,
-+   10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 12, 10, 10,
-+    7, 12, 12, 12, 12, 12, 12, 12,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7, 12, 12, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+   21,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7, 12, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  7,
-+    7,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,
-+    7,  2,  7,  2,  2,  2,  7,  7,  7,  7,  2,  2, 12,  7, 10, 10,
-+   10, 12, 12, 12, 12,  2,  2, 10, 10,  2,  2, 10, 10, 12,  7,  2,
-+    2,  2,  2,  2,  2,  2,  2, 10,  2,  2,  2,  2,  7,  7,  2,  7,
-+    7,  7, 12, 12,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+    7,  7, 23, 23, 15, 15, 15, 15, 15, 15, 26, 23,  7, 21, 12,  2,
-+    2, 12, 12, 10,  2,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  7,
-+    7,  2,  7,  7,  2,  7,  7,  2,  7,  7,  2,  2, 12,  2, 10, 10,
-+   10, 12, 12,  2,  2,  2,  2, 12, 12,  2,  2, 12, 12, 12,  2,  2,
-+    2, 12,  2,  2,  2,  2,  2,  2,  2,  7,  7,  7,  7,  2,  7,  2,
-+    2,  2,  2,  2,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+   12, 12,  7,  7,  7, 12, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2, 12, 12, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,
-+    7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  2,  2, 12,  7, 10, 10,
-+   10, 12, 12, 12, 12, 12,  2, 12, 12, 10,  2, 10, 10, 12,  2,  2,
-+    7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   21, 23,  2,  2,  2,  2,  2,  2,  2,  7, 12, 12, 12, 12, 12, 12,
-+    2, 12, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  7,
-+    7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  2,  2, 12,  7, 10, 12,
-+   10, 12, 12, 12, 12,  2,  2, 10, 10,  2,  2, 10, 10, 12,  2,  2,
-+    2,  2,  2,  2,  2,  2, 12, 10,  2,  2,  2,  2,  7,  7,  2,  7,
-+   26,  7, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2, 12,  7,  2,  7,  7,  7,  7,  7,  7,  2,  2,  2,  7,  7,
-+    7,  2,  7,  7,  7,  7,  2,  2,  2,  7,  7,  2,  7,  2,  7,  7,
-+    2,  2,  2,  7,  7,  2,  2,  2,  7,  7,  7,  2,  2,  2,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2, 10, 10,
-+   12, 10, 10,  2,  2,  2, 10, 10, 10,  2, 10, 10, 10, 12,  2,  2,
-+    7,  2,  2,  2,  2,  2,  2, 10,  2,  2,  2,  2,  2,  2,  2,  2,
-+   15, 15, 15, 26, 26, 26, 26, 26, 26, 23, 26,  2,  2,  2,  2,  2,
-+   12, 10, 10, 10, 12,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,
-+    7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  7, 12, 12,
-+   12, 10, 10, 10, 10,  2, 12, 12, 12,  2, 12, 12, 12, 12,  2,  2,
-+    2,  2,  2,  2,  2, 12, 12,  2,  7,  7,  7,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2, 21, 15, 15, 15, 15, 15, 15, 15, 26,
-+    7, 12, 10, 10, 21,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,
-+    7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  2,  2, 12,  7, 10, 12,
-+   10, 10, 10, 10, 10,  2, 12, 10, 10,  2, 10, 10, 12, 12,  2,  2,
-+    2,  2,  2,  2,  2, 10, 10,  2,  2,  2,  2,  2,  2,  2,  7,  2,
-+    2,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   12, 12, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12,  7, 10, 10,
-+   10, 12, 12, 12, 12,  2, 10, 10, 10,  2, 10, 10, 10, 12,  7, 26,
-+    2,  2,  2,  2,  7,  7,  7, 10, 15, 15, 15, 15, 15, 15, 15,  7,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 26,  7,  7,  7,  7,  7,  7,
-+    2,  2, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  7,  7,  7,  7,  7,  7,
-+    7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  2,  2,  2, 12,  2,  2,  2,  2, 10,
-+   10, 10, 12, 12, 12,  2, 12,  2, 10, 10, 10, 10, 10, 10, 10, 10,
-+    2,  2, 10, 10, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7, 12,  7,  7, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,  2, 23,
-+    7,  7,  7,  7,  7,  7,  6, 12, 12, 12, 12, 12, 12, 12, 12, 21,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21,  2,  2,  2,  2,
-+    2,  7,  7,  2,  7,  2,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,
-+    7,  7,  7,  7,  2,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7, 12,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12, 12,  7,  2,  2,
-+    7,  7,  7,  7,  7,  2,  6,  2, 12, 12, 12, 12, 12, 12,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  7,  7,  7,  7,
-+    7, 26, 26, 26, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 26, 21, 26, 26, 26, 12, 12, 26, 26, 26, 26, 26, 26,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 26, 12, 26, 12, 26, 12, 22, 18, 22, 18, 10, 10,
-+    7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,
-+    2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
-+   12, 12, 12, 12, 12, 21, 12, 12,  7,  7,  7,  7,  7, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2, 26, 26,
-+   26, 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26,  2, 26, 26,
-+   21, 21, 21, 21, 21, 26, 26, 26, 26, 21, 21,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10, 10, 12, 12, 12,
-+   12, 10, 12, 12, 12, 12, 12, 12, 10, 12, 12, 10, 10, 12, 12,  7,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 21, 21,
-+    7,  7,  7,  7,  7,  7, 10, 10, 12, 12,  7,  7,  7,  7, 12, 12,
-+   12,  7, 10, 10, 10,  7,  7, 10, 10, 10, 10, 10, 10, 10,  7,  7,
-+    7, 12, 12, 12, 12,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7, 12, 10, 10, 12, 12, 10, 10, 10, 10, 10, 10, 12,  7, 10,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 12, 26, 26,
-+    9,  9,  9,  9,  9,  9,  2,  9,  2,  2,  2,  2,  2,  9,  2,  2,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 21,  6,  5,  5,  5,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  2,  7,  2,  7,  7,  7,  7,  2,  2,
-+    7,  2,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,  7,  2,
-+    7,  2,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2, 12, 12, 12,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,
-+    9,  9,  9,  9,  9,  9,  2,  2,  5,  5,  5,  5,  5,  5,  2,  2,
-+   17,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 26, 21,  7,
-+   29,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 22, 18,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 21, 21, 21, 14, 14,
-+   14,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,
-+    7,  7, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7, 12, 12, 12, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  2, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 10, 10,
-+   10, 10, 10, 10, 10, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 21, 21, 21,  6, 21, 21, 21, 23,  7, 12,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2,  2,  2,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,
-+   21, 21, 21, 21, 21, 21, 17, 21, 21, 21, 21, 12, 12, 12,  1,  2,
-+    7,  7,  7,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7, 12, 12,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7, 12,  7,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,
-+   12, 12, 12, 10, 10, 10, 10, 12, 12, 10, 10, 10,  2,  2,  2,  2,
-+   10, 10, 12, 10, 10, 10, 10, 10, 10, 12, 12, 12,  2,  2,  2,  2,
-+   26,  2,  2,  2, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,
-+    7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15,  2,  2,  2, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+    7,  7,  7,  7,  7,  7,  7, 12, 12, 10, 10, 12,  2,  2, 21, 21,
-+    7,  7,  7,  7,  7, 10, 12, 10, 12, 12, 12, 12, 12, 12, 12,  2,
-+   12, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10,
-+   10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2, 12,
-+   21, 21, 21, 21, 21, 21, 21,  6, 21, 21, 21, 21, 21, 21,  2,  2,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11,  2,
-+   12, 12, 12, 12, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7, 12, 10, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10,
-+   10, 10, 12, 10, 10,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,
-+   21, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,
-+   12, 12, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 12, 12, 12,  7,  7,
-+    7,  7,  7,  7,  7,  7, 12, 10, 12, 12, 10, 10, 10, 12, 10, 12,
-+   12, 12, 10, 10,  2,  2,  2,  2,  2,  2,  2,  2, 21, 21, 21, 21,
-+    7,  7,  7,  7, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12,
-+   12, 12, 12, 12, 10, 10, 12, 12,  2,  2,  2, 21, 21, 21, 21, 21,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6, 21, 21,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  2,  2,  2,  2,  2,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,
-+   21, 21, 21, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,
-+   12, 12, 12, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 10, 12, 12, 12, 12, 12, 12, 12,  7,  7,  7,  7, 12,  7,  7,
-+    7,  7,  7,  7, 12,  7,  7, 10, 12, 12,  7,  2,  2,  2,  2,  2,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,
-+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  6,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12,
-+    9,  5,  9,  5,  9,  5,  5,  5,  5,  5,  5,  5,  5,  5,  9,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  9,  9,  9,  9,  9,  9,  9,  9,
-+    5,  5,  5,  5,  5,  5,  2,  2,  9,  9,  9,  9,  9,  9,  2,  2,
-+    5,  5,  5,  5,  5,  5,  5,  5,  2,  9,  2,  9,  2,  9,  2,  9,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,
-+    5,  5,  5,  5,  5,  5,  5,  5,  8,  8,  8,  8,  8,  8,  8,  8,
-+    5,  5,  5,  5,  5,  2,  5,  5,  9,  9,  9,  9,  8, 24,  5, 24,
-+   24, 24,  5,  5,  5,  2,  5,  5,  9,  9,  9,  9,  8, 24, 24, 24,
-+    5,  5,  5,  5,  2,  2,  5,  5,  9,  9,  9,  9,  2, 24, 24, 24,
-+    5,  5,  5,  5,  5,  5,  5,  5,  9,  9,  9,  9,  9, 24, 24, 24,
-+    2,  2,  5,  5,  5,  2,  5,  5,  9,  9,  9,  9,  8, 24, 24,  2,
-+   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,  1,  1,  1,  1,  1,
-+   17, 17, 17, 17, 17, 17, 21, 21, 20, 19, 22, 20, 20, 19, 22, 20,
-+   21, 21, 21, 21, 21, 21, 21, 21, 27, 28,  1,  1,  1,  1,  1, 29,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 21, 21, 21, 21, 16,
-+   16, 21, 21, 21, 25, 22, 18, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 25, 21, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 29,
-+    1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-+   15,  6,  2,  2, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18,  6,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18,  2,
-+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  2,  2,  2,
-+   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
-+   11, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26,  9, 26, 26, 26, 26,  9, 26, 26,  5,  9,  9,  9,  5,  5,
-+    9,  9,  9,  5, 26,  9, 26, 26, 25,  9,  9,  9,  9,  9, 26, 26,
-+   26, 26, 26, 26,  9, 26,  9, 26,  9, 26,  9,  9,  9,  9, 26,  5,
-+    9,  9,  9,  9,  5,  7,  7,  7,  7,  5, 26, 26,  5,  5,  9,  9,
-+   25, 25, 25, 25, 25,  9,  5,  5,  5,  5, 26, 25, 26, 26,  5, 26,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14,  9,  5, 14, 14, 14, 14, 15, 26, 26,  2,  2,  2,  2,
-+   25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 25, 25, 26, 26, 26, 26,
-+   25, 26, 26, 25, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 25, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25,
-+   26, 26, 25, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 26, 26, 26, 26,
-+   25, 25, 26, 26, 26, 26, 26, 26, 26, 22, 18, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25,
-+   25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15,
-+   26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25,
-+   26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18,
-+   22, 18, 22, 18, 22, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   25, 25, 25, 25, 25, 22, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18,
-+   25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
-+   18, 22, 18, 22, 18, 22, 18, 22, 18, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 25, 25,
-+   25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 26, 26, 26,
-+   26, 26, 26, 26,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
-+    9,  5,  9,  9,  9,  5,  5,  9,  5,  9,  5,  9,  5,  9,  9,  9,
-+    9,  5,  9,  5,  5,  9,  5,  5,  5,  5,  5,  5,  6,  6,  9,  9,
-+    9,  5,  9,  5,  5, 26, 26, 26, 26, 26, 26,  9,  5,  9,  5, 12,
-+   12, 12,  9,  5,  2,  2,  2,  2,  2, 21, 21, 21, 21, 15, 21, 21,
-+    5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  2,  2,  5,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  6,
-+   21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12,
-+    7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  2,
-+   21, 21, 20, 19, 20, 19, 21, 21, 21, 20, 19, 21, 20, 19, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 17, 21, 21, 17, 21, 20, 19, 21, 21,
-+   20, 19, 22, 18, 22, 18, 22, 18, 22, 18, 21, 21, 21, 21, 21,  6,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 17, 17, 21, 21, 21, 21,
-+   17, 21, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,
-+   29, 21, 21, 21, 26,  6,  7, 14, 22, 18, 22, 18, 22, 18, 22, 18,
-+   22, 18, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, 17, 22, 18, 18,
-+   26, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 10, 10,
-+   17,  6,  6,  6,  6,  6, 26, 26, 14, 14, 14,  6,  7, 21, 26, 26,
-+    7,  7,  7,  7,  7,  7,  7,  2,  2, 12, 12, 24, 24,  6,  6,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 21,  6,  6,  6,  7,
-+    2,  2,  2,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+   26, 26, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, 15, 15,
-+   26, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+    7,  7,  7,  7,  7,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6, 21, 21, 21,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7,  7,  2,  2,  2,  2,
-+    9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  7, 12,
-+   11, 11, 11, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21,  6,
-+    9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  6,  6, 12, 12,
-+    7,  7,  7,  7,  7,  7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   12, 12, 21, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,
-+   24, 24, 24, 24, 24, 24, 24,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-+   24, 24,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
-+    5,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
-+    6,  5,  5,  5,  5,  5,  5,  5,  5,  9,  5,  9,  5,  9,  9,  5,
-+    9,  5,  9,  5,  9,  5,  9,  5,  6, 24, 24,  9,  5,  9,  5,  7,
-+    9,  5,  9,  5,  5,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
-+    9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  9,  9,  9,  9,  5,
-+    9,  9,  9,  9,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,  9,  5,
-+    2,  2,  9,  5,  9,  9,  9,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  7,  6,  6,  5,  7,  7,  7,  7,  7,
-+    7,  7, 12,  7,  7,  7, 12,  7,  7,  7,  7, 12,  7,  7,  7,  7,
-+    7,  7,  7, 10, 10, 12, 12, 10, 26, 26, 26, 26,  2,  2,  2,  2,
-+   15, 15, 15, 15, 15, 15, 26, 26, 23, 26,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,
-+   10, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-+   10, 10, 10, 10, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2, 21, 21,
-+   12, 12,  7,  7,  7,  7,  7,  7, 21, 21, 21,  7, 21,  7,  7, 12,
-+    7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12, 21, 21,
-+    7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 10, 10,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 21,
-+    7,  7,  7, 12, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 10,
-+   10, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,  6,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 21, 21,
-+    7,  7,  7,  7,  7, 12,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7,  7,  7,  7,  7,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 10,
-+   10, 12, 12, 10, 10, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7, 12,  7,  7,  7,  7,  7,  7,  7,  7, 12, 10,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2, 21, 21, 21, 21,
-+    6,  7,  7,  7,  7,  7,  7, 26, 26, 26,  7, 10, 12, 10,  7,  7,
-+   12,  7, 12, 12, 12,  7,  7, 12, 12,  7,  7,  7,  7,  7, 12, 12,
-+    7, 12,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7,  6, 21, 21,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10, 12, 12, 10, 10,
-+   21, 21,  7,  6,  6, 10, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  7,  7,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,  2,
-+    2,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 24,  6,  6,  6,  6,
-+    5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7, 10, 10, 12, 10, 10, 12, 10, 10, 21, 10, 12,  2,  2,
-+    7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  7,  7,  7,  7,  7,
-+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-+    5,  5,  5,  5,  5,  5,  5,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  5,  5,  5,  5,  5,  2,  2,  2,  2,  2,  7, 12,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7, 25,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  2,  7,  2,
-+    7,  7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-+   24, 24,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 18, 22,
-+    2,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 23, 26,  2,  2,
-+   21, 21, 21, 21, 21, 21, 21, 22, 18, 21,  2,  2,  2,  2,  2,  2,
-+   21, 17, 17, 16, 16, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
-+   18, 22, 18, 22, 18, 21, 21, 22, 18, 21, 21, 21, 21, 16, 16, 16,
-+   21, 21, 21,  2, 21, 21, 21, 21, 17, 22, 18, 22, 18, 22, 18, 21,
-+   21, 21, 25, 17, 25, 25, 25,  2, 21, 23, 21, 21,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  1,
-+    2, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 22, 25, 18, 25, 22,
-+   18, 21, 22, 18, 21, 21,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  6,  6,
-+    2,  2,  7,  7,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,
-+    2,  2,  7,  7,  7,  7,  7,  7,  2,  2,  7,  7,  7,  2,  2,  2,
-+   23, 23, 25, 24, 26, 23, 23,  2, 26, 25, 25, 25, 25, 26, 26,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1, 26, 26,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  2,  7,
-+   21, 21, 21,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15,  2,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   14, 14, 14, 14, 14, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 26, 26, 26,  2,
-+   26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12,  2,  2,
-+   12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,
-+   15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7,  7,
-+    7, 14,  7,  7,  7,  7,  7,  7,  7,  7, 14,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2, 21,
-+    7,  7,  7,  7,  2,  2,  2,  2,  7,  7,  7,  7,  7,  7,  7,  7,
-+   21, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    9,  9,  9,  9,  9,  9,  9,  9,  5,  5,  5,  5,  5,  5,  5,  5,
-+    9,  9,  9,  9,  2,  2,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  2,  2,
-+    7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 21,
-+    7,  7,  7,  7,  7,  7,  2,  2,  7,  2,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  2,  7,  7,  2,  2,  2,  7,  2,  2,  7,
-+    7,  7,  7,  7,  7,  7,  2, 21, 15, 15, 15, 15, 15, 15, 15, 15,
-+    7,  7,  7,  7,  7,  7,  7, 26, 26, 15, 15, 15, 15, 15, 15, 15,
-+    2,  2,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+    7,  7,  7,  2,  7,  7,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15,
-+    7,  7,  7,  7,  7,  7, 15, 15, 15, 15, 15, 15,  2,  2,  2, 21,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2, 21,
-+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2, 15, 15,  7,  7,
-+    2,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+    7, 12, 12, 12,  2, 12, 12,  2,  2,  2,  2,  2, 12, 12, 12, 12,
-+    7,  7,  7,  7,  2,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  2,  2, 12, 12, 12,  2,  2,  2,  2, 12,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 15, 15, 21,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 15, 15, 15,
-+    7,  7,  7,  7,  7,  7,  7,  7, 26,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7, 12, 12,  2,  2,  2,  2, 15, 15, 15, 15, 15,
-+   21, 21, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  2,  2,  2, 21, 21, 21, 21, 21, 21, 21,
-+    7,  7,  7,  7,  7,  7,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15,
-+    7,  7,  7,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15,
-+    7,  7,  2,  2,  2,  2,  2,  2,  2, 21, 21, 21, 21,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15, 15,
-+    9,  9,  9,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    5,  5,  5,  2,  2,  2,  2,  2,  2,  2, 15, 15, 15, 15, 15, 15,
-+    7,  7,  7,  7, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,
-+   15, 15, 15, 15, 15, 15, 15,  7,  2,  2,  2,  2,  2,  2,  2,  2,
-+   12, 15, 15, 15, 15, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,
-+   10, 12, 10,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 21, 21,  2,  2,
-+   15, 15, 15, 15, 15, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12,
-+   10, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 21, 21,  1, 21, 21,
-+   21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  2,  2,
-+   12, 12, 12,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 10, 12, 12, 12,
-+   12, 12, 12, 12, 12,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+   21, 21, 21, 21,  7, 10, 10,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7, 12, 21, 21,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
-+   10,  7,  7,  7,  7, 21, 21, 21, 21, 12, 12, 12, 12, 21,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  7, 21,  7, 21, 21, 21,
-+    2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10, 10, 10, 12,
-+   12, 12, 10, 10, 12, 10, 12, 12, 21, 21, 21, 21, 21, 21, 12,  2,
-+    7,  7,  7,  7,  7,  7,  7,  2,  7,  2,  7,  7,  7,  7,  2,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7, 21,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12,
-+   10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,  2,  2,
-+   12, 12, 10, 10,  2,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  7,
-+    7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  2, 12, 12,  7, 10, 10,
-+   12, 10, 10, 10, 10,  2,  2, 10, 10,  2,  2, 10, 10, 10,  2,  2,
-+    7,  2,  2,  2,  2,  2,  2, 10,  2,  2,  2,  2,  2,  7,  7,  7,
-+    7,  7, 10, 10,  2,  2, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,
-+   12, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12,
-+   10, 10, 12, 12, 12, 10, 12,  7,  7,  7,  7, 21, 21, 21, 21, 21,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2, 21,  2, 21, 12,  7,
-+   10, 10, 10, 12, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, 10, 12,
-+   12, 10, 12, 12,  7,  7, 21,  7,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10,
-+   10, 10, 12, 12, 12, 12,  2,  2, 10, 10, 10, 10, 12, 12, 10, 12,
-+   12, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21,  7,  7,  7,  7, 12, 12,  2,  2,
-+   10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 12, 10, 12,
-+   12, 21, 21, 21,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 10, 12, 10, 10,
-+   12, 12, 12, 12, 12, 12, 10, 12,  7,  2,  2,  2,  2,  2,  2,  2,
-+   10, 10, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12,  2,  2,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 21, 21, 21, 26,
-+   12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21,  2,  2,  2,  2,
-+   15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  7,  7,  7,  7,  7,  7,
-+    7, 10, 10, 10, 12, 12, 12, 12,  2,  2, 12, 12, 10, 10, 10, 10,
-+   12,  7, 21,  7, 10,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  7,  7,  7,  7,  7,
-+    7,  7,  7, 12, 12, 12, 12, 12, 12, 10,  7, 12, 12, 12, 12, 21,
-+   21, 21, 21, 21, 21, 21, 21, 12,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7, 12, 12, 12, 12, 12, 12, 10, 10, 12, 12, 12,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 21, 21,  7, 21, 21,
-+   21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   12, 12, 12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12, 12, 10, 12,
-+    7, 21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   21, 21,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    2,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12,  2, 10, 12, 12, 12, 12, 12, 12,
-+   12, 10, 12, 12, 10, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  2,  7,  7,  7,  7,  7,
-+    7, 12, 12, 12, 12, 12, 12,  2,  2,  2, 12,  2, 12, 12,  2, 12,
-+   12, 12, 12, 12, 12, 12,  7, 12,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  2,  7,  7,  2,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 10, 10, 10, 10, 10,  2,
-+   12, 12,  2, 10, 10, 12, 10, 12,  7,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7, 12, 12, 10, 10, 21, 21,  2,  2,  2,  2,  2,  2,  2,
-+   15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 23, 23, 23,
-+   23, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 21,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2,
-+   21, 21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
-+   12, 12, 12, 12, 12, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 26, 26, 26, 26,
-+    6,  6,  6,  6, 21, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2, 15, 15, 15, 15, 15,
-+   15, 15,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2,  2,  7,  7,  7,
-+   15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2,  2,  2, 12,
-+    7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-+   10, 10, 10, 10, 10, 10, 10, 10,  2,  2,  2,  2,  2,  2,  2, 12,
-+   12, 12, 12,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-+    6,  6, 21,  6,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  7,  7,  7,  7,  2,  2,  2,  2,  2,  2,  2,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  2, 26, 12, 12, 21,
-+    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26, 26, 26, 26, 26, 26,  2,  2, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 10, 10, 12, 12, 12, 26, 26, 26, 10, 10, 10,
-+   10, 10, 10,  1,  1,  1,  1,  1,  1,  1,  1, 12, 12, 12, 12, 12,
-+   12, 12, 12, 26, 26, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26, 12, 12, 12, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  5,  5,
-+    5,  5,  5,  5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    9,  9,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  9,  2,  9,  9,
-+    2,  2,  9,  2,  2,  9,  9,  2,  2,  9,  9,  9,  9,  2,  9,  9,
-+    9,  9,  9,  9,  9,  9,  5,  5,  5,  5,  2,  5,  2,  5,  5,  5,
-+    5,  5,  5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  9,  9,  2,  9,  9,  9,  9,  2,  2,  9,  9,  9,
-+    9,  9,  9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  2,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  9,  9,  2,  9,  9,  9,  9,  2,
-+    9,  9,  9,  9,  9,  2,  9,  2,  2,  2,  9,  9,  9,  9,  9,  9,
-+    9,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  2,  2,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9, 25,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 25,  5,  5,  5,  5,
-+    5,  5,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 25,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5, 25,  5,  5,  5,  5,  5,  5,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9, 25,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 25,
-+    5,  5,  5,  5,  5,  5,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 25,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5, 25,  5,  5,  5,  5,  5,  5,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9, 25,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5, 25,  5,  5,  5,  5,  5,  5,  9,  5,  2,  2, 13, 13,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+   12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26,
-+   26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 12, 26, 26, 21, 21, 21, 21, 21,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12,  2, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2, 12, 12, 12, 12, 12,
-+   12, 12,  2, 12, 12,  2, 12, 12, 12, 12, 12,  2,  2,  2,  2,  2,
-+   12, 12, 12, 12, 12, 12, 12,  6,  6,  6,  6,  6,  6,  6,  2,  2,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2,  7, 26,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 12, 12, 12, 12,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2,  2, 23,
-+    7,  7,  7,  7,  7,  2,  2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   12, 12, 12, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    5,  5,  5,  5, 12, 12, 12, 12, 12, 12, 12,  6,  2,  2,  2,  2,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, 15, 15,
-+   23, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,
-+    7,  7,  7,  7,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    2,  7,  7,  2,  7,  2,  2,  7,  2,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  2,  7,  7,  7,  7,  2,  7,  2,  7,  2,  2,  2,  2,
-+    2,  2,  7,  2,  2,  2,  2,  7,  2,  7,  2,  7,  2,  7,  7,  7,
-+    2,  7,  7,  2,  7,  2,  2,  7,  2,  7,  2,  7,  2,  7,  2,  7,
-+    2,  7,  7,  2,  7,  2,  2,  7,  7,  7,  7,  2,  7,  7,  7,  7,
-+    7,  7,  7,  2,  7,  7,  7,  7,  2,  7,  7,  7,  7,  2,  7,  2,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,
-+    2,  7,  7,  7,  2,  7,  7,  7,  7,  7,  2,  7,  7,  7,  7,  7,
-+   25, 25,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 24, 24, 24, 24, 24,
-+   26, 26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  2,  2,  2,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 26, 26, 26,
-+   26, 26,  2, 26, 26, 26, 26,  2,  2,  2, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26,  2,  2, 26, 26, 26, 26, 26, 26,  2,  2,  2, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2,  2, 26, 26, 26,
-+   26, 26, 26, 26,  2,  2,  2,  2, 26, 26, 26,  2,  2,  2,  2,  2,
-+    7,  7,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  1,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,
-+    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13,
-+   14,  0,  0, 15,  0,  0,  0, 16, 17, 18, 19, 20, 21, 22,  0,  0,
-+   23,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 24, 25,  0,  0,
-+   26,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 27,  0, 28, 29, 30, 31,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 32,  0,  0, 33,  0,
-+    0, 34, 35, 36,  0,  0,  0,  0,  0,  0, 37,  0,  0, 38,  0, 39,
-+   40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,  0, 51, 52,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 53, 54,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 55,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0, 56, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   58, 54, 59,  0,  0,  0,  0,  0, 60, 61,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,
-+    7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  8,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  9, 10, 11, 12,  0,  0,  0,  0, 13,  0,  0, 14, 15,
-+    0, 16,  0,  0,  0,  0,  0, 17, 18,  0,  0, 19,  0, 20, 21,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,
-+    0,  0,  0,  0,  0,  0,  0, 27, 28, 29,  0,  0,  0, 30, 31, 32,
-+    0,  0,  0,  0,  0, 30, 31,  0,  0, 33,  0,  0,  0, 30, 31,  0,
-+    0,  0,  0,  0,  0, 30, 31,  0,  0,  0,  0,  0,  0, 30, 31,  0,
-+    0,  0,  0,  0,  0,  0, 31,  0,  0,  0,  0,  0,  0,  0, 31, 34,
-+    0,  0,  0,  0,  0, 30, 31,  0,  0,  0,  0,  0,  0, 35, 31,  0,
-+    0,  0,  0,  0,  0,  0, 36,  0,  0,  0,  0,  0,  0, 37, 38,  0,
-+    0,  0,  0,  0,  0, 39, 40,  0,  0,  0,  0, 41,  0, 42,  0,  0,
-+    0, 43, 44,  0,  0,  0, 45,  0,  0,  0,  0,  0,  0, 46,  0,  0,
-+    0,  0, 47,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 48,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 49,  0, 49,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 50,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0, 51,  0,  0,  0,  0,  0,  0,  0,  0, 52,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 53,  0,  0,  0,  0,
-+   54, 55,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0, 57, 49,  0,
-+   58, 59,  0,  0, 60,  0,  0,  0, 61, 62,  0,  0,  0, 63,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 64, 65, 66,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 67, 68,  1, 69,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 70, 71, 72,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 73, 74,  0,  0,  0,  0,  0,  0,
-+    0, 75,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0, 76,  0,  0,  0,
-+    0,  0,  0, 77,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   73, 78,  0, 79,  0,  0,  0,  0,  0, 74, 80,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 49,  0,  1, 74,  0,  0, 81,  0,  0, 82,
-+    0,  0,  0,  0,  0, 83, 54,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0, 84, 85,  0,  0, 80,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 31,  0,  0, 86,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 87,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0, 47,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 88,  0,  0,  0,  0,  0,  0,  0,
-+    0, 89,  0,  0,  0,  0,  0,  0,  0,  0, 90,  0,  0, 91,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 92,  0,  0,  0, 93,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 94, 88,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 80,  0,
-+    0, 75,  0,  0,  0, 95,  0,  0,  0,  0, 96,  0,  0, 97,  0,  0,
-+    0, 83,  0,  0,  0,  0, 98,  0,  0,  0,  0,  0,  0, 99,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,100,  0,  0,  0,  0,101, 31,  0,
-+  102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,104, 33,
-+    0,  0,  0,  0,  0,  0,105,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0, 75,106,  0,  0,  0,  0,  0,  0, 75,  0,  0,
-+    0,  0,  0,  0,  0,107,  0,  0,  0,  0,  0,  0,108,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 95,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0, 49,109,  0,
-+    0,  0,  0,110,  0,  0,  0,  0,  0,  0,  0,  0,  0, 75,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,111,  0,
-+    0,  0,  0,109,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,112,  0,  0,  0,113,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,114,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  115,116,117,  0,118,  0,  0,  0,  0,  0,  0,  0,  0,  0,119,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,120,121,122,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,123,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,124,  0,  0,  0,  0,  0,  0,125,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,230,230,230,
-+  230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,232,
-+  220,220,220,220,232,216,220,220,220,220,220,202,202,220,220,220,
-+  220,202,202,220,220,220,220,220,220,220,220,220,220,220,  1,  1,
-+    1,  1,  1,220,220,220,220,230,230,230,230,230,230,230,230,240,
-+  230,220,220,220,230,230,230,220,220,  0,230,230,230,220,220,220,
-+  220,230,232,220,220,230,233,234,234,233,234,234,233,230,230,230,
-+  230,230,230,230,230,230,230,230,230,230,  0,  0,  0,230,230,230,
-+  230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,220,230,230,230,230,
-+  220,230,230,230,222,220,230,230,230,230,230,230,220,220,220,220,
-+  220,220,230,230,220,230,230,222,228,230, 10, 11, 12, 13, 14, 15,
-+   16, 17, 18, 19, 19, 20, 21, 22,  0, 23,  0, 24, 25,  0,230,220,
-+    0, 18,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,230,230,230,
-+  230,230, 30, 31, 32,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,
-+  220,230,230,230,230,230,220,230,230,220, 35,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  230,230,230,230,230,230,230,  0,  0,230,230,230,230,220,230,  0,
-+    0,230,230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,220,230,230,220,230,
-+  230,220,220,220,230,220,220,230,220,230,230,230,220,230,220,230,
-+  220,230,220,230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,230,230,230,230,230,230,230,220,230,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,220,  0,  0,  0,  0,  0,  0,  0,  0,
-+  230,230,230,230,  0,230,230,230,230,230,230,230,230,230,  0,230,
-+  230,230,  0,230,230,230,230,230,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,220,220,220,  0,  0,  0,  0,  0,  0,  0,220,230,230,
-+  230,230,230,230,230,230,230,230,230,230,230,230,  0,220,230,230,
-+  220,230,230,220,230,230,230,220,220,220, 27, 28, 29,230,230,230,
-+  220,230,230,220,220,230,230,230,230,230,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,230,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,230,  0,  0,  0,  0,  0,  0, 84,
-+   91,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,103,103,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,107,107,107,107,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,118,118,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,122,122,122,122,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,220,220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,220,
-+    0,220,  0,216,  0,  0,  0,  0,  0,  0,  0,129,130,  0,132,  0,
-+    0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,230,230,  9,  0,
-+  230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  7,  0,  9,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,220,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,230,230,230,  0,  0,  0,  0,  9,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,230,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,228,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,222,230,220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,230,220,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,
-+  230,230,230,230,230,230,230,  0,  0,220,230,230,230,230,230,220,
-+  220,220,220,220,220,230,230,220,  0,  0,  0,  0,  0,  0,  7,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,230,220,230,230,230,230,230,230,230,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  9,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  7,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,  0,  1,220,
-+  220,220,220,220,230,230,220,220,220,220,230,  0,  1,  1,  1,  1,
-+    1,  1,  1,  0,  0,  0,  0,220,  0,  0,  0,  0,  0,  0,230,  0,
-+    0,  0,230,230,  0,  0,  0,  0,  0,  0,230,230,220,230,230,230,
-+  230,230,230,230,220,230,230,234,214,220,202,230,230,230,230,230,
-+  230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,
-+  232,228,228,220,  0,230,233,220,230,220,230,230,  1,  1,230,230,
-+  230,230,  1,  1,  1,230,230,  0,  0,  0,  0,230,  0,  0,  0,  1,
-+    1,230,220,230,  1,  1,220,220,220,220,230,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,218,228,232,222,224,224,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  8,  8,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,
-+  230,230,230,230,230,230,230,230,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,230,230,  0,  0,  0,  0,  0,  0,
-+    9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,220,220,220,  0,  0,  0,  0,  0,  9,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  7,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,  0,230,230,220,  0,
-+    0,230,230,  0,  0,  0,  0,  0,230,230,  0,230,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 26,  0,230,230,230,230,230,230,
-+  230,220,220,220,220,220,220,220,230,230,220,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  230,230,230,230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,220,  0,230,  0,  0,  0,  0,  0,  0,
-+    0,  0,230,  1,220,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,230,
-+  220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,
-+  230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  220,220,230,230,230,220,230,220,220,220,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  9,  7,  0,  0,  0,  0,  0,230,230,230,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  9,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,
-+    7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  7,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  7,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  230,230,230,230,230,230,230,  0,  0,  0,230,230,230,230,230,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  0,  0,  0,
-+    7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  7,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  7,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    9,  7,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  9,  0,  0,  0,  0,  0,  0,  0,  0,  7,  0,  9,  9,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,230,230,230,
-+  230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,216,
-+  216,  1,  1,  1,  0,  0,  0,226,216,216,216,216,216,  0,  0,  0,
-+    0,  0,  0,  0,  0,220,220,220,220,220,220,220,220,  0,  0,230,
-+  230,230,230,230,220,220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,230,230,230,230,  0,  0,  0,  0,230,230,230,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,230,230,230,230,
-+  230,  0,230,230,230,230,230,230,230,230,230,230,230,230,230,230,
-+  230,230,230,  0,  0,230,230,230,230,230,230,230,  0,230,230,  0,
-+  230,230,230,230,230,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,230,230,230,230,220,220,220,220,220,220,
-+  220,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,230,230,
-+  230,230,230,230,  7,  0,  0,  0,  0,  0, 16, 17, 17, 17, 17, 17,
-+   17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,129,169,
-+   17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17,237,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
-+    3,  4,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  5,  0,  0,  0,  6,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  7,  1,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    8,  9,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0, 10,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0, 10,  0,  0,  0, 10,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 11, 12,  0, 13,
-+    0, 14, 15, 16,  0,  0,  0,  0,  0,  1, 17, 18,  0, 19,  7,  1,
-+    0,  0,  0, 20, 20,  7, 20, 20, 20, 20, 20, 20, 20,  8, 21,  0,
-+   22,  0,  7, 23, 24,  0, 20, 20, 25,  0,  0,  0, 26, 27,  1,  7,
-+   20, 20, 20, 20, 20,  1, 28, 29, 30, 31,  0,  0, 20,  0,  0,  0,
-+    0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0, 20, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  8, 21, 32,  4,  0, 10,
-+    0, 33,  7, 20, 20, 20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  8, 34, 34, 35, 36, 34,
-+   37,  0, 38,  1, 20, 20,  0,  0, 39,  0,  1,  1,  0,  8, 21,  1,
-+   20,  0,  0,  0,  1,  0,  0, 40,  1,  1,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  8, 21,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  1,  0,  0,  0,  0, 26, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 21,  7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,
-+    0, 42, 43, 44,  0, 45,  0,  8, 21,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0, 46,  7,  1, 10,  1,  0,  0,
-+    0,  1, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 20,  1, 20,
-+   20,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   26, 21,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,
-+    0,  2,  0,  0,  0,  0,  0,  0,  3,  4,  0,  0,  0,  0,  0,  0,
-+    3, 47, 48,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
-+    3,  4,  0,  0,  0,  0,  0,  0,  3,  4,  0,  1,  2,  3,  4,  5,
-+    6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 17, 19, 20,
-+   21, 22, 23, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 27, 28, 28, 29, 30, 31, 32,
-+   33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
-+   33, 33, 33, 33, 33, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
-+   46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 35, 35, 35,
-+   35, 35, 59, 59, 60, 35, 35, 35, 35, 35, 35, 35, 61, 62, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 63, 64,
-+   35, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 66, 68,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 69, 70, 35, 35, 35, 35, 71, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 72, 73, 74, 75, 76, 77, 35, 35, 78, 79, 35, 35, 80, 35,
-+   81, 82, 83, 84, 17, 85, 86, 87, 35, 35, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 88, 25, 25,
-+   25, 25, 25, 25, 25, 89, 90, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 91, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 92,
-+   35, 35, 35, 35, 35, 35, 25, 93, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 94,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19,  0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19,  0,  0,  0,  0,  0,  0,  0, 19, 19, 19, 19,
-+   19,  0,  0,  0,  0,  0, 26, 26,  0,  0,  0,  0,  1,  1,  1,  1,
-+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  9,  9,  9,  9,
-+    0,  9,  9,  9,  2,  2,  9,  9,  9,  9,  0,  9,  2,  2,  2,  2,
-+    9,  0,  9,  0,  9,  9,  9,  2,  9,  2,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 55, 55,
-+   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,  6,  6,  6,  6,
-+    6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-+    6,  1,  1,  6,  6,  6,  6,  6,  6,  6,  6,  6,  2,  4,  4,  4,
-+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
-+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
-+    4,  4,  4,  2,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
-+    4,  4,  4,  4,  4,  0,  4,  2,  2,  4,  4,  4,  2, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14,  2,  2,  2,  2,  2,  2,  2,  2, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14,  2,  2,  2,  2, 14, 14, 14, 14, 14,
-+   14,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-+    3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  0,  3,  2,  3,  0,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-+    1,  1,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  1,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,  3, 37, 37, 37, 37,
-+   37, 37, 37, 37, 37, 37, 37, 37, 37, 37,  2, 37, 37, 37, 37, 37,
-+   37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-+   37, 37, 37, 37, 37, 37, 37,  2,  2, 37, 37, 37, 38, 38, 38, 38,
-+   38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 64, 64, 64, 64,
-+   64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-+   64, 64, 64, 64, 64, 64, 64,  2,  2, 64, 64, 64, 90, 90, 90, 90,
-+   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
-+   90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2,  2, 90, 90, 90, 90,
-+   90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,  2, 95, 95, 95, 95,
-+   95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
-+   95, 95, 95, 95, 95, 95, 95, 95,  2,  2, 95,  2, 37, 37, 37, 37,
-+   37, 37, 37, 37, 37, 37, 37,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-+    3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,  1,  1,
-+    1,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    0,  0,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  5,  5,  5,  5,
-+    2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,  2,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  2,  5,  2,
-+    2,  2,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  2,  2,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,  2,  2,
-+    2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,  5,  5,
-+    2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11, 11, 11,
-+    2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,  2, 11,
-+   11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11, 11, 11,  2, 11, 11, 11, 11, 11, 11, 11,  2, 11, 11,
-+    2, 11, 11,  2, 11, 11,  2,  2, 11,  2, 11, 11, 11, 11, 11,  2,
-+    2,  2,  2, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,  2,  2,
-+    2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,  2,  2,
-+    2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 10, 10, 10,
-+    2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2, 10,
-+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-+   10, 10, 10, 10, 10,  2, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10,
-+    2, 10, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10, 10, 10, 10, 10,
-+   10, 10,  2, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10,
-+    2,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,  2,
-+    2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21, 21, 21,
-+    2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,  2, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21,  2, 21, 21, 21, 21, 21, 21, 21,  2, 21, 21,
-+    2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21,  2,  2, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,  2,  2,
-+    2,  2, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21, 21, 21,
-+    2,  2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 22,
-+    2, 22, 22, 22, 22, 22, 22,  2,  2,  2, 22, 22, 22,  2, 22, 22,
-+   22, 22,  2,  2,  2, 22, 22,  2, 22,  2, 22, 22,  2,  2,  2, 22,
-+   22,  2,  2,  2, 22, 22, 22,  2,  2,  2, 22, 22, 22, 22, 22, 22,
-+   22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22, 22, 22,  2,
-+    2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2, 22,  2,  2,  2,
-+    2,  2,  2, 22,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
-+   22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2,  2, 23, 23, 23, 23,
-+   23, 23, 23, 23, 23, 23, 23, 23, 23,  2, 23, 23, 23,  2, 23, 23,
-+   23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-+   23, 23, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-+   23, 23, 23, 23, 23, 23,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23,
-+   23,  2, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,  2,  2,
-+    2, 23, 23,  2, 23, 23, 23,  2,  2,  2,  2,  2, 23, 23, 23, 23,
-+    2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,  2,  2,  2,  2,
-+    2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 16, 16, 16, 16,
-+   16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2, 16, 16,
-+   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
-+   16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
-+    2, 16, 16, 16, 16, 16,  2,  2, 16, 16, 16, 16, 16, 16, 16, 16,
-+   16,  2, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,  2,  2,
-+    2, 16, 16,  2,  2,  2,  2,  2,  2,  2, 16,  2, 16, 16, 16, 16,
-+    2,  2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 20, 20, 20, 20,
-+    2, 20, 20, 20, 20, 20, 20, 20, 20,  2, 20, 20, 20,  2, 20, 20,
-+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-+   20,  2, 20, 20, 20,  2, 20, 20, 20, 20, 20, 20,  2,  2,  2,  2,
-+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-+    2,  2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 36, 36,
-+    2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2, 36, 36, 36, 36,
-+   36, 36, 36,  2,  2,  2, 36,  2,  2,  2,  2, 36, 36, 36, 36, 36,
-+   36,  2, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,  2,
-+    2,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2, 36, 36,
-+   36,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 24, 24, 24,
-+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-+   24, 24, 24, 24, 24, 24, 24,  2,  2,  2,  2,  0, 24, 24, 24, 24,
-+   24, 24, 24, 24, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18, 18,  2,
-+   18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18, 18, 18,
-+   18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
-+    2, 18,  2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
-+   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2,  2, 18, 18, 18, 18,
-+   18,  2, 18,  2, 18, 18, 18, 18, 18, 18,  2,  2, 18, 18, 18, 18,
-+   18, 18, 18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25,  2,  2,  2,  2, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25,  2, 25, 25, 25, 25, 25, 25,
-+   25,  0,  0,  0,  0, 25, 25,  2,  2,  2,  2,  2, 33, 33, 33, 33,
-+   33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,  8,  8,  8,  8,
-+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-+    8,  8,  2,  8,  2,  2,  2,  2,  2,  8,  2,  2,  8,  8,  8,  8,
-+    8,  8,  8,  8,  8,  8,  8,  0,  8,  8,  8,  8, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 30, 30, 30, 30,
-+   30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-+   30, 30, 30, 30, 30,  2, 30, 30, 30, 30,  2,  2, 30, 30, 30, 30,
-+   30, 30, 30,  2, 30,  2, 30, 30, 30, 30,  2,  2, 30,  2, 30, 30,
-+   30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30,  2, 30,  2, 30, 30,
-+   30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-+   30, 30, 30,  2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
-+   30, 30, 30, 30, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30,
-+   30, 30, 30, 30, 30, 30, 30, 30, 30,  2,  2,  2, 30, 30, 30, 30,
-+   30, 30, 30, 30, 30, 30,  2,  2,  2,  2,  2,  2, 29, 29, 29, 29,
-+   29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-+   29, 29,  2,  2, 29, 29, 29, 29, 29, 29,  2,  2, 28, 28, 28, 28,
-+   28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34,  2,  2,  2, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35,  0,  0,  0, 35, 35, 35, 35, 35, 35,
-+   35, 35, 35, 35, 35,  2,  2,  2,  2,  2,  2,  2, 45, 45, 45, 45,
-+   45, 45, 45, 45, 45, 45, 45, 45, 45,  2, 45, 45, 45, 45, 45, 45,
-+   45,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 44, 44, 44, 44,
-+   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
-+   44,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2, 43, 43, 43, 43,
-+   43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 46, 46, 46, 46,
-+   46, 46, 46, 46, 46, 46, 46, 46, 46,  2, 46, 46, 46,  2, 46, 46,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 31, 31, 31, 31,
-+   31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-+   31, 31, 31, 31, 31, 31, 31, 31, 31, 31,  2,  2, 31, 31, 31, 31,
-+   31, 31, 31, 31, 31, 31,  2,  2,  2,  2,  2,  2, 32, 32,  0,  0,
-+   32,  0, 32, 32, 32, 32, 32, 32, 32, 32, 32,  2, 32, 32, 32, 32,
-+   32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32, 32, 32, 32,
-+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-+   32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2,  2, 32, 32, 32, 32,
-+   32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28, 28, 28,
-+   28, 28,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 48, 48, 48, 48,
-+   48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
-+   48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,  2, 48, 48, 48, 48,
-+   48, 48, 48, 48, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,  2,  2,
-+   48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 52, 52, 52, 52,
-+   52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-+   52, 52, 52, 52, 52, 52, 52, 52, 52, 52,  2,  2, 52, 52, 52, 52,
-+   52,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 58, 58, 58, 58,
-+   58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
-+   58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58, 58, 58,
-+   58, 58, 58, 58, 58, 58,  2,  2,  2,  2,  2,  2, 58, 58, 58, 58,
-+   58, 58, 58, 58, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54, 54, 54,
-+   54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
-+   54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91, 91, 91,
-+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
-+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91, 91, 91,
-+   91, 91, 91, 91, 91, 91, 91, 91, 91,  2,  2, 91, 91, 91, 91, 91,
-+   91, 91, 91, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91, 91, 91,
-+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2,  2,  1,  1,  1,  1,
-+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62, 62, 62,
-+   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
-+   62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2,  2, 62, 62, 62, 62,
-+   62, 62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2, 76, 76, 76, 76,
-+   76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93, 93, 93,
-+   93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
-+    2,  2,  2,  2,  2,  2,  2,  2, 93, 93, 93, 93, 70, 70, 70, 70,
-+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73, 73, 73,
-+   73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,  6,  6,  6,  6,
-+    6,  6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
-+    8,  8,  8,  8,  8,  8,  8,  2,  2,  8,  8,  8, 76, 76, 76, 76,
-+   76, 76, 76, 76,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  0,
-+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  1,  1,
-+    1,  1,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
-+    1,  0,  0,  0,  1,  1,  0,  2,  2,  2,  2,  2, 19, 19, 19, 19,
-+   19, 19,  9,  9,  9,  9,  9,  6, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19, 19, 19,  9,  9,  9,  9,  9, 19, 19,
-+   19, 19,  9,  9,  9,  9,  9, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19, 19,  6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,  9,  1,  1,  1,  1,
-+    1,  1,  1,  1,  1,  1,  2,  1,  1,  1,  1,  1,  9,  9,  9,  9,
-+    9,  9,  2,  2,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,  9,
-+    9,  9,  9,  9,  2,  9,  2,  9,  2,  9,  2,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,  9,
-+    9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    2,  2,  9,  9,  9,  9,  9,  9,  2,  9,  9,  9,  2,  2,  9,  9,
-+    9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,  0,  0,
-+    0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  2,  2,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19, 19, 19,  2,  2,  2,  1,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  9,  0,  0,  0, 19, 19,  0,  0,  0,  0,  0,  0, 19,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,  0, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19,  0,  0,  0,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2, 27, 27, 27, 27,
-+   27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,  0,  0,
-+    2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0, 56, 56, 56, 56,
-+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
-+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,  2, 55, 55, 55, 55,
-+   55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
-+    2,  2,  2,  2,  2, 55, 55, 55, 55, 55, 55, 55, 61, 61, 61, 61,
-+   61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
-+   61, 61, 61, 61,  2,  2,  2,  2,  2,  2,  2, 61, 61,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 61, 30, 30, 30, 30,
-+   30, 30, 30,  2,  2,  2,  2,  2,  2,  2,  2,  2, 30, 30, 30, 30,
-+   30, 30, 30,  2, 30, 30, 30, 30, 30, 30, 30,  2, 13, 13, 13, 13,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+   13, 13, 13, 13, 13, 13,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13, 13, 13,
-+   13, 13,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0, 13,  0, 13,  0,  0,  0,  0,  0,  0,  0,  0,  0, 13, 13, 13,
-+   13, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,  0,  0,  0,  0,
-+    0,  0,  0,  0, 13, 13, 13, 13,  0,  0,  0,  0,  2, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15,  2,  2,  1,  1,  0,  0, 15, 15, 15,  0, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17,  0,  0, 17, 17, 17,  2,  2,  2,  2,
-+    2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,  2, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  2, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26, 26,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,  0, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,  0, 17, 17, 17, 17,
-+   17, 17, 17, 17,  0,  0,  0,  0,  0,  0,  0,  0, 39, 39, 39, 39,
-+   39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
-+   39, 39, 39, 39, 39, 39, 39, 39, 39,  2,  2,  2, 39, 39, 39, 39,
-+   39, 39, 39,  2,  2,  2,  2,  2,  2,  2,  2,  2, 86, 86, 86, 86,
-+   86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77, 77, 77,
-+   77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
-+   77, 77, 77, 77, 77, 77, 77, 77,  2,  2,  2,  2, 79, 79, 79, 79,
-+   79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
-+   79, 79, 79, 79,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19, 19,  0,  0,  0, 19, 19, 19, 19, 19,  2,  2, 19, 19,
-+   19, 19, 19,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 60, 60, 60, 60,
-+   60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-+   60, 60, 60, 60, 60, 60, 60, 60,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  2, 65, 65, 65, 65,
-+   65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
-+   65, 65, 65, 65,  2,  2,  2,  2,  2,  2,  2,  2, 75, 75, 75, 75,
-+   75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
-+   75, 75,  2,  2,  2,  2,  2,  2,  2,  2, 75, 75, 75, 75, 75, 75,
-+   75, 75, 75, 75, 75, 75,  2,  2,  2,  2,  2,  2, 69, 69, 69, 69,
-+   69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-+   69, 69, 69, 69, 69, 69, 69, 69, 69, 69,  0, 69, 74, 74, 74, 74,
-+   74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 74, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2, 84, 84, 84, 84,
-+   84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
-+   84, 84, 84, 84, 84, 84, 84, 84, 84, 84,  2,  0, 84, 84, 84, 84,
-+   84, 84, 84, 84, 84, 84,  2,  2,  2,  2, 84, 84, 33, 33, 33, 33,
-+   33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,  2, 68, 68, 68, 68,
-+   68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-+   68, 68, 68,  2,  2,  2,  2,  2,  2,  2,  2,  2, 68, 68, 68, 68,
-+   68, 68, 68, 68, 68, 68, 68, 68, 68, 68,  2,  2, 68, 68, 68, 68,
-+   68, 68, 68, 68, 68, 68,  2,  2, 68, 68, 68, 68, 92, 92, 92, 92,
-+   92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2, 92, 92, 92, 92, 92, 87, 87, 87, 87,
-+   87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
-+   87, 87, 87,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 30, 30, 30,
-+   30, 30, 30,  2,  2, 30, 30, 30, 30, 30, 30,  2,  2, 30, 30, 30,
-+   30, 30, 30,  2,  2,  2,  2,  2,  2,  2,  2,  2, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19,  0, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19,  9, 19, 19,  2,  2,  2,  2,  2,  2,  2,  2, 87, 87, 87, 87,
-+   87, 87, 87, 87, 87, 87, 87, 87, 87, 87,  2,  2, 87, 87, 87, 87,
-+   87, 87, 87, 87, 87, 87,  2,  2,  2,  2,  2,  2, 12, 12, 12, 12,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 12, 12, 12, 12,
-+   12, 12, 12,  2,  2,  2,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12,  2,  2,  2,  2, 13, 13, 13, 13,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2, 13, 13, 13, 13,
-+   13, 13, 13, 13, 13, 13,  2,  2,  2,  2,  2,  2, 19, 19, 19, 19,
-+   19, 19, 19,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  4,
-+    4,  4,  4,  4,  2,  2,  2,  2,  2, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14,  2, 14, 14, 14, 14, 14,  2, 14,  2, 14, 14,  2, 14,
-+   14,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  3,  3,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  0,  2,  2,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-+    3,  3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  1,  1,  1,  1,
-+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  6,  6,  0,  0,  0,  2,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  2,  0,  0,  0,  0,  2,  2,  2,  2,  3,  3,  3,  3,
-+    3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  0,  2,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17,  0,  0,  2,  2, 12, 12,
-+   12, 12, 12, 12,  2,  2, 12, 12, 12, 12, 12, 12,  2,  2, 12, 12,
-+   12, 12, 12, 12,  2,  2, 12, 12, 12,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2, 49, 49, 49, 49,
-+   49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49, 49, 49,
-+   49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-+   49, 49, 49,  2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
-+   49, 49, 49, 49, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49, 49, 49,
-+   49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2,  2, 49, 49, 49, 49,
-+   49, 49, 49, 49, 49, 49, 49,  2,  2,  2,  2,  2,  0,  0,  0,  2,
-+    2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  2,  9,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  2, 71, 71, 71, 71,
-+   71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
-+   71, 71, 71, 71, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67, 67, 67,
-+   67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 42, 42, 42, 42,
-+   42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2, 42, 42, 42, 41, 41, 41, 41,
-+   41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
-+   41, 41, 41, 41, 41, 41, 41,  2,  2,  2,  2,  2,118,118,118,118,
-+  118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,
-+  118,118,118,118,118,118,118,  2,  2,  2,  2,  2, 53, 53, 53, 53,
-+   53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
-+   53, 53, 53, 53, 53, 53, 53, 53, 53, 53,  2, 53, 59, 59, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+    2,  2,  2,  2, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
-+   59, 59,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 40, 40, 40, 40,
-+   40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51, 51, 51,
-+   51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50, 50, 50,
-+   50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
-+   50, 50, 50, 50, 50, 50, 50, 50, 50, 50,  2,  2, 50, 50, 50, 50,
-+   50, 50, 50, 50, 50, 50,  2,  2,  2,  2,  2,  2,135,135,135,135,
-+  135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
-+    2,  2,  2,  2,135,135,135,135,135,135,135,135,135,135,135,135,
-+  135,135,135,135,135,135,135,135,  2,  2,  2,  2,106,106,106,106,
-+  106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
-+  106,106,106,106,  2,  2,  2,  2,  2,  2,  2,  2,104,104,104,104,
-+  104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,104,110,110,110,110,
-+  110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-+  110,110,110,  2,  2,  2,  2,  2,  2,  2,  2,  2,110,110,110,110,
-+  110,110,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,110,110,110,110,
-+  110,110,110,110,  2,  2,  2,  2,  2,  2,  2,  2, 47, 47, 47, 47,
-+   47, 47,  2,  2, 47,  2, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
-+   47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
-+   47, 47,  2, 47, 47,  2,  2,  2, 47,  2,  2, 47, 81, 81, 81, 81,
-+   81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
-+   81, 81,  2, 81, 81, 81, 81, 81, 81, 81, 81, 81,120,120,120,120,
-+  120,120,120,120,120,120,120,120,120,120,120,120,116,116,116,116,
-+  116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
-+  116,116,116,116,116,116,116,116,116,116,116,  2,  2,  2,  2,  2,
-+    2,  2,  2,116,116,116,116,116,116,116,116,116,128,128,128,128,
-+  128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,  2,
-+  128,128,  2,  2,  2,  2,  2,128,128,128,128,128, 66, 66, 66, 66,
-+   66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
-+   66, 66, 66, 66, 66, 66, 66, 66,  2,  2,  2, 66, 72, 72, 72, 72,
-+   72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
-+   72, 72, 72, 72, 72, 72,  2,  2,  2,  2,  2, 72, 98, 98, 98, 98,
-+   98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
-+   97, 97, 97, 97,  2,  2,  2,  2, 97, 97, 97, 97,  2,  2, 97, 97,
-+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 57, 57, 57, 57,
-+    2, 57, 57,  2,  2,  2,  2,  2, 57, 57, 57, 57, 57, 57, 57, 57,
-+    2, 57, 57, 57,  2, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
-+   57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
-+   57, 57,  2,  2, 57, 57, 57,  2,  2,  2,  2, 57, 57, 57, 57, 57,
-+   57, 57, 57, 57, 57,  2,  2,  2,  2,  2,  2,  2, 88, 88, 88, 88,
-+   88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,117,117,117,117,
-+  117,117,117,117,117,117,117,117,117,117,117,117,112,112,112,112,
-+  112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,
-+  112,112,112,  2,  2,  2,  2,112,112,112,112,112,112,112,112,112,
-+  112,112,112,  2,  2,  2,  2,  2,  2,  2,  2,  2, 78, 78, 78, 78,
-+   78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
-+   78, 78,  2,  2,  2, 78, 78, 78, 78, 78, 78, 78, 83, 83, 83, 83,
-+   83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
-+   83, 83,  2,  2, 83, 83, 83, 83, 83, 83, 83, 83, 82, 82, 82, 82,
-+   82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,  2,
-+    2,  2,  2,  2, 82, 82, 82, 82, 82, 82, 82, 82,122,122,122,122,
-+  122,122,122,122,122,122,122,122,122,122,122,122,122,122,  2,  2,
-+    2,  2,  2,  2,  2,122,122,122,122,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,122,122,122,122,122,122,122, 89, 89, 89, 89,
-+   89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
-+   89, 89, 89, 89, 89,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,
-+  130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,130,130,130,  2,
-+    2,  2,  2,  2,  2,  2,130,130,130,130,130,130,  0,  0,  0,  0,
-+    0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  1,  1,  1,  1,
-+    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-+    3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 94, 94, 94,
-+   94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
-+   94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2, 94, 94,
-+   94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,101,101,
-+  101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-+  101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,101,101,
-+  101,101,101,101,101,101,  2,  2,  2,  2,  2,  2, 96, 96, 96, 96,
-+   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-+   96,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-+   96, 96, 96,  2,  2,  2,  2,  2,  2,  2,  2,  2,111,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+  111,111,111,  2,  2,  2,  2,  2,  2,  2,  2,  2,100,100,100,100,
-+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+  100,100,100,100,100,100,100,100,100,100,  2,  2,  2, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,108,108,108,108,
-+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,  2,108,
-+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
-+  108,108,108,108,108,108,108,108,108,108,108,  2,129,129,129,129,
-+  129,129,129,  2,129,  2,129,129,129,129,  2,129,129,129,129,129,
-+  129,129,129,129,129,129,129,129,129,129,  2,129,129,129,129,129,
-+  129,129,129,129,129,129,  2,  2,  2,  2,  2,  2,109,109,109,109,
-+  109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
-+  109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,109,109,
-+  109,109,109,109,109,109,  2,  2,  2,  2,  2,  2,107,107,107,107,
-+    2,107,107,107,107,107,107,107,107,  2,  2,107,107,  2,  2,107,
-+  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
-+  107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,107,107,
-+    2,107,107,107,107,107,  2,  1,107,107,107,107,107,107,107,107,
-+  107,  2,  2,107,107,  2,  2,107,107,107,  2,  2,107,  2,  2,  2,
-+    2,  2,  2,107,  2,  2,  2,  2,  2,107,107,107,107,107,107,107,
-+    2,  2,107,107,107,107,107,107,107,  2,  2,  2,107,107,107,107,
-+  107,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,137,137,137,137,
-+  137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
-+  137,137,137,137,137,137,  2,137,  2,137,137,137,124,124,124,124,
-+  124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,
-+  124,124,124,124,  2,  2,  2,  2,  2,  2,  2,  2,124,124,124,124,
-+  124,124,124,124,124,124,  2,  2,  2,  2,  2,  2,123,123,123,123,
-+  123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,
-+  123,123,  2,  2,123,123,123,123,123,123,123,123,123,123,123,123,
-+  123,123,123,123,123,123,123,123,123,123,  2,  2,114,114,114,114,
-+  114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,
-+  114,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,114,114,114,114,
-+  114,114,114,114,114,114,  2,  2,  2,  2,  2,  2, 32, 32, 32, 32,
-+   32, 32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,102,102,102,102,
-+  102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
-+  102,102,102,102,102,  2,  2,  2,  2,  2,  2,  2,102,102,102,102,
-+  102,102,102,102,102,102,  2,  2,  2,  2,  2,  2,126,126,126,126,
-+  126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
-+  126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,126,126,
-+  126,126,126,126,126,126,126,126,  2,  2,  2,  2,  4,  4,  4,  4,
-+    4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,125,125,125,125,
-+  125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,  5,  5,  5,  5,
-+    5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  6,  6,  6,  6,
-+    6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7,  7,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,121,121,121,121,
-+  121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-+  121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,133,133,133,133,
-+  133,133,133,133,133,  2,133,133,133,133,133,133,133,133,133,133,
-+  133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-+  133,133,133,  2,133,133,133,133,133,133,133,133,133,133,133,133,
-+  133,133,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,133,133,133,133,
-+  133,133,133,133,133,133,133,133,133,  2,  2,  2,134,134,134,134,
-+  134,134,134,134,134,134,134,134,134,134,134,134,  2,  2,134,134,
-+  134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
-+  134,134,134,134,  2,134,134,134,134,134,134,134,134,134,134,134,
-+  134,134,134,  2,  2,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
-+    8,  8,  8,  2,  8,  8,  2,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-+    8,  8,  8,  2,  2,  2,  8,  2,  8,  8,  2,  8,  8,  8,  8,  8,
-+    8,  8,  8,  8,  2,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
-+    8,  8,  8,  8,  8,  8,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
-+    9,  9,  2,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  2,  9,
-+    9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10,
-+   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
-+   10, 10, 10, 10, 10,  2,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
-+   22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63, 63, 63,
-+   63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
-+   63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63, 63, 63,
-+   63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,  2, 63, 63, 63, 63,
-+   63,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 63, 63, 63, 63,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 80, 80, 80, 80,
-+   80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
-+   80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,  2, 80, 80, 80, 80,
-+   80, 80, 80, 80, 80,  2,  2,  2,  2,  2,  2,  2,127,127,127,127,
-+  127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
-+  127,127,127,  2,  2,  2,  2,  2,  2,  2,  2,  2, 79, 79, 79, 79,
-+   79, 79, 79, 79, 79,  2,  2,  2,  2,  2,  2,  2,115,115,115,115,
-+  115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
-+  115,115,115,115,115,115,115,115,115,115,115,  2,115,115,115,115,
-+  115,115,115,115,115,115,  2,  2,  2,  2,115,115,103,103,103,103,
-+  103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,
-+  103,103,103,103,103,103,103,103,103,103,  2,  2,103,103,103,103,
-+  103,103,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,119,119,119,119,
-+  119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-+  119,119,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,119,119,119,119,
-+  119,119,119,119,119,119,  2,119,119,119,119,119,119,119,  2,119,
-+  119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-+  119,119,119,119,  2,  2,  2,  2,  2,119,119,119, 11, 11, 11, 11,
-+   11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2,  2, 99, 99, 99, 99,
-+   99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-+   99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99, 99, 99, 99, 99,
-+   99, 99, 99, 99,  2,  2,  2,  2,  2,  2,  2, 99,136, 12,  0,  0,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,136,136,136,136,
-+  136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-+  136,136,136,136,  2,  2,  2,  2,  2,  2,  2,  2,136,136,136,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 17, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2, 15, 15, 15,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+   17, 17, 17, 17,  2,  2,  2,  2,  2,  2,  2,  2,105,105,105,105,
-+  105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-+  105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,105,105,
-+  105,105,105,105,105,105,105,105,105,  2,  2,  2,105,105,105,105,
-+  105,105,105,105,105,  2,  2,  2,  2,  2,  2,  2,105,105,105,105,
-+  105,105,105,105,105,105,  2,  2,105,105,105,105,  0,  0,  0,  0,
-+    0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  0,
-+    0,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
-+    9,  9,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  2,  2,  0,  2,
-+    2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  2,  0,  2,  0,  0,  0,  0,  0,  0,  0,
-+    2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  2,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,
-+    0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
-+    0,  2,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,131,131,131,131,
-+  131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
-+  131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,131,131,131,131,131,  2,131,131,131,
-+  131,131,131,131,131,131,131,131,131,131,131,131, 56, 56, 56, 56,
-+   56, 56, 56,  2, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
-+   56, 56, 56, 56, 56,  2,  2, 56, 56, 56, 56, 56, 56, 56,  2, 56,
-+   56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2, 13, 13, 13, 13,
-+   13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2, 13, 13, 13, 13,
-+   13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2, 14,113,113,113,113,
-+  113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+  113,  2,  2,113,113,113,113,113,113,113,113,113,113,113,113,113,
-+  113,113,113,  2,  2,  2,  2,  2,  2,  2,  2,  2,132,132,132,132,
-+  132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-+  132,132,132,132,132,132,132,132,  2,  2,  2,  2,132,132,132,132,
-+  132,132,132,132,132,132,  2,  2,  2,  2,132,132,  0,  0,  0,  0,
-+    0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  3,  3,  3,  3,
-+    2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  3,  3,  2,
-+    3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,
-+    3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,  3,  2,
-+    2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,  3,  2,
-+    3,  2,  2,  3,  2,  3,  2,  3,  2,  3,  2,  3,  2,  3,  3,  2,
-+    3,  2,  2,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  2,
-+    3,  3,  3,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,  3,  3,
-+    2,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 15,  0,  0,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,
-+    0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,
-+    2,  0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,
-+    2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  2,  2,  0,  0,  0,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13, 13, 13,
-+   13, 13, 13,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13, 13, 13,
-+   13,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13,  2,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  2,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  1,
-+    2,  3,  4,  5,  6,  0,  0,  0,  0,  7,  8,  9, 10, 11,  0, 12,
-+    0,  0,  0,  0, 13,  0,  0, 14,  0,  0,  0,  0,  0,  0,  0,  0,
-+   15, 16,  0, 17, 18, 19,  0,  0,  0, 20, 21, 22,  0, 23,  0, 24,
-+    0, 25,  0, 26,  0,  0,  0,  0,  0, 27, 28,  0, 29,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 30, 31,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0, 32, 33, 34, 35, 36, 37, 38, 39, 40,  0,  0,  0,
-+   41,  0, 42, 43, 44, 45, 46, 47, 48,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 49,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 50, 51, 52,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   53, 54, 55, 56, 57, 58, 59, 60, 61, 62,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 63,  0,
-+   64,  0,  0,  0,  0,  0,  0,  0,  0, 65,  0,  0,  0,  0, 66,  0,
-+    0,  0, 67,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0, 68, 69, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 71, 72, 73, 74,
-+   75, 76, 77, 78, 79,  0,
-+};
-+static const uint16_t
-+_hb_ucd_u16[11168] =
-+{
-+     0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
-+    13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
-+    13,  13,  13,  24,  25,  11,  11,  11,  11,  26,  11,  27,  28,  29,  30,  31,
-+    32,  32,  32,  32,  32,  32,  32,  33,  34,  35,  36,  11,  37,  38,  13,  39,
-+     9,   9,   9,  11,  11,  11,  13,  13,  40,  13,  13,  13,  41,  13,  13,  13,
-+    13,  13,  13,  42,   9,  43,  11,  11,  44,  45,  32,  46,  47,  48,  49,  50,
-+    51,  52,  48,  48,  53,  32,  54,  55,  48,  48,  48,  48,  48,  56,  57,  58,
-+    59,  60,  48,  32,  61,  48,  48,  48,  48,  48,  62,  63,  64,  48,  65,  66,
-+    48,  67,  68,  69,  48,  70,  71,  72,  72,  72,  48,  73,  72,  74,  75,  32,
-+    76,  48,  48,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-+    90,  83,  84,  91,  92,  93,  94,  95,  96,  97,  84,  98,  99, 100,  88, 101,
-+   102,  83,  84, 103, 104, 105,  88, 106, 107, 108, 109, 110, 111, 112,  94, 113,
-+   114, 115,  84, 116, 117, 118,  88, 119, 120, 115,  84, 121, 122, 123,  88, 124,
-+   125, 115,  48, 126, 127, 128,  88, 129, 130, 131,  48, 132, 133, 134,  94, 135,
-+   136,  48,  48, 137, 138, 139,  72,  72, 140,  48, 141, 142, 143, 144,  72,  72,
-+   145, 146, 147, 148, 149,  48, 150, 151, 152, 153,  32, 154, 155, 156,  72,  72,
-+    48,  48, 157, 158, 159, 160, 161, 162, 163, 164,   9,   9, 165,  11,  11, 166,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48, 167, 168,  48,  48, 167,  48,  48, 169, 170, 171,  48,  48,
-+    48, 170,  48,  48,  48, 172, 173, 174,  48, 175,   9,   9,   9,   9,   9, 176,
-+   177,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48, 178,  48, 179, 180,  48,  48,  48,  48, 181, 182,
-+   183, 184,  48, 185,  48, 186, 183, 187,  48,  48,  48, 188, 189, 190, 191, 192,
-+   193, 191,  48,  48, 194,  48,  48, 195, 196,  48, 197,  48,  48,  48,  48, 198,
-+    48, 199, 200, 201, 202,  48, 203, 204,  48,  48, 205,  48, 206, 207, 208, 208,
-+    48, 209,  48,  48,  48, 210, 211, 212, 191, 191, 213, 214,  72,  72,  72,  72,
-+   215,  48,  48, 216, 217, 159, 218, 219, 220,  48, 221,  64,  48,  48, 222, 223,
-+    48,  48, 224, 225, 226,  64,  48, 227, 228,   9,   9, 229, 230, 231, 232, 233,
-+    11,  11, 234,  27,  27,  27, 235, 236,  11, 237,  27,  27,  32,  32,  32, 238,
-+    13,  13,  13,  13,  13,  13,  13,  13,  13, 239,  13,  13,  13,  13,  13,  13,
-+   240, 241, 240, 240, 241, 242, 240, 243, 244, 244, 244, 245, 246, 247, 248, 249,
-+   250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 260,  72, 261, 262, 263,
-+   264, 265, 266, 267, 268, 269, 270, 270, 271, 272, 273, 208, 274, 275, 208, 276,
-+   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-+   278, 208, 279, 208, 208, 208, 208, 280, 208, 281, 277, 282, 208, 283, 284, 208,
-+   208, 208, 285,  72, 286,  72, 269, 269, 269, 287, 208, 208, 208, 208, 288, 269,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 289, 290, 208, 208, 291,
-+   208, 208, 208, 208, 208, 208, 292, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-+   208, 208, 208, 208, 208, 208, 293, 294, 269, 295, 208, 208, 296, 277, 297, 277,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-+   277, 277, 277, 277, 277, 277, 277, 277, 298, 299, 277, 277, 277, 300, 277, 301,
-+   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-+   208, 208, 208, 277, 302, 208, 208, 303, 208, 304, 208, 208, 208, 208, 208, 208,
-+     9,   9, 305,  11,  11, 306, 307, 308,  13,  13,  13,  13,  13,  13, 309, 310,
-+    11,  11, 311,  48,  48,  48, 312, 313,  48, 314, 315, 315, 315, 315,  32,  32,
-+   316, 317, 318, 319, 320,  72,  72,  72, 208, 321, 208, 208, 208, 208, 208, 322,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323,  72, 324,
-+   325, 326, 327, 328, 136,  48,  48,  48,  48, 329, 177,  48,  48,  48,  48, 330,
-+   331,  48,  48, 136,  48,  48,  48,  48, 199, 332,  48,  71, 208, 208, 322,  48,
-+   208, 333, 334, 208, 335, 336, 208, 208, 334, 208, 208, 336, 208, 208, 208, 208,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 198, 208, 208, 208, 208,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  72,
-+    48, 337,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48, 150, 208, 208, 208, 285,  48,  48, 227,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+   338,  48, 339,  72,  13,  13, 340, 341,  13, 342,  48,  48,  48,  48, 343, 344,
-+    31, 345, 346, 347,  13,  13,  13, 348, 349, 350, 351, 352, 353,  72,  72, 354,
-+   355,  48, 356, 357,  48,  48,  48, 358, 359,  48,  48, 360, 361, 191,  32, 362,
-+    64,  48, 363,  48, 364, 365,  48, 150,  76,  48,  48, 366, 367, 368, 369, 370,
-+    48,  48, 371, 372, 373, 374,  48, 375,  48,  48,  48, 376, 377, 378, 379, 380,
-+   381, 382, 315,  11,  11, 383, 384,  11,  11,  11,  11,  11,  48,  48, 385, 191,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 386,  48, 387,  48,  48, 205,
-+   388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388,
-+   388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388,
-+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
-+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
-+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48, 203,  48,  48,  48,  48,  48,  48, 206,  72,  72,
-+   390, 391, 392, 393, 394,  48,  48,  48,  48,  48,  48, 395, 396, 397,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48, 398,  72,  48,  48,  48,  48, 399,  48,  48, 400,  72,  72, 401,
-+    32, 402,  32, 403, 404, 405, 406, 407,  48,  48,  48,  48,  48,  48,  48, 408,
-+   409,   2,   3,   4,   5, 410, 411, 412,  48, 413,  48, 199, 414, 415, 416, 417,
-+   418,  48, 171, 419, 203, 203,  72,  72,  48,  48,  48,  48,  48,  48,  48,  71,
-+   420, 269, 269, 421, 270, 270, 270, 422, 423, 324, 424,  72,  72, 208, 208, 425,
-+    72,  72,  72,  72,  72,  72,  72,  72,  48, 150,  48,  48,  48, 100, 426, 427,
-+    48,  48, 428,  48, 429,  48,  48, 430,  48, 431,  48,  48, 432, 433,  72,  72,
-+     9,   9, 434,  11,  11,  48,  48,  48,  48, 203, 191,   9,   9, 435,  11, 436,
-+    48,  48, 400,  48,  48,  48, 437,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48, 314,  48, 198, 400,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+   438,  48,  48, 439,  48, 440,  48, 441,  48, 199, 442,  72,  72,  72,  48, 443,
-+    48, 444,  48, 445,  72,  72,  72,  72,  48,  48,  48, 446, 269, 447, 269, 269,
-+   448, 449,  48, 450, 451, 452,  48, 453,  48, 454,  72,  72, 455,  48, 456, 457,
-+    48,  48,  48, 458,  48, 459,  48, 460,  48, 461, 462,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48, 195,  72,  72,  72,   9,   9,   9, 463,  11,  11,  11, 464,
-+    48,  48, 465, 191,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72, 269, 466,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48, 454, 467,  48,  62, 468,  72,  72,  72,  72,  72,  72,  72,  72,  48, 314,
-+   469,  48,  48, 470, 471, 447, 472, 473, 220,  48,  48, 474, 475,  48, 195, 191,
-+   476,  48, 477, 478, 479,  48,  48, 480, 220,  48,  48, 481, 482, 483, 484, 485,
-+    48,  97, 486, 487,  72,  72,  72,  72, 488, 489, 490,  48,  48, 491, 492, 191,
-+   493,  83,  84, 494, 495, 496, 497, 498,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48, 499, 500, 501,  72,  72,  48,  48,  48, 502, 503, 191,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  48,  48, 504, 505, 506, 507,  72,  72,
-+    48,  48,  48, 508, 509, 191, 510,  72,  48,  48, 511, 512, 191,  72,  72,  72,
-+    48, 172, 513, 514,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48, 486, 515,  72,  72,  72,  72,  72,  72,   9,   9,  11,  11, 147, 516,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72, 517,  48,  48, 518, 519,  72,
-+   520,  48,  48, 521, 522, 523,  48,  48, 524, 525, 526,  72,  48,  48,  48, 195,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    84,  48, 504, 527, 528, 147, 174, 529,  48, 530, 531, 532,  72,  72,  72,  72,
-+   533,  48,  48, 534, 535, 191, 536,  48, 537, 538, 191,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  48, 539,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72, 269, 540, 541, 542,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48, 206,  72,  72,  72,  72,  72,  72,
-+   270, 270, 270, 270, 270, 270, 543, 544,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48, 386,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48, 199, 545,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48, 314,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48, 195,  48, 199, 368,  72,  72,  72,  72,  72,  72,  48, 203, 546,
-+    48,  48,  48, 547, 548, 549, 550, 551,  48,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,   9,   9,  11,  11, 269, 552,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48, 553, 554, 555, 555, 556, 557,  72,  72,  72,  72, 558,  72,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 400,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 559,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48, 199,  72,  72,  72, 559, 560,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 205,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48,  48,  48,  71, 150, 195, 561, 562,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323,
-+   208, 208, 563, 208, 208, 208, 564, 565, 566, 208, 567, 208, 208, 208, 568,  72,
-+   208, 208, 208, 208, 569,  72,  72,  72,  72,  72,  72,  72,  72,  72, 269, 570,
-+   208, 208, 208, 208, 208, 285, 269, 451,  72,  72,  72,  72,  72,  72,  72,  72,
-+     9, 571,  11, 572, 573, 574, 240,   9, 575, 576, 577, 578, 579,   9, 571,  11,
-+   580, 581,  11, 582, 583, 584, 585,   9, 586,  11,   9, 571,  11, 572, 573,  11,
-+   240,   9, 575, 585,   9, 586,  11,   9, 571,  11, 587,   9, 588, 589, 590, 591,
-+    11, 592,   9, 593, 594, 595, 596,  11, 597,   9, 598,  11, 599, 600, 600, 600,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208,
-+    32,  32,  32, 601,  32,  32, 602, 603, 604, 605,  45,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+   606, 607, 608,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48, 150, 609, 610,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  48,  48, 611, 612,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 613, 614,  72,  72,
-+     9,   9, 575,  11, 615, 368,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72, 484, 269, 269, 616, 617,  72,  72,  72,  72,
-+   484, 269, 618, 619,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+   620,  48, 621, 622, 623, 624, 625, 626, 627, 205, 628, 205,  72,  72,  72, 629,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+   208, 208, 324, 208, 208, 208, 208, 208, 208, 322, 333, 630, 630, 630, 208, 323,
-+   174, 208, 208, 208, 208, 208, 631, 208, 208, 208, 631,  72,  72,  72, 632, 208,
-+   633, 208, 208, 324, 568, 634, 323,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 635,
-+   208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 323, 631, 286,
-+   208, 208, 208, 208, 208, 208, 208, 322, 208, 208, 208, 208, 208, 568, 324,  72,
-+   324, 208, 208, 208, 636, 175, 208, 208, 636, 208, 637,  72,  72,  72,  72,  72,
-+   638, 208, 208, 208, 208, 208, 208, 639, 208, 208, 640, 208, 641, 208, 208, 208,
-+   208, 208, 208, 208, 208, 322, 637, 642, 633, 323,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 314,  72,  72,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48, 204,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48, 203,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 643,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 100,  72,
-+    48, 203,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,
-+   644,  72, 645, 645, 645, 645, 645, 645,  72,  72,  72,  72,  72,  72,  72,  72,
-+    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  72,
-+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
-+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 646,
-+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389,
-+   389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, 647,
-+     0,   0,   0,   0,   1,   2,   1,   2,   0,   0,   3,   3,   4,   5,   4,   5,
-+     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
-+     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   6,   0,   0,   7,   0,
-+     8,   8,   8,   8,   8,   8,   8,   9,  10,  11,  12,  11,  11,  11,  13,  11,
-+    14,  14,  14,  14,  14,  14,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,
-+    14,  14,  14,  16,  17,  18,  17,  17,  19,  20,  21,  21,  22,  21,  23,  24,
-+    25,  26,  27,  27,  28,  29,  27,  30,  27,  27,  27,  27,  27,  31,  27,  27,
-+    32,  33,  33,  33,  34,  27,  27,  27,  35,  35,  35,  36,  37,  37,  37,  38,
-+    39,  39,  40,  41,  42,  43,  44,  45,  45,  45,  27,  46,  45,  47,  48,  27,
-+    49,  49,  49,  49,  49,  50,  51,  49,  52,  53,  54,  55,  56,  57,  58,  59,
-+    60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,
-+    76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,  91,
-+    92,  93,  94,  95,  96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107,
-+   108, 109, 110, 110, 111, 112, 113, 110, 114, 115, 116, 117, 118, 119, 120, 121,
-+   122, 123, 123, 124, 123, 125,  45,  45, 126, 127, 128, 129, 130, 131,  45,  45,
-+   132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137,  45,  45,
-+   138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141,
-+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
-+   143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143,
-+   143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153,
-+   154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
-+   154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
-+   154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159,
-+   160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170,
-+   171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176,
-+   177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168,
-+   188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 195,  45,  45,  45,  45,
-+   196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201,
-+   202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211,
-+     4,   4, 212,   4,   4, 213, 214, 215,   4,   4,   4, 216,   8,   8,   8, 217,
-+     4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,   4,
-+    11, 218,  11,  11, 218, 219,  11, 220,  11,  11,  11, 221, 221, 222,  11, 223,
-+   224,   0,   0,   0,   0,   0, 225, 226, 227, 228,   0,   0,  45,   8,   8, 229,
-+     0,   0, 230, 231, 232,   0,   4,   4, 233,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0, 234,  45, 235,  45,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0, 237,   0, 238,   0,   0,   0,   0,   0,   0,
-+   239, 239, 240, 239, 239, 240,   4,   4, 241, 241, 241, 241, 241, 241, 241, 242,
-+   139, 139, 140, 243, 243, 243, 244, 245, 143, 246, 247, 247, 247, 247,  14,  14,
-+     0,   0,   0,   0,   0,  45,  45,  45, 248, 249, 248, 248, 248, 248, 248, 250,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251,  45, 252,
-+   253,   0, 254, 255, 256, 257, 257, 257, 257, 258, 259, 260, 260, 260, 260, 261,
-+   262, 263, 263, 264, 142, 142, 142, 142, 265,   0, 263, 266,   0,   0, 267, 260,
-+   142, 265,   0,   0,   0,   0, 142, 268,   0,   0,   0,   0,   0, 260, 260, 269,
-+   260, 260, 260, 260, 260, 270,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251,   0,   0,   0,   0,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,  45,
-+   271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271,
-+   271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271, 271,
-+   271, 271, 271, 271, 271, 271, 271, 271, 272, 271, 271, 271, 273, 274, 274, 274,
-+   275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
-+   275, 275, 276,  45,  14,  14,  14,  14,  14,  14, 277, 277, 277, 277, 277, 278,
-+     0,   0, 279,   4,   4,   4,   4,   4, 280,   4,   4,   4, 281,  45,  45, 282,
-+   283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290,  49,  49,
-+   291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299,
-+   300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308,
-+   309, 310, 247,   4,   4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314,
-+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
-+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
-+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
-+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 315, 142, 316, 142, 142, 317,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319,  45,  45,
-+   320, 321,  21, 322, 323,  27,  27,  27,  27,  27,  27,  27, 324,  47,  27,  27,
-+    27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,  27,
-+    27,  27,  27, 325,  45,  27,  27,  27,  27, 326,  27,  27, 327,  45,  45, 328,
-+     8, 285, 329,   0,   0, 330, 331, 332,  27,  27,  27,  27,  27,  27,  27, 333,
-+   334,   0,   1,   2,   1,   2, 335, 259, 260, 336, 142, 265, 337, 338, 339, 340,
-+   341, 342, 343, 344, 345, 345,  45,  45, 342, 342, 342, 342, 342, 342, 342, 346,
-+   347,   0,   0, 348,  11,  11,  11,  11, 349, 252, 350,  45,  45,   0,   0, 351,
-+    45,  45,  45,  45,  45,  45,  45,  45, 352, 353, 354, 354, 354, 355, 356, 252,
-+   357, 357, 358, 359, 360, 361, 361, 362, 363, 364, 365, 365, 366, 367,  45,  45,
-+   368, 368, 368, 368, 368, 369, 369, 369, 370, 371, 372, 373, 373, 374, 373, 375,
-+   376, 376, 377, 378, 378, 378, 379,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380,
-+   380, 380, 380, 381, 380, 382, 383,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   384, 385, 385, 386, 387, 388, 389, 389, 390, 391, 392,  45,  45,  45, 393, 394,
-+   395, 396, 397, 398,  45,  45,  45,  45, 399, 399, 400, 401, 400, 402, 400, 400,
-+   403, 404, 405, 406, 407, 407, 408, 408, 409, 409,  45,  45, 410, 410, 411, 412,
-+   413, 413, 413, 414, 415, 416, 417, 418, 419, 420, 421,  45,  45,  45,  45,  45,
-+   422, 422, 422, 422, 423,  45,  45,  45, 424, 424, 424, 425, 424, 424, 424, 426,
-+     0,   0, 427, 285,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  27, 428,  45,  45,  45,  45,  45,  45,  45,  45,
-+     8,   8, 429,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  27, 430,
-+   431, 431, 431, 431, 432, 433, 431, 434, 435, 435, 435, 435, 436, 437, 438, 439,
-+   440, 440, 440, 441, 442, 443, 443, 444, 445, 445, 445, 445, 446, 445, 447, 448,
-+   449, 450, 449, 451,  45,  45,  45,  45, 452, 453, 454, 455, 455, 455, 456, 457,
-+   458, 459, 460, 461, 462, 463, 464, 465,  45,  45,  45,  45,  45,  45,  45,  45,
-+   466, 466, 466, 466, 466, 467,  45,  45, 468, 468, 468, 468, 469, 470,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45, 471, 471, 471, 472, 471, 473,  45,  45,
-+   474, 474, 474, 474, 475, 476, 477,  45, 478, 478, 478, 479, 480,  45,  45,  45,
-+   481, 482, 483, 481,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    17,  17,  17, 484,  45,  45,  45,  45,  45,  45, 485, 485, 485, 485, 485, 486,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 487, 488, 488, 487, 489,  45,
-+    14,  14,  14,  14, 490,  49,  49,  49,  49,  49, 491,  45, 492, 492, 492, 493,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   494, 495, 495, 496, 497, 495, 498, 499, 499, 500, 501, 502,  45,  45,  45,  45,
-+   503, 139, 139, 504, 505, 506, 507,  11, 349, 508, 509,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 510, 511,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 512, 512, 512, 513,
-+   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
-+   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
-+   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
-+   514, 514, 514, 514, 514, 514, 514, 514, 514, 515,  45,  45,  45,  45,  45,  45,
-+   514, 514, 514, 514, 514, 514, 516, 517, 514, 514, 514, 514, 514, 514, 514, 514,
-+   514, 514, 514, 514, 518,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519,
-+   519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519,
-+   519, 519, 520, 521,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522,
-+   522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522,
-+   522, 522, 522, 522, 523,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-+   277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-+   277, 277, 277, 524, 525, 526, 527,  45,  45,  45,  45,  45,  45, 528, 529, 530,
-+   531, 531, 531, 531, 532, 533, 534, 535, 531,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45, 536, 536, 536, 536, 536, 537,  45,  45,  45,  45,  45,  45,
-+   538, 538, 538, 538, 539, 538, 538, 538, 540, 538,  45,  45,  45,  45, 541,  45,
-+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
-+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
-+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
-+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 543,
-+   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 544,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   545, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
-+   257, 546,  45,  45,  45, 547, 548, 142, 142, 142, 142, 142, 142, 142, 142, 142,
-+   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 317,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   549, 549, 549, 549, 549, 549, 550, 551, 552, 553, 267,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 554,
-+     0,   0, 555,   0,   0,   0, 556, 557, 558,   0, 559,   0,   0,   0, 560,  45,
-+    11,  11,  11,  11, 561,  45,  45,  45,  45,  45,  45,  45,  45,  45,   0, 267,
-+     0,   0,   0,   0,   0, 234,   0, 560,  45,  45,  45,  45,  45,  45,  45,  45,
-+     0,   0,   0,   0,   0, 225,   0,   0,   0, 562, 563, 564, 565,   0,   0,   0,
-+   566, 567,   0, 568, 569, 570,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 238,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 571,   0,   0,   0,
-+   572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572,
-+   572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572,
-+   572, 572, 572, 572, 572, 572, 572, 572, 573, 574, 575,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   576, 577, 578,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   248, 248, 579, 318, 580,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  21,  21,  21, 581,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 584,  45,  45,
-+   585, 585, 585, 585, 586, 587,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45, 334,   0,   0,   0, 588,  45,  45,  45,  45,
-+   334,   0,   0, 589,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   590,  27, 591, 592, 593, 594, 595, 596, 597, 598, 599, 598,  45,  45,  45, 324,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+     0,   0, 252,   0,   0,   0,   0,   0,   0, 267, 227, 334, 334, 334,   0, 554,
-+   600,   0,   0,   0,   0,   0, 600,   0,   0,   0, 600,  45,  45,  45, 601,   0,
-+   602,   0,   0, 252, 560, 603, 554,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 554, 600, 235,
-+     0,   0,   0,   0,   0,   0,   0, 267,   0,   0,   0,   0,   0, 560, 252,  45,
-+   252,   0,   0,   0, 427, 285,   0,   0, 427,   0, 589,  45,  45,  45,  45,  45,
-+   604,   0,   0,   0,   0,   0,   0, 605,   0,   0, 606,   0, 607,   0,   0,   0,
-+     0,   0,   0,   0,   0, 267, 589, 608, 609, 554,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 610,  45,  45,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 611, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 612, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 613,  45,
-+   248, 318,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   614,  45,   0,   0,   0,   0,   0,   0,  45,  45,  45,  45,  45,  45,  45,  45,
-+     8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
-+     0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
-+  1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
-+     0,1219,1226,1227,1228,1229,1233,   0,   0,1267,1268,1269,1273,1298,   0,1303,
-+   943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
-+     0,   0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
-+   991,1176, 993,1178, 994,1179,   0,   0,1004,1190,1005,1191,1006,1192,1014,1199,
-+  1007,   0,   0,   0,1016,1201,1020,1206,   0,1022,1208,1025,1211,1023,1209,   0,
-+     0,   0,   0,1032,1218,1037,1223,1035,1221,   0,   0,   0,1044,1230,1045,1231,
-+  1049,1235,   0,   0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
-+  1069,1255,1077,1264,1074,1261,   0,   0,1083,1270,1084,1271,1085,1272,1088,1275,
-+  1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1053,1239,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1093,
-+  1280,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 949,1134,1010,
-+  1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366,   0,1320,1347,
-+  1418,1419,1323,1350,   0,   0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
-+  1202,   0,   0,   0, 987,1172,   0,   0,1031,1217,1321,1348,1322,1349,1338,1365,
-+   950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
-+  1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263,   0,   0, 997,1182,
-+     0,   0,   0,   0,   0,   0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
-+  1422,1423,1113,1301,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     8,   9,   0,  10,1425,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,
-+     0,   0,   0,   0,   0,1314,1427,   5,1434,1438,1443,   0,1450,   0,1455,1461,
-+  1514,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1446,1458,1468,1476,1480,1486,
-+  1517,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1489,1503,1494,1500,1508,   0,
-+     0,   0,   0,1520,1521,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1526,1528,   0,1525,   0,   0,   0,1522,   0,   0,   0,   0,1536,1532,1539,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1534,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1556,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1548,1550,   0,1547,   0,   0,   0,1567,   0,   0,   0,   0,1558,1554,1561,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,1568,1569,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,1529,1551,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1523,1545,1524,1546,   0,   0,1527,1549,   0,   0,1570,1571,1530,1552,1531,1553,
-+     0,   0,1533,1555,1535,1557,1537,1559,   0,   0,1572,1573,1544,1566,1538,1560,
-+  1540,1562,1541,1563,1542,1564,   0,   0,1543,1565,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,1606,1607,1609,1608,1610,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1613,   0,1611,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1612,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1620,   0,   0,   0,   0,   0,   0,
-+     0,1623,   0,   0,1624,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1614,1615,1616,1617,1618,1619,1621,1622,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1628,1629,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1625,1626,   0,1627,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1634,   0,   0,1635,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1630,1631,1632,   0,   0,1633,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1639,   0,   0,1638,1640,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1636,1637,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,1641,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1642,1644,1643,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1645,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1646,   0,   0,   0,   0,   0,   0,1648,1649,   0,1647,1650,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1651,1653,1652,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1654,   0,1655,1657,1656,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1659,   0,   0,   0,   0,   0,   0,   0,   0,   0,1660,   0,   0,
-+     0,   0,1661,   0,   0,   0,   0,1662,   0,   0,   0,   0,1663,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1658,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1664,   0,1665,1673,   0,1674,   0,   0,   0,   0,   0,   0,   0,
-+     0,1666,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1668,   0,   0,   0,   0,   0,   0,   0,   0,   0,1669,   0,   0,
-+     0,   0,1670,   0,   0,   0,   0,1671,   0,   0,   0,   0,1672,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1667,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,1675,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,1676,   0,1677,   0,1678,   0,1679,   0,1680,   0,
-+     0,   0,1681,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1682,   0,1683,   0,   0,
-+  1684,1685,   0,1686,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
-+   966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
-+   989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
-+  1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
-+  1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
-+  1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
-+  1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
-+  1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
-+  1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
-+  1119,1308,1122,1311,1123,1312,1186,1260,1293,1305,   0,1394,   0,   0,   0,   0,
-+   952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
-+  1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
-+  1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
-+  1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
-+  1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
-+  1409,1414,1109,1297,1117,1306,1116,1304,1112,1300,   0,   0,   0,   0,   0,   0,
-+  1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
-+  1477,1478,1729,1731,1730,1732,   0,   0,1435,1436,1733,1735,1734,1736,   0,   0,
-+  1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
-+  1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
-+  1495,1496,1777,1779,1778,1780,   0,   0,1451,1452,1781,1783,1782,1784,   0,   0,
-+  1504,1505,1785,1788,1786,1789,1787,1790,   0,1459,   0,1791,   0,1792,   0,1793,
-+  1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
-+  1467,  21,1475,  22,1479,  23,1485,  24,1493,  27,1499,  28,1507,  29,   0,   0,
-+  1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
-+  1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
-+  1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
-+  1470,1469,1822,1474,1465,   0,1473,1825,1429,1428,1426,  12,1432,   0,  26,   0,
-+     0,1315,1823,1484,1466,   0,1483,1829,1433,  13,1437,  14,1441,1826,1827,1828,
-+  1488,1487,1513,  19,   0,   0,1492,1515,1445,1444,1442,  15,   0,1831,1832,1833,
-+  1502,1501,1516,  25,1497,1498,1506,1518,1457,1456,1454,  17,1453,1313,  11,   3,
-+     0,   0,1824,1512,1519,   0,1511,1830,1449,  16,1460,  18,1464,   4,   0,   0,
-+    30,  31,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,  20,   0,   0,   0,   2,   6,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1834,1835,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1836,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1837,1839,1838,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,1840,   0,   0,   0,   0,1841,   0,   0,1842,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,1843,   0,1844,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,1845,   0,   0,1846,   0,   0,1847,   0,1848,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   937,   0,1850,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1849, 936, 938,
-+  1851,1852,   0,   0,1853,1854,   0,   0,1855,1856,   0,   0,   0,   0,   0,   0,
-+  1857,1858,   0,   0,1861,1862,   0,   0,1863,1864,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1867,1868,1869,1870,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1859,1860,1865,1866,   0,   0,   0,   0,   0,   0,1871,1872,1873,1874,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,  32,  33,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1875,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1877,   0,1878,   0,
-+  1879,   0,1880,   0,1881,   0,1882,   0,1883,   0,1884,   0,1885,   0,1886,   0,
-+  1887,   0,1888,   0,   0,1889,   0,1890,   0,1891,   0,   0,   0,   0,   0,   0,
-+  1892,1893,   0,1894,1895,   0,1896,1897,   0,1898,1899,   0,1900,1901,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,1876,   0,   0,   0,   0,   0,   0,   0,   0,   0,1902,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1904,   0,1905,   0,
-+  1906,   0,1907,   0,1908,   0,1909,   0,1910,   0,1911,   0,1912,   0,1913,   0,
-+  1914,   0,1915,   0,   0,1916,   0,1917,   0,1918,   0,   0,   0,   0,   0,   0,
-+  1919,1920,   0,1921,1922,   0,1923,1924,   0,1925,1926,   0,1927,1928,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,1903,   0,   0,1929,1930,1931,1932,   0,   0,   0,1933,   0,
-+   710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
-+   663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
-+   810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
-+   368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
-+   811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
-+   594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
-+   313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
-+   424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
-+   193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
-+   337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
-+   683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
-+   608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
-+   479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
-+   791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
-+   377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
-+   659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
-+   153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210,   0,   0,
-+   227,   0, 379,   0,   0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604,   0,
-+   661,   0, 703,   0,   0, 735, 743,   0,   0,   0, 793, 794, 795, 808, 741, 773,
-+   118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
-+   335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
-+   549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
-+   690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623,   0,   0,
-+   102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
-+   250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
-+   370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
-+   493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
-+   591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
-+   709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
-+   847, 857,  55,  65,  66, 883, 892, 916, 822, 824,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1586,   0,1605,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,
-+  1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,
-+  1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1948,1949,
-+  1950,1951,1952,1953,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,1957,1959,1958,
-+  1960,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131,
-+   132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37,
-+   157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
-+   181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
-+   197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
-+   153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
-+   836, 837, 247, 248, 249, 246, 251,  39,  40, 253, 255, 255, 838, 257, 258, 259,
-+   261, 839, 262, 263, 301, 264,  41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
-+   278, 281, 282,  42, 283, 284, 285, 286,  43, 843,  44, 289, 290, 291, 293, 934,
-+   298, 845, 845, 621, 300, 300,  45, 852, 894, 302, 304,  46, 306, 309, 310, 312,
-+   316,  48,  47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
-+   335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
-+   358, 356,  49, 363, 365, 367, 364,  50, 369, 371, 851, 376, 386, 378,  53, 381,
-+    52,  51, 140, 141, 387, 382, 614,  78, 388, 389, 390, 394, 392, 856,  54, 399,
-+   396, 402, 404, 858, 405, 401, 407,  55, 408, 409, 410, 413, 859, 415,  56, 417,
-+   860, 418,  57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
-+   437, 441, 438, 439, 442, 443, 864, 436, 449, 450,  58, 454, 453, 865, 447, 460,
-+   866, 867, 461, 466, 465, 464,  59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
-+   483, 485, 486, 871, 488, 489, 872, 873, 495, 497,  60, 498,  61,  61, 504, 505,
-+   507, 508, 511,  62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878,  63,  64,
-+   528, 880, 879, 881, 882, 530, 531, 531, 533,  66, 534,  67,  68, 884, 536, 538,
-+   541,  69, 885, 549, 886, 887, 556, 559,  70, 561, 562, 563, 888, 889, 889, 567,
-+    71, 890, 570, 571,  72, 891, 577,  73, 581, 579, 582, 893, 587,  74, 590, 592,
-+   596,  75, 895, 896,  76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
-+   853,  77, 615, 616,  79, 617, 252, 902, 903, 854, 855, 621, 622, 731,  80, 627,
-+   626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
-+   638, 643, 644, 645, 905, 907, 906,  81, 653, 654, 656, 911, 657, 908,  82,  83,
-+   909, 910,  84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675,  85,
-+   677, 678,  86, 681, 682, 912, 685, 686,  87, 689,  36, 913, 914,  88,  89, 696,
-+   702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
-+   918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762,  90,
-+   764, 922,  91, 775, 279, 780, 923, 925,  92,  93, 785, 926,  94, 927, 787, 787,
-+   789, 928, 792,  95, 796, 797, 798, 800,  96, 929, 802, 804, 806,  97,  98, 807,
-+   930,  99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+};
-+static const int16_t
-+_hb_ucd_i16[196] =
-+{
-+      0,    0,    0,    0,    1,   -1,    0,    0,    2,    0,   -2,    0,    0,    0,    0,    2,
-+      0,   -2,    0,    0,    0,    0,    0,   16,    0,    0,    0,  -16,    0,    0,    1,   -1,
-+      0,    0,    0,    1,   -1,    0,    0,    0,    0,    1,   -1,    0,    3,    3,    3,   -3,
-+     -3,   -3,    0,    0,    0, 2016,    0,    0,    0,    0,    0, 2527, 1923, 1914, 1918,    0,
-+   2250,    0,    0,    0,    0,    0,    0,  138,    0,    7,    0,    0,   -7,    0,    0,    0,
-+      1,   -1,    1,   -1,   -1,    1,   -1,    0, 1824,    0,    0,    0,    0,    0, 2104,    0,
-+   2108, 2106,    0, 2106, 1316,    0,    0,    0,    0,    1,   -1,    1,   -1, -138,    0,    0,
-+      1,   -1,    8,    8,    8,    0,    7,    7,    0,    0,   -8,   -8,   -8,   -7,   -7,    0,
-+      1,   -1,    0,    2,-1316,    1,   -1,    0,   -1,    1,   -1,    1,   -1,    3,    1,   -1,
-+     -3,    1,   -1,    1,   -1,    0,    0,-1914,-1918,    0,    0,-1923,-1824,    0,    0,    0,
-+      0,-2016,    0,    0,    1,   -1,    0,    1,    0,    0,-2104,    0,    0,    0,    0,-2106,
-+  -2108,-2106,    0,    0,    1,   -1,-2250,    0,    0,    0,-2527,    0,    0,   -2,    0,    1,
-+     -1,    0,    1,   -1,
-+};
-+
-+static inline uint_fast8_t
-+_hb_ucd_gc (unsigned u)
-+{
-+  return u<1114110u?_hb_ucd_u8[2176+(((_hb_ucd_u16[((_hb_ucd_u8[u>>4>>5])<<5)+((u>>4)&31u)])<<4)+((u)&15u))]:2;
-+}
-+static inline uint_fast8_t
-+_hb_ucd_ccc (unsigned u)
-+{
-+  return u<125259u?_hb_ucd_u8[14026+(((_hb_ucd_u8[13034+(((_hb_ucd_u8[12544+(u>>4>>4)])<<4)+((u>>4)&15u))])<<4)+((u)&15u))]:0;
-+}
-+static inline unsigned
-+_hb_ucd_b4 (const uint8_t* a, unsigned i)
-+{
-+  return (a[i>>1]>>((i&1u)<<2))&15u;
-+}
-+static inline int_fast16_t
-+_hb_ucd_bmg (unsigned u)
-+{
-+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[16170+(((_hb_ucd_b4(16042+_hb_ucd_u8,u>>2>>6))<<6)+((u>>2)&63u))])<<2)+((u)&3u)]:0;
-+}
-+static inline uint_fast8_t
-+_hb_ucd_sc (unsigned u)
-+{
-+  return u<918000u?_hb_ucd_u8[18924+(((_hb_ucd_u16[3008+(((_hb_ucd_u8[17130+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:2;
-+}
-+static inline uint_fast16_t
-+_hb_ucd_dm (unsigned u)
-+{
-+  return u<195102u?_hb_ucd_u16[6048+(((_hb_ucd_u8[28764+(u>>6)])<<6)+((u)&63u))]:0;
-+}
-+
-+
-+#else
-+
-+static const uint8_t
-+_hb_ucd_u8[16998] =
-+{
-+    0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  9, 10, 11,  7,  7,  7,  7, 12, 13, 14, 14, 14, 15,
-+   16, 17, 18, 19, 20, 21, 22, 21, 23, 21, 21, 21, 21, 24,  7,  7,
-+   25, 26, 21, 21, 21, 21, 27, 28, 21, 21, 29, 30, 31, 32, 33, 34,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7, 35,  7, 36, 37,  7, 38,  7,  7,  7, 39, 21, 40,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   41, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 42,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 43,
-+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-+   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-+   32, 33, 34, 34, 35, 36, 37, 38, 39, 34, 34, 34, 40, 41, 42, 43,
-+   44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
-+   60, 61, 62, 63, 64, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
-+   69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
-+   84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 91,
-+   92, 34, 34, 34, 34, 34, 34, 34, 34, 93, 34, 34, 94, 95, 96, 97,
-+   98, 99,100,101,102,103,104,105, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,106,
-+  107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
-+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
-+  108,108, 34, 34,109,110,111,112, 34, 34,113,114,115,116,117,118,
-+  119,120,121,122,123,124,125,126,127,128,129,123, 34, 34,130,123,
-+  131,132,133,134,135,136,137,138,139,140,141,123,142,123,143,144,
-+  145,146,147,148,149,150,151,123,152,153,123,154,155,156,157,123,
-+  158,159,123,160,161,162,123,123,163,164,165,166,123,167,123,168,
-+   34, 34, 34, 34, 34, 34, 34,169,170, 34,171,123,123,123,123,123,
-+  123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,
-+   34, 34, 34, 34, 34, 34, 34, 34,172,123,123,123,123,123,123,123,
-+  123,123,123,123,123,123,123,123, 34, 34, 34, 34,173,123,123,123,
-+   34, 34, 34, 34,174,175,176,177,123,123,123,123,178,179,180,181,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,182,
-+   34, 34, 34, 34, 34,183,123,123,123,123,123,123,123,123,123,123,
-+   34, 34,184, 34, 34,185,123,123,123,123,123,123,123,123,123,123,
-+  123,123,123,123,123,123,123,123,186,187,123,123,123,123,123,123,
-+   69,188,189,190,191,192,193,123,194,195,196,197,198,199,200,201,
-+   69, 69, 69, 69,202,203,123,123,123,123,123,123,123,123,123,123,
-+  204,123,205,123,123,206,123,123,123,123,123,123,123,123,123,123,
-+   34,207,208,123,123,123,123,123,209,210,211,123,212,213,123,123,
-+  214,215,216,217,218,123, 69,219, 69, 69, 69, 69, 69,220,221,222,
-+  223,224,225,226,227,228,123,123,123,123,123,123,123,123,123,123,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,229, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,230, 34,
-+  231, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,232, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34,233,123,123,123,123,123,123,123,123,
-+   34, 34, 34, 34,234,123,123,123,123,123,123,123,123,123,123,123,
-+  235,123,236,237,123,123,123,123,123,123,123,123,123,123,123,123,
-+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,238,
-+  108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,239,
-+    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
-+    7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
-+   16, 16, 16, 16, 16, 17, 18, 19,  1, 20, 20, 21, 22, 23, 24, 25,
-+   26, 27, 15,  2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16,
-+   16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32,
-+   32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32,
-+   32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11,
-+   11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11,
-+   34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34,
-+   34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32,
-+   32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32,
-+   16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40,
-+   40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41,
-+   40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41,
-+   43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10,
-+   44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11,
-+   11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34,
-+   16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11,
-+   32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16,
-+   48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52,  2,  2,  2,
-+   16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43,
-+   43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62,
-+   36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65,  8,  9, 66,  2, 67,
-+   43, 43, 43, 43, 43, 60, 68,  2, 69, 36, 36, 36, 36, 70, 43, 43,
-+    7,  7,  7,  7,  7,  2,  2, 36, 71, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36,
-+    7,  7,  7,  7,  7, 36, 77, 78,  2,  2,  2,  2,  2,  2,  2, 79,
-+   70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36,
-+   36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44,
-+    7,  7,  7,  7,  7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43,
-+   43, 43, 40, 21,  2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
-+   43, 43, 75, 43, 75, 43, 43, 44,  2,  2,  2,  2,  2,  2,  2, 64,
-+   36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
-+   44, 44, 44, 44, 44, 44, 44, 44, 36, 36, 61, 36, 36, 36, 36, 44,
-+   44, 57, 43, 43, 43, 43, 43, 43, 43, 82, 43, 43, 43, 43, 43, 43,
-+   43, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 83, 71, 84,
-+   85, 43, 43, 43, 83, 84, 85, 84, 70, 43, 43, 43, 36, 36, 36, 36,
-+   36, 43,  2,  7,  7,  7,  7,  7, 86, 36, 36, 36, 36, 36, 36, 36,
-+   70, 84, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 84,
-+   85, 43, 80, 87, 88, 87, 85, 61, 44, 44, 44, 87, 44, 44, 36, 62,
-+   36, 43, 44,  7,  7,  7,  7,  7, 36, 20, 27, 27, 27, 56, 63, 80,
-+   57, 83, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 84,
-+   85, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61,
-+   44, 44, 44,  7,  7,  7,  7,  7, 43, 36, 70, 64, 44, 44, 44, 44,
-+   57, 83, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36,
-+   61, 36, 62, 36, 36, 44, 71, 84, 85, 43, 43, 57, 83, 87, 85, 44,
-+   61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43,
-+   57, 84, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 85,
-+   85, 43, 80, 87, 88, 87, 85, 44, 44, 44, 44, 83, 44, 44, 36, 62,
-+   78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36,
-+   61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36,
-+   36, 36, 36, 36, 36, 44, 44, 84, 83, 88, 44, 84, 88, 84, 85, 44,
-+   61, 44, 44, 87, 44, 44, 44, 44, 27, 89, 67, 67, 56, 90, 44, 44,
-+   83, 84, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 44, 62, 43, 83, 84, 88, 43, 80, 43, 43, 44,
-+   44, 44, 57, 80, 36, 61, 44, 44, 44, 44, 44, 91, 27, 27, 27, 89,
-+   70, 84, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 85,
-+   84, 84, 88, 83, 88, 84, 43, 44, 44, 44, 87, 88, 44, 44, 44, 61,
-+   62, 61, 44, 44, 44, 44, 44, 44, 43, 84, 62, 36, 36, 36, 61, 36,
-+   36, 36, 36, 36, 36, 70, 71, 84, 85, 43, 80, 84, 88, 84, 85, 77,
-+   44, 44, 36, 92, 27, 27, 27, 93, 27, 27, 27, 27, 89, 36, 36, 36,
-+   44, 84, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36,
-+   36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 87,
-+   84, 43, 80, 80, 84, 84, 84, 84, 44, 84, 64, 44, 44, 44, 44, 44,
-+   62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 94,
-+   36, 36, 36, 75, 43, 43, 43, 60,  7,  7,  7,  7,  7,  2, 44, 44,
-+   62, 61, 61, 36, 36, 61, 36, 36, 36, 36, 62, 62, 36, 36, 36, 36,
-+   70, 36, 43, 43, 43, 43, 71, 44, 36, 36, 61, 81, 43, 43, 43, 44,
-+    7,  7,  7,  7,  7, 44, 36, 36, 77, 67,  2,  2,  2,  2,  2,  2,
-+    2, 95, 95, 67, 43, 67, 67, 67,  7,  7,  7,  7,  7, 27, 27, 27,
-+   27, 27, 50, 50, 50,  4,  4, 84, 36, 36, 36, 36, 62, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 61, 44, 57, 43, 43, 43, 43, 43, 43, 83,
-+   43, 43, 60, 43, 36, 36, 70, 43, 43, 43, 43, 43, 57, 43, 43, 43,
-+   43, 43, 43, 43, 43, 43, 80, 67, 67, 67, 67, 76, 67, 67, 90, 67,
-+    2,  2, 95, 67, 21, 64, 44, 44, 36, 36, 36, 36, 36, 92, 85, 43,
-+   83, 43, 43, 43, 85, 83, 85, 71,  7,  7,  7,  7,  7,  2,  2,  2,
-+   36, 36, 36, 84, 43, 36, 36, 43, 71, 84, 96, 92, 84, 84, 84, 36,
-+   70, 43, 71, 36, 36, 36, 36, 36, 36, 83, 85, 83, 84, 84, 85, 92,
-+    7,  7,  7,  7,  7, 84, 85, 67, 11, 11, 11, 48, 44, 44, 48, 44,
-+   16, 16, 16, 16, 16, 53, 45, 16, 36, 36, 36, 36, 61, 36, 36, 44,
-+   36, 36, 36, 61, 61, 36, 36, 44, 61, 36, 36, 44, 36, 36, 36, 61,
-+   61, 36, 36, 44, 36, 36, 36, 36, 36, 36, 36, 61, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 61, 57, 43,  2,  2,  2,  2, 97, 27, 27, 27,
-+   27, 27, 27, 27, 27, 27, 98, 44, 67, 67, 67, 67, 67, 44, 44, 44,
-+   11, 11, 11, 44, 16, 16, 16, 44, 99, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 77, 72,100, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36,101,102, 44, 36, 36, 36, 36, 36, 63,  2,103,
-+  104, 36, 36, 36, 61, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36,
-+   36, 43, 80, 44, 44, 44, 44, 44, 36, 43, 60, 64, 44, 44, 44, 44,
-+   36, 43, 44, 44, 44, 44, 44, 44, 61, 43, 44, 44, 44, 44, 44, 44,
-+   36, 36, 43, 85, 43, 43, 43, 84, 84, 84, 84, 83, 85, 43, 43, 43,
-+   43, 43,  2, 86,  2, 66, 70, 44,  7,  7,  7,  7,  7, 44, 44, 44,
-+   27, 27, 27, 27, 27, 44, 44, 44,  2,  2,  2,105,  2, 59, 43, 68,
-+   36,106, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 44, 44,
-+   36, 36, 70, 71, 36, 36, 36, 36, 36, 36, 36, 36, 70, 61, 44, 44,
-+   36, 36, 36, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 61,
-+   43, 83, 84, 85, 83, 84, 44, 44, 84, 83, 84, 84, 85, 43, 44, 44,
-+   90, 44,  2,  7,  7,  7,  7,  7, 36, 36, 36, 36, 36, 36, 36, 44,
-+   36, 36, 61, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 44, 44,
-+   36, 36, 36, 36, 36, 44, 44, 44,  7,  7,  7,  7,  7, 98, 44, 67,
-+   67, 67, 67, 67, 67, 67, 67, 67, 36, 36, 36, 70, 83, 85, 44,  2,
-+   36, 36, 92, 83, 43, 43, 43, 80, 83, 83, 85, 43, 43, 43, 83, 84,
-+   84, 85, 43, 43, 43, 43, 80, 57,  2,  2,  2, 86,  2,  2,  2, 44,
-+   43, 43, 43, 43, 43, 43, 43,107, 43, 43, 96, 36, 36, 36, 36, 36,
-+   36, 36, 83, 43, 43, 83, 83, 84, 84, 83, 96, 36, 36, 36, 44, 44,
-+   95, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 90, 44,
-+   43, 96, 36, 36, 36, 36, 36, 36, 92, 43, 43, 84, 43, 85, 43, 36,
-+   36, 36, 36, 83, 43, 84, 85, 85, 43, 84, 44, 44, 44, 44,  2,  2,
-+   36, 36, 84, 84, 84, 84, 43, 43, 43, 43, 84, 43, 44, 91,  2,  2,
-+    7,  7,  7,  7,  7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40,  2,
-+   16, 16, 16, 16,108, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
-+    2,  2,  2,  2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
-+   83, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 92, 43, 61, 44, 44,
-+   16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
-+   16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,109, 40, 40,
-+   43, 43, 43, 43, 43, 57, 43, 43, 32, 32, 32, 16, 16, 16, 16, 32,
-+   16, 16, 16, 16, 11, 11, 11, 11, 16, 16, 16, 44, 11, 11, 11, 44,
-+   16, 16, 16, 16, 48, 48, 48, 48, 16, 16, 16, 16, 16, 16, 16, 44,
-+   16, 16, 16, 16,110,110,110,110, 16, 16,108, 16, 11, 11,111,112,
-+   41, 16,108, 16, 11, 11,111, 41, 16, 16, 44, 16, 11, 11,113, 41,
-+   16, 16, 16, 16, 11, 11,114, 41, 44, 16,108, 16, 11, 11,111,115,
-+  116,116,116,116,116,117, 65, 65,118,118,118,  2,119,120,119,120,
-+    2,  2,  2,  2,121, 65, 65,122,  2,  2,  2,  2,123,124,  2,125,
-+  126,  2,127,128,  2,  2,  2,  2,  2,  9,126,  2,  2,  2,  2,129,
-+   65, 65, 68, 65, 65, 65, 65, 65,130, 44, 27, 27, 27,  8,127,131,
-+   27, 27, 27, 27, 27,  8,127,102, 40, 40, 40, 40, 40, 40, 81, 44,
-+   20, 20, 20, 20, 20, 20, 20, 20, 43, 43, 43, 43, 43, 43,132, 51,
-+  133, 51,133, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44,
-+   67,134, 67,135, 67, 34, 11, 16, 11, 32,135, 67, 49, 11, 11, 67,
-+   67, 67,134,134,134, 11, 11,136, 11, 11, 35, 36, 39, 67, 16, 11,
-+    8,  8, 49, 16, 16, 26, 67,137, 27, 27, 27, 27, 27, 27, 27, 27,
-+  103,103,103,103,103,103,103,103,103,138,139,103,140, 67, 44, 44,
-+    8,  8,141, 67, 67,  8, 67, 67,141, 26, 67,141, 67, 67, 67,141,
-+   67, 67, 67, 67, 67, 67, 67,  8, 67,141,141, 67, 67, 67, 67, 67,
-+   67, 67,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-+   67, 67, 67, 67,  4,  4, 67, 67,  8, 67, 67, 67,142,143, 67, 67,
-+   67, 67, 67, 67, 67, 67,141, 67, 67, 67, 67, 67, 67, 26,  8,  8,
-+    8,  8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,
-+    8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90, 44, 44, 44, 44,
-+   67, 67, 67, 67, 67, 90, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
-+   67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
-+   26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,  8,  8,  8,  8,
-+   67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67,  4,  4,  4,  4,
-+    4,  4,  4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
-+    8,  8,127,144,  8,  8,  8,  8,  8,  8,  8,  4,  4,  4,  4,  4,
-+    8,127,145,145,145,145,145,145,145,145,145,145,144,  8,  8,  8,
-+    8,  8,  8,  8,  4,  4,  8,  8,  8,  8,  8,  8,  8,  8,  4,  8,
-+    8,  8,141, 26,  8,  8,141, 67, 67, 67, 44, 67, 67, 67, 67, 67,
-+   67, 67, 67, 44, 67, 67, 67, 67, 11, 11, 11, 11, 11, 11, 11, 47,
-+   16, 16, 16, 16, 16, 16, 16,108, 32, 11, 32, 34, 34, 34, 34, 11,
-+   32, 32, 34, 16, 16, 16, 40, 11, 32, 32,137, 67, 67,135, 34,146,
-+   43, 32, 44, 44, 91,  2, 97,  2, 16, 16, 16,147, 44, 44,147, 44,
-+   36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
-+   36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
-+    2,119,119,  2,123,124,119,  2,  2,  2,  2,  6,  2,105,119,  2,
-+  119,  4,  4,  4,  4,  2,  2, 86,  2,  2,  2,  2,  2,118,  2,  2,
-+  105,148,  2,  2,  2,  2,  2,  2, 67, 67, 67, 67, 67, 55, 67, 67,
-+   67, 67, 44, 44, 44, 44, 44, 44, 67, 67, 67, 44, 44, 44, 44, 44,
-+   67, 67, 67, 67, 67, 67, 44, 44,  1,  2,149,150,  4,  4,  4,  4,
-+    4, 67,  4,  4,  4,  4,151,152,153,103,103,103,103, 43, 43, 84,
-+  154, 40, 40, 67,103,155, 63, 67, 36, 36, 36, 61, 57,156,157, 69,
-+   36, 36, 36, 36, 36, 63, 40, 69, 44, 44, 62, 36, 36, 36, 36, 36,
-+   67, 27, 27, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90,
-+   27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67, 67, 27, 27, 27, 27,
-+  158, 27, 27, 27, 27, 27, 27, 27, 36, 36,106, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36,159,  2,  7,  7,  7,  7,  7, 36, 44, 44,
-+   32, 32, 32, 32, 32, 32, 32, 70, 51,160, 43, 43, 43, 43, 43, 86,
-+   32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36,103,103,103,103,103,
-+   43,  2,  2,  2, 44, 44, 44, 44, 41, 41, 41,157, 40, 40, 40, 40,
-+   41, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32,
-+   45, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,161, 34, 35,
-+   32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32,
-+   11, 11, 32, 32, 32, 32, 32, 32, 44, 32, 11, 47, 44, 44, 44, 44,
-+   44, 44, 44, 62, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
-+   36, 92, 85, 83, 67, 67, 44, 44, 27, 27, 27, 67,162, 44, 44, 44,
-+   36, 36,  2,  2, 44, 44, 44, 44, 84, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 84, 84, 84, 84, 84, 84, 84, 84, 43, 44, 44, 44, 44,  2,
-+   43, 36, 36, 36,  2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43,  2,
-+   36, 36, 36, 70, 43, 43, 43, 43, 43, 84, 44, 44, 44, 44, 44, 91,
-+   36, 70, 84, 43, 43, 84, 43, 84,163,  2,  2,  2,  2,  2,  2, 52,
-+    7,  7,  7,  7,  7, 44, 44,  2, 36, 36, 70, 69, 36, 36, 36, 36,
-+    7,  7,  7,  7,  7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 83,
-+   85, 83, 85, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 83, 44,
-+    7,  7,  7,  7,  7, 44,  2,  2, 69, 36, 36, 77, 67, 92, 83, 36,
-+   71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44,
-+   44, 44, 44, 44, 44, 62,106,  2, 36, 36, 36, 36, 36, 92, 43, 84,
-+    2,106,164, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61,
-+   62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,112, 40, 40,
-+   16, 16, 16, 16, 44, 44, 44, 44, 36, 92, 85, 84, 83,163, 85, 44,
-+   36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36,
-+  165,165,165,165,165,165,165,165,166,166,166,166,166,166,166,166,
-+   16, 16, 16,108, 44, 44, 44, 44, 44,147, 16, 16, 44, 44, 62, 71,
-+   36, 36, 36, 36,167, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61,
-+   36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
-+   41, 44, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36,145, 44, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36,162, 44,
-+    2,  2,  2,168,128, 44, 44, 44,  6,169,170,145,145,145,145,145,
-+  145,145,128,168,128,  2,125,171,  2, 64,  2,  2,151,145,145,128,
-+    2,172,  8,173, 66,  2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 61, 79, 91,  2,  3,  2,  4,  5,  6,  2,
-+   16, 16, 16, 16, 16, 17, 18,127,128,  4,  2, 36, 36, 36, 36, 36,
-+   69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
-+   44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44,
-+   20,174, 56,175, 26,  8,141, 90, 44, 44, 44, 44, 79, 65, 67, 44,
-+   36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62,
-+    2, 64, 44,176, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67,
-+  103,103,140, 27, 89, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 90,
-+   90, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 50, 44,
-+  177, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 44, 44,
-+   27, 27, 44, 44, 44, 44, 62, 36,150, 36, 36, 36, 36,178, 44, 44,
-+   36, 36, 36, 43, 43, 80, 44, 44, 36, 36, 36, 36, 36, 36, 36, 91,
-+   36, 36, 44, 44, 36, 36, 36, 36,179,103,103, 44, 44, 44, 44, 44,
-+   11, 11, 11, 11, 16, 16, 16, 16, 11, 11, 44, 44, 16, 16, 16, 16,
-+   16, 16, 16, 16, 16, 16, 44, 44, 36, 36, 44, 44, 44, 44, 44, 91,
-+   36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62,
-+   36, 36, 36, 91, 27, 27, 27, 27, 36, 36, 36, 77,158, 27, 27, 27,
-+   44, 44, 44,176, 27, 27, 27, 27, 36, 61, 36, 44, 44,176, 27, 27,
-+   36, 36, 36, 27, 27, 27, 44, 91, 36, 36, 36, 36, 36, 44, 44, 91,
-+   36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27,
-+   70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36,
-+   36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27, 98, 44, 44, 44,
-+    2,  2,  2,  2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,180, 30,
-+   36, 36, 36, 36, 36, 36,180, 27, 36, 36, 36, 36, 78, 36, 36, 36,
-+   36, 36, 70, 80, 44,176, 27, 27,  2,  2,  2, 64, 44, 44, 44, 44,
-+   36, 36, 36, 44, 91,  2,  2,  2, 36, 36, 36, 44, 27, 27, 27, 27,
-+   36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 91,  2, 64, 44,
-+   44, 44, 44, 44,176, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
-+   16,108, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
-+   27, 27, 27, 27, 27, 27, 27, 98, 27, 27, 27, 93, 44, 44, 44, 44,
-+  177, 27, 30,  2,  2, 44, 44, 44, 85, 96, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 43, 60,  2,  2,  2, 44,
-+   27, 27, 27,  7,  7,  7,  7,  7, 44, 44, 44, 44, 44, 44, 44, 57,
-+   84, 85, 43, 83, 85, 60,181,  2,  2, 44, 44, 44, 44, 44, 79, 44,
-+   43, 71, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, 85, 43,
-+   43, 43, 80,  7,  7,  7,  7,  7,  2,  2, 92, 88, 44, 44, 44, 44,
-+   36, 70,  2, 61, 44, 44, 44, 44, 36, 92, 84, 43, 43, 43, 43, 83,
-+   96, 36, 63,  2, 59, 43, 60, 44,  7,  7,  7,  7,  7, 63, 63,  2,
-+  176, 27, 27, 27, 27, 27, 27, 27, 27, 27, 98, 44, 44, 44, 44, 44,
-+   36, 36, 36, 36, 36, 36, 84, 85, 43, 84, 83, 43,  2,  2,  2, 80,
-+   36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62,
-+   36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70,
-+   84, 85, 43, 43, 43, 80, 44, 44, 43, 84, 62, 36, 36, 36, 61, 62,
-+   61, 36, 62, 36, 36, 57, 71, 84, 83, 84, 88, 87, 88, 87, 84, 44,
-+   61, 44, 44, 87, 44, 44, 62, 36, 36, 84, 44, 43, 43, 43, 80, 44,
-+   43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 92, 84, 43, 43, 43, 43,
-+   84, 43, 83, 71, 36, 63,  2,  2,  7,  7,  7,  7,  7, 91, 91, 71,
-+   84, 85, 43, 43, 83, 83, 84, 85, 83, 43, 36, 72, 44, 44, 44, 44,
-+   36, 36, 36, 36, 36, 36, 36, 92, 84, 43, 43, 44, 84, 84, 43, 85,
-+   60,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 44,
-+   84, 85, 43, 43, 43, 83, 85, 85, 60,  2, 61, 44, 44, 44, 44, 44,
-+    2,  2,  2,  2,  2,  2, 64, 44, 36, 36, 36, 36, 36, 70, 85, 84,
-+   43, 43, 43, 85, 61, 44, 44, 44, 84, 43, 43, 85, 43, 43, 44, 44,
-+    7,  7,  7,  7,  7, 27,  2, 95, 43, 43, 43, 43, 85, 60, 44, 44,
-+   27, 98, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 44, 36, 36, 36,
-+   92, 84, 43, 43, 44, 43, 84, 84, 71, 72, 88, 44, 44, 44, 44, 44,
-+   70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 83, 70, 43, 60,
-+    2,  2,  2, 59, 44, 44, 44, 44, 70, 43, 43, 83, 85, 43, 36, 36,
-+   36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 83, 43,  2, 72,  2,
-+    2, 64, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 85,
-+   63,  2,  2, 44, 44, 44, 44, 44,  2, 36, 36, 36, 36, 36, 36, 36,
-+   44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 87, 43, 43, 43,
-+   83, 43, 85, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
-+   70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
-+   36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 84, 84, 88,
-+   43, 87, 85, 85, 61, 44, 44, 44, 36, 70, 83,163, 64, 44, 44, 44,
-+   27, 27, 89, 67, 67, 67, 56, 20,162, 67, 67, 67, 67, 67, 67, 67,
-+   67, 44, 44, 44, 44, 44, 44, 91,103,103,103,103,103,103,103,178,
-+    2,  2, 64, 44, 44, 44, 44, 44, 65, 65, 65, 65, 68, 44, 44, 44,
-+   43, 43, 60, 44, 44, 44, 44, 44, 43, 43, 43, 60,  2,  2, 67, 67,
-+   40, 40, 95, 44, 44, 44, 44, 44,  7,  7,  7,  7,  7,176, 27, 27,
-+   27, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 44, 44, 62, 36,
-+   27, 27, 27, 30,  2, 64, 44, 44, 36, 36, 36, 36, 36, 61, 44, 57,
-+   92, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
-+   84, 84, 84, 84, 44, 44, 44, 57, 43, 74, 40, 40, 40, 40, 40, 40,
-+   40, 86, 44, 44, 44, 44, 44, 44, 36, 61, 44, 44, 44, 44, 44, 44,
-+   44, 44, 36, 36, 44, 44, 44, 44, 36, 36, 36, 36, 36, 44, 50, 60,
-+   65, 65, 44, 44, 44, 44, 44, 44, 67, 67, 67, 90, 55, 67, 67, 67,
-+   67, 67,182, 85, 43, 67,182, 84, 84,183, 65, 65, 65, 82, 43, 43,
-+   43, 76, 50, 43, 43, 43, 67, 67, 67, 67, 67, 67, 67, 43, 43, 67,
-+   67, 67, 67, 67, 90, 44, 44, 44, 67, 43, 76, 44, 44, 44, 44, 44,
-+   27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
-+   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
-+   16, 16,108, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
-+   16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
-+   11, 11, 11, 16, 16,147,147, 16, 16, 16,147, 16, 16, 16, 16, 16,
-+   16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
-+   16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
-+   47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
-+   11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
-+   31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
-+   16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
-+   16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
-+   16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
-+   11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
-+   11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7, 43, 43, 43, 76, 67, 50, 43, 43,
-+   43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
-+   67, 67, 76, 21,  2,  2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
-+   43, 43, 43, 80, 43, 43, 43, 43, 43, 43, 43, 43, 80, 57, 43, 43,
-+   43, 57, 80, 43, 43, 80, 44, 44, 43, 43, 43, 74, 40, 40, 40, 44,
-+    7,  7,  7,  7,  7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 43, 43,
-+    7,  7,  7,  7,  7, 44, 44, 94, 36, 36, 61,176, 27, 27, 27, 27,
-+   43, 43, 43, 80, 44, 44, 44, 44, 16, 16, 43, 43, 43, 74, 44, 44,
-+   27, 27, 27, 27, 27, 27,158, 27,184, 27, 98, 44, 44, 44, 44, 44,
-+   27, 27, 27, 27, 27, 27, 27,158, 27, 27, 27, 27, 27, 27, 27, 44,
-+   36, 36, 62, 36, 36, 36, 36, 36, 62, 61, 61, 62, 62, 36, 36, 36,
-+   36, 61, 36, 36, 62, 62, 44, 44, 44, 61, 44, 62, 62, 62, 62, 36,
-+   62, 61, 61, 62, 62, 62, 62, 62, 62, 61, 61, 62, 36, 61, 36, 36,
-+   36, 61, 36, 36, 62, 36, 61, 61, 36, 36, 36, 36, 36, 62, 36, 36,
-+   62, 36, 62, 36, 36, 62, 36, 36,  8, 44, 44, 44, 44, 44, 44, 44,
-+   55, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 90, 44,
-+   44, 44, 44, 67, 67, 67, 67, 67, 67, 90, 44, 44, 44, 44, 44, 44,
-+   67, 44, 44, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 25, 41, 41,
-+   67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 67, 44,
-+   67, 67, 67, 67, 67, 67, 55, 67, 67, 55, 67, 90, 44, 67, 67, 67,
-+   67, 90, 55, 67, 67, 90, 44, 67, 67, 67, 67, 67, 67, 90, 55, 67,
-+   67, 67, 44, 44, 67, 90, 44, 44, 36, 44, 44, 44, 44, 44, 44, 44,
-+   79, 44, 44, 44, 44, 44, 44, 44, 65, 65, 65, 65, 65, 65, 65, 65,
-+  166,166,166,166,166,166,166, 44,166,166,166,166,166,166,166,  0,
-+    0,  0, 29, 21, 21, 21, 23, 21, 22, 18, 21, 25, 21, 17, 13, 13,
-+   25, 25, 25, 21, 21,  9,  9,  9,  9, 22, 21, 18, 24, 16, 24,  5,
-+    5,  5,  5, 22, 25, 18, 25,  0, 23, 23, 26, 21, 24, 26,  7, 20,
-+   25,  1, 26, 24, 26, 25, 15, 15, 24, 15,  7, 19, 15, 21,  9, 25,
-+    9,  5,  5, 25,  5,  9,  5,  7,  7,  7,  9,  8,  8,  5,  7,  5,
-+    6,  6, 24, 24,  6, 24, 12, 12,  2,  2,  6,  5,  9, 21,  9,  2,
-+    2,  9, 25,  9, 26, 12, 11, 11,  2,  6,  5, 21, 17,  2,  2, 26,
-+   26, 23,  2, 12, 17, 12, 21, 12, 12, 21,  7,  2,  2,  7,  7, 21,
-+   21,  2,  1,  1, 21, 23, 26, 26,  1,  2,  6,  7,  7, 12, 12,  7,
-+   21,  7, 12,  1, 12,  6,  6, 12, 12, 26,  7, 26, 26,  7,  2,  1,
-+   12,  2,  6,  2,  1, 12, 12, 10, 10, 10, 10, 12, 21,  6,  2, 10,
-+   10,  2, 15, 26, 26,  2,  2, 21,  7, 10, 15,  7,  2, 23, 21, 26,
-+   10,  7, 21, 15, 15,  2, 17,  7, 29,  7,  7, 22, 18,  2, 14, 14,
-+   14,  7, 17, 21,  7,  6, 11,  2,  5,  2,  5,  6,  8,  8,  8, 24,
-+    5, 24,  2, 24,  9, 24, 24,  2, 29, 29, 29,  1, 17, 17, 20, 19,
-+   22, 20, 27, 28,  1, 29, 21, 20, 19, 21, 21, 16, 16, 21, 25, 22,
-+   18, 21, 21, 29, 15,  6, 18,  6, 12, 11, 11, 12,  9, 26, 26,  9,
-+   26,  5,  5, 26, 14,  9,  5, 14, 14, 15, 25, 26, 26, 22, 18, 26,
-+   18, 25, 18, 22,  5, 12,  2,  5, 22, 21, 26,  6,  7, 14, 17, 22,
-+   18, 18, 26, 14, 17,  6, 14,  6, 12, 24, 24,  6, 26, 15,  6, 21,
-+   11, 21, 24,  9, 23, 26, 10, 21,  6, 10,  4,  4,  3,  3,  7, 25,
-+   21, 22, 17, 16, 16, 22, 16, 16, 25, 17, 25,  2, 25, 24, 23,  2,
-+    2, 15, 12, 15, 14,  2, 21, 14,  7, 15, 21,  1, 26, 10, 10,  1,
-+   23, 15,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  0, 10, 11, 12,
-+   13,  0, 14,  0,  0,  0,  0,  0, 15,  0, 16,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,
-+    0, 21, 22, 23,  0,  0,  0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
-+   33,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 34,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   35,  0,  0,  0,  0,  0,  0,  0,  0,  0, 36, 37,  0,  0,  0,  0,
-+    0,  0, 38, 39,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    1,  2,  3,  4,  0,  0,  0,  0,  0,  0,  0,  0,  5,  0,  0,  0,
-+    0,  0,  0,  0,  6,  7,  8,  0,  9,  0, 10, 11,  0,  0, 12, 13,
-+   14, 15, 16,  0,  0,  0,  0, 17, 18, 19, 20,  0,  0,  0, 21, 22,
-+    0, 23, 24,  0,  0, 23, 25, 26,  0, 23, 25,  0,  0, 23, 25,  0,
-+    0, 23, 25,  0,  0,  0, 25,  0,  0,  0, 27,  0,  0, 23, 25,  0,
-+    0, 28, 25,  0,  0,  0, 29,  0,  0, 30, 31,  0,  0, 32, 33,  0,
-+   34, 35,  0, 36, 37,  0, 38,  0,  0, 39,  0,  0, 40,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 41,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   42, 42,  0,  0,  0,  0, 43,  0,  0,  0,  0,  0,  0, 44,  0,  0,
-+    0, 45,  0,  0,  0,  0,  0,  0, 46,  0,  0, 47,  0, 48,  0,  0,
-+    0, 49, 50, 51,  0, 52,  0, 53,  0, 54,  0,  0,  0,  0, 55, 56,
-+    0,  0,  0,  0,  0,  0, 57, 58,  0,  0,  0,  0,  0,  0, 59, 60,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 61,
-+    0,  0,  0, 62,  0,  0,  0, 63,  0, 64,  0,  0, 65,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 66, 67,  0,  0, 68,
-+    0,  0,  0,  0,  0,  0,  0,  0, 69,  0,  0,  0,  0,  0, 50, 70,
-+    0, 71, 72,  0,  0, 73, 74,  0,  0,  0,  0,  0,  0, 75, 76, 77,
-+    0,  0,  0,  0,  0,  0,  0, 25,  0,  0,  0,  0,  0,  0,  0,  0,
-+   78,  0,  0,  0,  0,  0,  0,  0,  0, 79,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 80,  0,  0,  0,  0,  0,  0,  0, 81,
-+    0,  0,  0, 82,  0,  0,  0,  0, 83, 84,  0,  0,  0,  0,  0, 85,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0, 86,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 87,  0,  0,  0,  0,  0,  0,  0, 69, 62,  0, 88,  0,  0,
-+   89, 90,  0, 73,  0,  0, 91,  0,  0, 92,  0,  0,  0,  0,  0, 93,
-+    0, 94, 25, 95,  0,  0,  0,  0,  0,  0, 96,  0,  0,  0, 97,  0,
-+    0,  0,  0,  0,  0, 62, 98,  0,  0, 62,  0,  0,  0, 99,  0,  0,
-+    0,100,  0,  0,  0,  0,  0,  0,  0, 88,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 74,  0, 42,101,  0,102,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0,  0,  0,  0,
-+    0,  0,103,  0,104,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,
-+    0,106,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,108,109,110,  0,  0,  0,  0,111,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,112,113,  0,  0,  0,  0,  0,  0,
-+    0,106,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,114,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,115,  0,
-+    0,  0,116,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    1,  1,  1,  1,  1,  2,  3,  4,  5,  6,  7,  4,  4,  8,  9, 10,
-+    1, 11, 12, 13, 14, 15, 16, 17, 18,  1,  1,  1,  0,  0,  0,  0,
-+   19,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20, 21, 22,  1,
-+   23,  4, 21, 24, 25, 26, 27, 28, 29, 30,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  1,  1, 31,  0,  0,  0, 32, 33, 34, 35,  1, 36,
-+    0,  0,  0,  0, 37,  0,  0,  0,  0,  0,  0,  0,  0, 38,  1, 39,
-+   14, 39, 40, 41,  0,  0,  0,  0,  0,  0,  0,  0, 42,  0,  0,  0,
-+    0,  0,  0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0,  0,  0,
-+    0,  0, 19,  1, 21,  0,  0, 47,  0,  0,  0,  0,  0, 38, 48,  1,
-+    1, 49, 49, 50,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 51,  0,
-+    0,  0,  0,  0, 52,  1,  1,  1, 53, 21, 43, 54, 55, 21, 35,  1,
-+    0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0, 57, 58, 59,  0,  0,
-+    0,  0,  0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 60,
-+    0,  0,  0, 57,  0, 61,  0,  0,  0,  0,  0,  0,  0,  0, 62, 63,
-+    0,  0, 64,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 65,  0,
-+    0,  0, 66,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 67,  0,
-+    0,  0, 68,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 69,  0,
-+    0,  0,  0,  0,  0, 70, 71,  0,  0,  0,  0,  0, 72, 73, 74, 75,
-+   76, 77,  0,  0,  0,  0,  0,  0,  0, 78,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0, 79, 80,  0,  0,  0,  0, 47,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 49,  0,  0,  0,  0,  0, 63,  0,  0,
-+    0,  0,  0,  0, 64,  0,  0, 81,  0,  0, 82,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 83,  0,  0,  0,  0,  0,  0, 19, 84,  0,
-+   63,  0,  0,  0,  0, 49,  1, 85,  0,  0,  0,  0,  1, 54, 15, 41,
-+    0,  0,  0,  0,  0, 56,  0,  0,  0, 63,  0,  0,  0,  0,  0,  0,
-+    0,  0, 19, 10,  1,  0,  0,  0,  0,  0, 86,  0,  0,  0,  0,  0,
-+    0, 87,  0,  0, 86,  0,  0,  0,  0,  0,  0,  0,  0, 79,  0,  0,
-+    0,  0,  0,  0, 88,  9, 12,  4, 89,  8, 90, 47,  0, 59, 50,  0,
-+   21,  1, 21, 91, 92,  1,  1,  1,  1,  1,  1,  1,  1, 93, 94, 95,
-+    0,  0,  0,  0, 96,  1, 97, 59, 81, 98, 99,  4, 59,  0,  0,  0,
-+    0,  0,  0, 19, 50,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,
-+    1,  1,  1,  1,  1,  1,  1,  1,  0,  0,100,101,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,102,  0,  0,  0,  0, 19,  0,  1,  1, 50,
-+    0,  0,  0,  0,  0,  0,  0, 38,  0,  0,  0,  0, 50,  0,  0,  0,
-+    0, 64,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1, 50,  0,  0,  0,
-+    0,  0, 52, 69,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0,
-+    0,  0,  0,  0, 79,  0,  0,  0, 63,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,103,104, 59, 38, 81,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0, 64,  0,  0,  0,  0,  0,  0,  0,  0,  0,105,
-+    1, 14,  4, 12,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 47,
-+   84,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 38, 88,  0,
-+    0,  0,  0,106,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,107, 62,
-+    0,108,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
-+    0,109, 14, 54, 84,  0,  0,  0,  0,  0,  0,  0,  0,  0,110,  0,
-+   88,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62, 63,  0,  0,
-+   63,  0, 87,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,110,  0,  0,
-+    0,  0,111,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 79, 56,
-+    0, 38,  1, 59,  1, 59,  0,  0, 64, 87,  0,  0,  0,  0,  0, 60,
-+  112,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,112,  0,  0,  0,  0, 62,  0,  0,  0,  0,  0,
-+    0, 62,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 57,  0,
-+   87,113,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,
-+    0,  0,  0,  0,  8, 90,  0,  0,  0,  0,  0,  0,  1, 88,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,114,  0,115,116,117,118,  0, 52,  4,
-+  119, 49, 23,  0,  0,  0,  0,  0,  0,  0, 38, 50,  0,  0,  0,  0,
-+   38, 59,  0,  0,  0,  0,  0,  0,  1, 88,  1,  1,  1,  1, 39,  1,
-+   48,103, 88,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,
-+    0,  0,  0,  0,  4,119,  0,  0,  0,  1,120,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,230,230,230,230,230,232,220,220,220,220,232,216,
-+  220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
-+    1,  1,  1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,
-+  220,220,230,230,230,220,220,  0,230,230,230,220,220,220,220,230,
-+  232,220,220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,
-+    0,220,230,230,230,230,220,230,230,230,222,220,230,230,220,220,
-+  230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
-+   21, 22,  0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,
-+    0,  0,  0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,
-+  220,230,230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,
-+  230,  0,220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,
-+  220,220,230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,
-+  230,230,  0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,
-+    0,  0,  0,220,230,230,  0,220,230,220,220,220, 27, 28, 29,230,
-+    7,  0,  0,  0,  0,  9,  0,  0,  0,230,220,230,230,  0,  0,  0,
-+    0,  0,230,  0,  0, 84, 91,  0,  0,  0,  0,  9,  9,  0,  0,  0,
-+    0,  0,  9,  0,103,103,  9,  0,107,107,107,107,118,118,  9,  0,
-+  122,122,122,122,220,220,  0,  0,  0,220,  0,220,  0,216,  0,  0,
-+    0,129,130,  0,132,  0,  0,  0,  0,  0,130,130,130,130,  0,  0,
-+  130,  0,230,230,  9,  0,230,230,  0,  0,220,  0,  0,  0,  0,  7,
-+    0,  9,  9,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,
-+  220,  0,  0,  0,230,  0,  0,220,  0,  0,  9,  9,  0,  0,  7,  0,
-+  230,230,230,  0,230,  0,  1,  1,  1,  0,  0,  0,230,234,214,220,
-+  202,230,230,230,230,230,232,228,228,220,  0,230,233,220,230,220,
-+  230,230,  1,  1,  1,  1,  1,230,  0,  1,  1,230,220,230,  1,  1,
-+    0,  0,218,228,232,222,224,224,  0,  8,  8,  0,230,  0,230,230,
-+  220,  0,  0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,
-+    0,230,220,  0,  0,  0,220,220,  0,  9,  7,  0,  0,  7,  9,  0,
-+    0,  0,  9,  7,  9,  9,  0,  0,  0,  0,  1,  0,  0,216,216,  1,
-+    1,  1,  0,  0,  0,226,216,216,216,216,216,  0,220,220,220,  0,
-+  230,230,  7,  0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
-+   17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17,237,  0,  1,  2,  2,  0,  3,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  4,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    5,  0,  0,  0,  0,  6,  7,  8,  9,  0,  0,  0, 10, 11, 12, 13,
-+   14, 15, 16, 17, 18, 19,  0,  0,  0,  0,  0,  0,  0,  0,  0, 20,
-+    0,  0, 21, 22,  0,  0,  0,  0, 23, 24, 25, 26,  0, 27,  0, 28,
-+   29, 30, 31, 32,  0,  0,  0,  0,  0,  0,  0, 33, 34, 35,  0,  0,
-+    0,  0,  0,  0, 36,  0,  0,  0,  0,  0,  0,  0,  0,  0, 37, 38,
-+    0,  0,  0,  0,  1,  2, 39, 40,  0,  1,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  2,  0,  0,  0,  0,
-+    0,  0,  3,  4,  0,  0,  5,  0,  0,  0,  6,  0,  0,  0,  0,  0,
-+    0,  0,  7,  1,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,  0,
-+    0,  0, 10,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0, 10,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0, 11, 12,
-+    0, 13,  0, 14, 15, 16,  0,  0,  0,  0,  0,  1, 17, 18,  0, 19,
-+    7,  1,  0,  0,  0, 20, 20,  7, 20, 20, 20, 20, 20, 20, 20,  8,
-+   21,  0, 22,  0,  7, 23, 24,  0, 20, 20, 25,  0,  0,  0, 26, 27,
-+    1,  7, 20, 20, 20, 20, 20,  1, 28, 29, 30, 31,  0,  0, 20,  0,
-+    0,  0,  0,  0,  0,  0, 10,  0,  0,  0,  0,  0,  0,  0, 20, 20,
-+   20,  1,  0,  0,  8, 21, 32,  4,  0, 10,  0, 33,  7, 20, 20, 20,
-+    0,  0,  0,  0,  8, 34, 34, 35, 36, 34, 37,  0, 38,  1, 20, 20,
-+    0,  0, 39,  0,  1,  1,  0,  8, 21,  1, 20,  0,  0,  0,  1,  0,
-+    0, 40,  1,  1,  0,  0,  8, 21,  0,  1,  0,  1,  0,  1,  0,  0,
-+    0,  0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  7, 20, 41,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 21,  0, 42, 43, 44,  0, 45,
-+    0,  8, 21,  0,  0,  0,  0,  0,  0,  0,  0, 46,  7,  1, 10,  1,
-+    0,  0,  0,  1, 20, 20,  1,  0,  0,  0,  0,  0,  0,  0, 20, 20,
-+    1, 20, 20,  0,  0,  0,  0,  0,  0,  0, 26, 21,  0,  1,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  3, 47, 48,  0,  0,  0,
-+    0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  9, 10, 11, 12, 12, 12, 12, 13, 14,
-+   14, 14, 14, 15, 16, 17, 18, 19, 20, 14, 21, 14, 22, 14, 14, 14,
-+   14, 23, 24, 24, 25, 26, 14, 14, 14, 14, 27, 28, 14, 14, 29, 30,
-+   31, 32, 33, 34,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7, 35,  7, 36, 37,  7, 38,  7,  7,
-+    7, 39, 14, 40, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 41,  0,  0,  1,  2,  2,  2,  3,  4,  5,  6,  7,
-+    8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
-+   24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 33, 34, 35, 36, 37, 37,
-+   37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-+   51, 52,  2,  2, 53, 54, 55, 56, 57, 58, 59, 59, 59, 59, 60, 59,
-+   59, 59, 59, 59, 59, 59, 61, 61, 59, 59, 59, 59, 62, 63, 64, 65,
-+   66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 59, 70, 70,
-+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 79, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70, 70, 70, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 82,
-+   83, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 32, 32,
-+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-+   32, 32, 32, 32, 32, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97, 97, 97, 70, 70, 98, 99,100,101,102,102,
-+  103,104,105,106,107,108,109,110,111,112, 97,113,114,115,116,117,
-+  118, 97,119,119,120, 97,121,122,123,124,125,126,127,128,129,130,
-+  131, 97,132, 97,133,134,135,136,137,138,139,140,141, 97,142,143,
-+   97,144,145,146,147, 97,148,149, 97,150,151,152, 97, 97,153,154,
-+  155,156, 97,157, 97,158,159,159,159,159,159,159,159,160,161,159,
-+  162, 97, 97, 97, 97, 97,163,163,163,163,163,163,163,163,164, 97,
-+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,165,165,
-+  165,165,166, 97, 97, 97,167,167,167,167,168,169,170,171, 97, 97,
-+   97, 97,172,173,174,175,176,176,176,176,176,176,176,176,176,176,
-+  176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-+  176,176,176,176,176,177,176,176,176,176,176,178, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97,179,180,181, 32, 32,182, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,183,184,
-+   97, 97, 97, 97, 97, 97, 59,185,186,187,188,189,190, 97,191,192,
-+  193, 59, 59,194, 59,195,196,196,196,196,196,197, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97,198, 97,199, 97, 97,200, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97,201,202,203, 97, 97, 97, 97, 97,204,205,
-+  206, 97,207,208, 97, 97,209,210,211,212,213, 97, 59, 59, 59, 59,
-+   59, 59, 59,214,215,216,217,218,219,220,221,222, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70,223, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70, 70,224, 70,225, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70,226, 70, 70, 70, 70, 70, 70, 70, 70, 70,227, 97, 97,
-+   97, 97, 97, 97, 97, 97, 70, 70, 70, 70,228, 97, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97,229, 97,230,231,  0,  1,  2,  2,  0,  1,
-+    2,  2,  2,  3,  4,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,
-+   19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19,  0,  0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0, 19, 19,
-+   19, 19, 19, 19, 19,  0, 19,  0,  0,  0,  0,  0,  0,  0, 19, 19,
-+   19, 19, 19,  0,  0,  0,  0,  0, 26, 26,  0,  0,  0,  0,  1,  1,
-+    1,  1,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,  2,  2,
-+    9,  9,  9,  9,  0,  9,  2,  2,  2,  2,  9,  0,  9,  0,  9,  9,
-+    9,  2,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    2,  9,  9,  9,  9,  9,  9,  9, 55, 55, 55, 55, 55, 55, 55, 55,
-+   55, 55, 55, 55, 55, 55,  6,  6,  6,  6,  6,  6,  6,  6,  6,  6,
-+    6,  6,  6,  1,  1,  6,  2,  4,  4,  4,  4,  4,  4,  4,  4,  4,
-+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  4,  0,
-+    4,  2,  2,  4,  4,  4,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-+   14, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2,  2,  2,  2, 14, 14,
-+   14,  2,  2,  2,  2, 14, 14, 14, 14, 14, 14,  2,  2,  2,  3,  3,
-+    3,  3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  0,  3,  2,  3,  0,  0,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  1,
-+    1,  1,  1,  1,  3,  3,  1,  3,  3,  3,  3,  3,  3,  3, 37, 37,
-+   37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,  2, 37, 37, 37,
-+   37,  2,  2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-+    2,  2,  2,  2,  2,  2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
-+   64,  2,  2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
-+   90, 90, 90, 90,  2,  2, 90, 90, 90, 90, 90, 90, 90,  2, 95, 95,
-+   95, 95, 95, 95, 95, 95, 95, 95, 95, 95,  2,  2, 95,  2, 37, 37,
-+   37,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,
-+    3,  3,  3,  3,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,
-+    0,  3,  3,  3,  3,  3,  7,  7,  7,  7,  7,  7,  7,  7,  7,  1,
-+    1,  1,  1,  7,  7,  7,  7,  7,  7,  7,  0,  0,  7,  7,  5,  5,
-+    5,  5,  2,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2,  5,  5,  2,
-+    2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,
-+    5,  5,  5,  5,  5,  5,  5,  2,  5,  2,  2,  2,  5,  5,  5,  5,
-+    2,  2,  5,  5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  2,  2,  2,
-+    2,  2,  2,  2,  2,  5,  2,  2,  2,  2,  5,  5,  2,  5,  5,  5,
-+    5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  2,  2, 11,
-+   11, 11,  2, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2, 11, 11,  2,
-+    2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,
-+   11, 11, 11, 11, 11, 11, 11,  2, 11, 11,  2, 11, 11,  2, 11, 11,
-+    2,  2, 11,  2, 11, 11, 11,  2,  2, 11, 11, 11,  2,  2,  2, 11,
-+    2,  2,  2,  2,  2,  2,  2, 11, 11, 11, 11,  2, 11,  2,  2,  2,
-+    2,  2,  2,  2, 11, 11, 11, 11, 11, 11, 11, 11, 11,  2,  2, 10,
-+   10, 10,  2, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,
-+    2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,  2,
-+   10, 10, 10, 10, 10, 10, 10,  2, 10, 10,  2, 10, 10, 10, 10, 10,
-+    2,  2, 10, 10, 10, 10, 10, 10,  2, 10, 10, 10,  2,  2, 10,  2,
-+    2,  2,  2,  2,  2,  2, 10, 10, 10, 10,  2,  2, 10, 10, 10, 10,
-+    2,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10, 10, 10, 10,  2, 21,
-+   21, 21,  2, 21, 21, 21, 21, 21, 21, 21, 21,  2,  2, 21, 21,  2,
-+    2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,  2,
-+   21, 21, 21, 21, 21, 21, 21,  2, 21, 21,  2, 21, 21, 21, 21, 21,
-+    2,  2, 21, 21, 21, 21, 21,  2,  2, 21, 21, 21,  2,  2,  2,  2,
-+    2,  2,  2,  2, 21, 21,  2,  2,  2,  2, 21, 21,  2, 21, 21, 21,
-+   21, 21,  2,  2, 21, 21,  2,  2, 22, 22,  2, 22, 22, 22, 22, 22,
-+   22,  2,  2,  2, 22, 22, 22,  2, 22, 22, 22, 22,  2,  2,  2, 22,
-+   22,  2, 22,  2, 22, 22,  2,  2,  2, 22, 22,  2,  2,  2, 22, 22,
-+   22, 22, 22, 22, 22, 22, 22, 22,  2,  2,  2,  2, 22, 22, 22,  2,
-+    2,  2,  2,  2,  2, 22,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
-+   22,  2,  2,  2,  2,  2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
-+   23, 23, 23,  2, 23, 23, 23,  2, 23, 23, 23, 23, 23, 23, 23, 23,
-+    2,  2,  2, 23, 23, 23, 23,  2, 23, 23, 23, 23,  2,  2,  2,  2,
-+    2,  2,  2, 23, 23,  2, 23, 23, 23,  2,  2,  2,  2,  2, 23, 23,
-+   23, 23,  2,  2, 23, 23,  2,  2,  2,  2,  2,  2,  2, 23, 16, 16,
-+   16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16,  2,
-+   16, 16, 16, 16, 16, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16, 16,
-+    2,  2, 16, 16, 16, 16, 16,  2, 16, 16, 16, 16,  2,  2,  2,  2,
-+    2,  2,  2, 16, 16,  2,  2,  2,  2,  2,  2,  2, 16,  2, 16, 16,
-+   16, 16,  2,  2, 16, 16,  2, 16, 16,  2,  2,  2,  2,  2, 20, 20,
-+   20, 20,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2, 20, 20, 20,  2,
-+   20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2,
-+    2,  2, 20, 20, 20, 20, 20, 20, 20, 20,  2,  2, 20, 20,  2,  2,
-+   36, 36,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36,
-+    2, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,  2,
-+   36,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36,  2, 36,  2,  2,  2,
-+    2,  2,  2,  2, 36, 36,  2,  2, 36, 36, 36,  2,  2,  2,  2, 24,
-+   24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
-+   24,  2,  2,  2,  2,  0, 24, 24, 24, 24,  2,  2,  2,  2,  2, 18,
-+   18,  2, 18,  2, 18, 18, 18, 18, 18,  2, 18, 18, 18, 18, 18, 18,
-+   18, 18, 18, 18, 18, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18, 18,
-+   18, 18, 18, 18,  2,  2, 18, 18, 18, 18, 18,  2, 18,  2, 18, 18,
-+    2,  2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25,  2, 25,
-+   25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,  2,  2,  2, 25, 25,
-+   25, 25, 25,  2, 25, 25, 25, 25, 25, 25, 25,  0,  0,  0,  0, 25,
-+   25,  2,  2,  2,  2,  2, 33, 33, 33, 33, 33, 33, 33, 33,  8,  8,
-+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  2,  8,  2,  2,
-+    2,  2,  2,  8,  2,  2,  8,  8,  8,  0,  8,  8,  8,  8, 12, 12,
-+   12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30,  2,
-+   30, 30, 30, 30,  2,  2, 30, 30, 30, 30, 30, 30, 30,  2, 30, 30,
-+   30,  2,  2, 30, 30, 30, 30, 30, 30, 30, 30,  2,  2,  2, 30, 30,
-+    2,  2,  2,  2,  2,  2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-+   29, 29, 29, 29,  2,  2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,  2,  2,  2, 35, 35,
-+   35, 35, 35, 35, 35, 35, 35, 35, 35,  0,  0,  0, 35, 35, 35,  2,
-+    2,  2,  2,  2,  2,  2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
-+   45, 45, 45,  2, 45, 45, 45, 45, 45, 45, 45,  2,  2,  2, 44, 44,
-+   44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,  0,  0,  2, 43, 43,
-+   43, 43, 43, 43, 43, 43, 43, 43, 43, 43,  2,  2,  2,  2, 46, 46,
-+   46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,  2, 46, 46, 46,  2,
-+   46, 46,  2,  2,  2,  2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
-+   31, 31, 31, 31,  2,  2, 31, 31,  2,  2,  2,  2,  2,  2, 32, 32,
-+    0,  0, 32,  0, 32, 32, 32, 32, 32, 32, 32, 32, 32,  2, 32, 32,
-+   32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,  2,  2,  2, 32,  2,
-+    2,  2,  2,  2,  2,  2, 32, 32, 32,  2,  2,  2,  2,  2, 28, 28,
-+   28, 28, 28, 28,  2,  2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
-+   48, 48, 48, 48, 48,  2, 48, 48, 48, 48,  2,  2,  2,  2, 48,  2,
-+    2,  2, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
-+   52, 52, 52, 52,  2,  2, 52, 52, 52, 52, 52,  2,  2,  2, 58, 58,
-+   58, 58, 58, 58, 58, 58, 58, 58, 58, 58,  2,  2,  2,  2, 58, 58,
-+    2,  2,  2,  2,  2,  2, 58, 58, 58,  2,  2,  2, 58, 58, 54, 54,
-+   54, 54, 54, 54, 54, 54, 54, 54, 54, 54,  2,  2, 54, 54, 91, 91,
-+   91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,  2, 91, 91,
-+   91, 91, 91,  2,  2, 91, 91, 91,  2,  2,  2,  2,  2,  2, 91, 91,
-+   91, 91, 91, 91,  2,  2,  1,  1,  1,  1,  1,  1,  1,  2, 62, 62,
-+   62, 62, 62, 62, 62, 62, 62, 62, 62, 62,  2,  2,  2,  2, 62, 62,
-+   62, 62, 62,  2,  2,  2, 76, 76, 76, 76, 76, 76, 76, 76, 93, 93,
-+   93, 93, 93, 93, 93, 93, 93, 93, 93, 93,  2,  2,  2,  2,  2,  2,
-+    2,  2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70,  2,  2,
-+    2, 70, 70, 70, 70, 70, 70, 70,  2,  2,  2, 70, 70, 70, 73, 73,
-+   73, 73, 73, 73, 73, 73,  6,  2,  2,  2,  2,  2,  2,  2,  8,  8,
-+    8,  2,  2,  8,  8,  8,  1,  1,  1,  0,  1,  1,  1,  1,  1,  0,
-+    1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,
-+    0,  0,  1,  0,  0,  0,  1,  1,  0,  2,  2,  2,  2,  2, 19, 19,
-+   19, 19, 19, 19,  9,  9,  9,  9,  9,  6, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19,  9,  9,  9,  9,  9, 19, 19, 19, 19,  9,  9,  9,  9,
-+    9, 19, 19, 19, 19, 19,  6, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19, 19, 19,  9,  1,  1,  2,  1,  1,  1,  1,  1,  9,  9,
-+    9,  9,  9,  9,  2,  2,  2,  9,  2,  9,  2,  9,  2,  9,  9,  9,
-+    9,  9,  9,  2,  9,  9,  9,  9,  9,  9,  2,  2,  9,  9,  9,  9,
-+    9,  9,  2,  9,  9,  9,  2,  2,  9,  9,  9,  2,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  2,  0,  0,  0,  0,  1,  1,  0,  0,  0,  0,
-+    0,  0,  0,  2,  0,  0,  0, 19,  2,  2,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0,  0,  0,  2, 19, 19,
-+   19, 19, 19,  2,  2,  2,  1,  2,  2,  2,  2,  2,  2,  2,  0,  0,
-+    0,  0,  0,  0,  9,  0,  0,  0, 19, 19,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0, 19,  0, 19,  0,  0,  0,  2,  2,  2,  2,  0,  0,
-+    0,  2,  2,  2,  2,  2, 27, 27, 27, 27, 27, 27, 27, 27,  0,  0,
-+    0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2, 56, 56,
-+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,  2, 55, 55,
-+   55, 55,  2,  2,  2,  2,  2, 55, 55, 55, 55, 55, 55, 55, 61, 61,
-+   61, 61, 61, 61, 61, 61,  2,  2,  2,  2,  2,  2,  2, 61, 61,  2,
-+    2,  2,  2,  2,  2,  2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+    2, 13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13,
-+   13, 13, 13, 13,  2,  2,  0,  0,  0,  0,  2,  2,  2,  2,  0,  0,
-+    0,  0,  0, 13,  0, 13,  0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
-+    1,  1,  1,  1, 12, 12, 13, 13, 13, 13,  0,  0,  0,  0,  2, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15,  2,  2,  1,  1,  0,  0, 15, 15, 15,  0, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17,  0,  0, 17, 17, 17,  2,  2,  2,  2,  2, 26, 26, 26, 26, 26,
-+   26, 26, 26, 26, 26, 26,  2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12,  2, 26, 26, 26,  2,  2,  2,  2,  2, 12, 12,
-+   12, 12, 12, 12, 12,  0, 17, 17, 17, 17, 17, 17, 17,  0, 39, 39,
-+   39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,  2,  2,  2, 39, 39,
-+   39, 39, 39, 39, 39,  2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77,
-+   77, 77, 77, 77, 77, 77, 77, 77, 77, 77,  2,  2,  2,  2, 79, 79,
-+   79, 79, 79, 79, 79, 79,  0,  0, 19, 19, 19, 19, 19, 19,  0,  0,
-+    0, 19, 19, 19, 19, 19,  2,  2, 19, 19, 19, 19, 19,  2,  2,  2,
-+    2,  2,  2,  2,  2, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
-+   60, 60,  2,  2,  2,  2,  0,  0,  2,  2,  2,  2,  2,  2, 65, 65,
-+   65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
-+   75, 75, 75, 75,  2,  2,  2,  2,  2,  2,  2,  2, 75, 75, 75, 75,
-+    2,  2,  2,  2,  2,  2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-+   69, 69, 69, 69,  0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
-+   74, 74,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 74, 12, 12,
-+   12, 12, 12,  2,  2,  2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
-+   84, 84, 84, 84,  2,  0, 84, 84,  2,  2,  2,  2, 84, 84, 33, 33,
-+   33, 33, 33, 33, 33,  2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
-+   68, 68, 68, 68, 68,  2, 68, 68, 68, 68, 68, 68,  2,  2, 68, 68,
-+    2,  2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
-+   92,  2,  2,  2,  2,  2,  2,  2,  2, 92, 92, 92, 92, 92, 87, 87,
-+   87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,  2,  2, 30,
-+   30, 30, 30, 30, 30,  2, 19, 19, 19,  0, 19, 19, 19, 19, 19, 19,
-+   19, 19, 19,  9, 19, 19, 87, 87, 87, 87, 87, 87,  2,  2, 87, 87,
-+    2,  2,  2,  2,  2,  2, 12, 12, 12, 12,  2,  2,  2,  2,  2,  2,
-+    2, 12, 12, 12, 12, 12, 13, 13,  2,  2,  2,  2,  2,  2, 19, 19,
-+   19, 19, 19, 19, 19,  2,  2,  2,  2,  4,  4,  4,  4,  4,  2,  2,
-+    2,  2,  2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,  2, 14, 14,
-+   14, 14, 14,  2, 14,  2, 14, 14,  2, 14, 14,  2, 14, 14,  3,  3,
-+    2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  0,  0,  2,  2,
-+    3,  3,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  6,  6,  0,  0,
-+    0,  2,  0,  0,  0,  0,  3,  3,  3,  3,  3,  2,  2,  0,  2,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 17, 17, 17, 17,
-+   17, 17, 17, 17,  0,  0,  2,  2, 12, 12, 12, 12, 12, 12,  2,  2,
-+   12, 12, 12,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2, 49, 49,
-+   49, 49, 49, 49, 49, 49, 49, 49, 49, 49,  2, 49, 49, 49, 49, 49,
-+   49, 49, 49, 49, 49,  2, 49, 49, 49,  2, 49, 49,  2, 49, 49, 49,
-+   49, 49, 49, 49,  2,  2, 49, 49, 49,  2,  2,  2,  2,  2,  0,  0,
-+    0,  2,  2,  2,  2,  0,  0,  0,  0,  0,  2,  2,  2,  0,  9,  2,
-+    2,  2,  2,  2,  2,  2,  0,  0,  0,  0,  0,  1,  2,  2, 71, 71,
-+   71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,  2,  2,  2, 67, 67,
-+   67, 67, 67, 67, 67, 67, 67,  2,  2,  2,  2,  2,  2,  2,  1,  0,
-+    0,  0,  0,  0,  0,  0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
-+   42, 42,  2,  2,  2,  2,  2,  2,  2,  2,  2, 42, 42, 42, 41, 41,
-+   41, 41, 41, 41, 41, 41, 41, 41, 41,  2,  2,  2,  2,  2,118,118,
-+  118,118,118,118,118,118,118,118,118,  2,  2,  2,  2,  2, 53, 53,
-+   53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,  2, 53, 59, 59,
-+   59, 59, 59, 59, 59, 59, 59, 59, 59, 59,  2,  2,  2,  2, 59, 59,
-+   59, 59, 59, 59,  2,  2, 40, 40, 40, 40, 40, 40, 40, 40, 51, 51,
-+   51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
-+   50, 50, 50, 50,  2,  2, 50, 50,  2,  2,  2,  2,  2,  2,135,135,
-+  135,135,135,135,135,135,135,135,135,135,  2,  2,  2,  2,106,106,
-+  106,106,106,106,106,106,104,104,104,104,104,104,104,104,104,104,
-+  104,104,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,104,110,110,
-+  110,110,110,110,110,110,110,110,110,110,110,110,110,  2,110,110,
-+  110,110,110,110,  2,  2, 47, 47, 47, 47, 47, 47,  2,  2, 47,  2,
-+   47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
-+   47, 47, 47, 47,  2, 47, 47,  2,  2,  2, 47,  2,  2, 47, 81, 81,
-+   81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,  2, 81,120,120,
-+  120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116,
-+  116,116,116,116,116,  2,  2,  2,  2,  2,  2,  2,  2,116,128,128,
-+  128,128,128,128,128,128,128,128,128,  2,128,128,  2,  2,  2,  2,
-+    2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
-+   66, 66,  2,  2,  2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
-+    2,  2,  2,  2,  2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97,
-+   97, 97, 97, 97, 97, 97,  2,  2,  2,  2, 97, 97, 97, 97,  2,  2,
-+   97, 97, 97, 97, 97, 97, 57, 57, 57, 57,  2, 57, 57,  2,  2,  2,
-+    2,  2, 57, 57, 57, 57, 57, 57, 57, 57,  2, 57, 57, 57,  2, 57,
-+   57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
-+   57, 57, 57, 57,  2,  2, 57, 57, 57,  2,  2,  2,  2, 57, 57,  2,
-+    2,  2,  2,  2,  2,  2, 88, 88, 88, 88, 88, 88, 88, 88,117,117,
-+  117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112,
-+  112,112,112,112,112,  2,  2,  2,  2,112,112,112,112,112, 78, 78,
-+   78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,  2,  2,  2, 78,
-+   78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
-+   83, 83, 83, 83,  2,  2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
-+   82,  2,  2,  2,  2,  2,122,122,122,122,122,122,122,122,122,122,
-+    2,  2,  2,  2,  2,  2,  2,122,122,122,122,  2,  2,  2,  2,122,
-+  122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89,  2,
-+    2,  2,  2,  2,  2,  2,130,130,130,130,130,130,130,130,130,130,
-+  130,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,130,130,  3,  3,
-+    3,  3,  3,  3,  3,  2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
-+   94, 94, 94, 94,  2,  2,  2,  2, 94, 94, 94, 94, 94, 94,  2,  2,
-+    2,  2,  2,  2,  2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,
-+  101,101,101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,
-+    2,  2,  2,  2,  2,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
-+   96, 96, 96,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96,  2,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,  2,100,100,
-+  100,100,100,100,100,100,100,100,100,100,100,100,  2,  2,  2, 36,
-+   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,108,108,
-+  108,108,108,108,108,108,108,108,  2,108,108,108,108,108,108,108,
-+  108,108,108,108,108,  2,129,129,129,129,129,129,129,  2,129,  2,
-+  129,129,129,129,  2,129,129,129,129,129,129,129,129,129,129,129,
-+  129,129,129,129,  2,129,129,129,  2,  2,  2,  2,  2,  2,109,109,
-+  109,109,109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,
-+    2,  2,  2,  2,  2,  2,107,107,107,107,  2,107,107,107,107,107,
-+  107,107,107,  2,  2,107,107,  2,  2,107,107,107,107,107,107,107,
-+  107,107,107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,
-+  107,107,  2,107,107,107,107,107,  2,  1,107,107,107,107,107,  2,
-+    2,107,107,107,  2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,
-+    2,  2,  2,107,107,107,107,107,107,107,  2,  2,107,107,107,107,
-+  107,107,107,  2,  2,  2,137,137,137,137,137,137,137,137,137,137,
-+    2,137,  2,137,137,137,124,124,124,124,124,124,124,124,124,124,
-+    2,  2,  2,  2,  2,  2,123,123,123,123,123,123,123,123,123,123,
-+  123,123,123,123,  2,  2,114,114,114,114,114,114,114,114,114,114,
-+  114,114,114,  2,  2,  2,114,114,  2,  2,  2,  2,  2,  2, 32, 32,
-+   32, 32, 32,  2,  2,  2,102,102,102,102,102,102,102,102,102,  2,
-+    2,  2,  2,  2,  2,  2,102,102,  2,  2,  2,  2,  2,  2,126,126,
-+  126,126,126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,
-+  126,126,  2,  2,  2,  2,  4,  4,  4,  4,  2,  2,  2,  2,125,125,
-+  125,125,125,125,125,125,125,125,125,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2,  2,  2,125,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,
-+    5,  5,  5,  2,  2,  2,  7,  7,  7,  2,  2,  2,  2,  2,121,121,
-+  121,121,121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,133,133,
-+  133,133,133,133,133,133,133,  2,133,133,133,133,133,133,133,133,
-+  133,133,133,133,133,  2,133,133,133,133,133,133,  2,  2,133,133,
-+  133,133,133,  2,  2,  2,134,134,134,134,134,134,134,134,  2,  2,
-+  134,134,134,134,134,134,  2,134,134,134,134,134,134,134,134,134,
-+  134,134,134,134,134,  2,  8,  8,  8,  8,  8,  8,  8,  2,  8,  8,
-+    2,  8,  8,  8,  8,  8,  2,  2,  8,  2,  8,  8,  2,  8,  8,  8,
-+    2,  2,  2,  2,  2,  2,  9,  9,  9,  9,  9,  9,  2,  9,  9,  2,
-+    9,  9,  9,  9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2, 22, 22,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63,
-+   63, 63, 63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63,
-+   63, 63, 63, 63, 63,  2, 63, 63, 63, 63, 63,  2,  2,  2, 63, 63,
-+   63, 63,  2,  2,  2,  2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
-+   80, 80, 80, 80, 80,  2, 80,  2,  2,  2,  2,  2,  2,  2,127,127,
-+  127,127,127,127,127,127,127,127,127,127,127,127,127,  2, 79,  2,
-+    2,  2,  2,  2,  2,  2,115,115,115,115,115,115,115,115,115,115,
-+  115,115,115,115,115,  2,115,115,  2,  2,  2,  2,115,115,103,103,
-+  103,103,103,103,103,103,103,103,103,103,103,103,  2,  2,119,119,
-+  119,119,119,119,119,119,119,119,119,119,119,119,  2,  2,119,119,
-+    2,119,119,119,119,119,  2,  2,  2,  2,  2,119,119,119, 11, 11,
-+   11,  2,  2,  2,  2,  2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-+   99,  2,  2,  2,  2, 99,  2,  2,  2,  2,  2,  2,  2, 99,136, 12,
-+    0,  0,  2,  2,  2,  2,136,136,136,136,136,136,136,136,136,136,
-+  136,  2,  2,  2,  2,  2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15,  2,  2,  2,  2,  2,  2,  2,  2,  2, 17, 17, 17, 17,105,105,
-+  105,105,105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,
-+  105,105,105,  2,  2,  2,105,  2,  2,  2,  2,  2,  2,  2,105,105,
-+    2,  2,105,105,105,105,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,
-+    1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
-+    1,  1,  1,  1,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,
-+    0,  2,  2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
-+    2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,
-+    2,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,  2,  2,  2,
-+    0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,131,131,
-+  131,131,131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,
-+    2,131,131,131,131,131,  2,131,131,131,131,131,131,131, 56,  2,
-+    2, 56, 56, 56, 56, 56, 56, 56,  2, 56, 56,  2, 56, 56, 56, 56,
-+   56,  2,  2,  2,  2,  2, 13, 13, 13, 13, 13,  2,  2,  2, 13, 13,
-+    2,  2,  2,  2, 13, 13, 14, 14,  2,  2,  2,  2,  2, 14,113,113,
-+  113,113,113,113,113,113,113,113,113,113,113,  2,  2,113,113,113,
-+  113,113,113,113,113,  2,132,132,132,132,132,132,132,132,132,132,
-+  132,132,  2,  2,  2,  2,132,132,  2,  2,  2,  2,132,132,  0,  0,
-+    0,  0,  0,  2,  2,  2,  3,  3,  3,  3,  2,  3,  3,  3,  2,  3,
-+    3,  2,  3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-+    3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,
-+    3,  2,  2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,
-+    2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,
-+    2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
-+    3,  3,  2,  3,  3,  3,  2,  2,  2,  2,  2,  2,  0,  0, 15,  0,
-+    0,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  0,  0, 13, 13,
-+   13, 13, 13, 13, 13,  2, 13,  2,  2,  2,  2,  2,  2,  2,  2,  0,
-+    2,  2,  2,  2,  2,  2, 16, 50, 84,118, 88, 89, 90, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 91, 85, 85,220, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  0,
-+   13, 14, 15, 16, 17, 18, 19, 20, 21, 22,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0,  0, 24, 25, 26,
-+   27, 28, 29, 30,  0,  0, 31, 32,  0, 33,  0, 34,  0, 35,  0,  0,
-+    0,  0, 36, 37, 38, 39,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 41, 42,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0, 43, 44,  0, 45,  0,  0,  0,  0,
-+    0,  0, 46, 47,  0,  0,  0,  0,  0, 48,  0, 49,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 50, 51,  0,  0,  0, 52,
-+    0,  0, 53,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0,  0,
-+    0,  0, 55,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,
-+    0,  0,  0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 58, 59, 60, 61, 62, 63,
-+   64, 65,  0,  0,  0,  0,  0,  0, 66,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 67, 68,  0, 69, 70,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
-+   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
-+   97, 98, 99,100,101,102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,104,  0,  0,  0,  0,  0,  0,105,
-+  106,  0,107,  0,  0,  0,108,  0,109,  0,110,  0,111,112,113,  0,
-+  114,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,117,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,118,119,120,121,  0,122,
-+  123,124,125,126,  0,127,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,128,129,130,131,132,133,134,135,136,137,
-+  138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
-+  154,155,156,157,  0,  0,  0,158,159,160,161,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,162,
-+  163,  0,  0,  0,  0,  0,  0,  0,164,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,165,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,166,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,167,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,168,169,  0,  0,  0,
-+    0,170,171,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,172,173,174,175,176,177,178,179,180,181,
-+  182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
-+  198,199,200,201,202,203,204,205,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  1,  2,  3,  4,
-+};
-+static const uint16_t
-+_hb_ucd_u16[8928] =
-+{
-+     0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
-+    13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
-+    13,  13,  13,  24,  25,  11,  11,  11,  11,  26,  11,  27,  28,  29,  30,  31,
-+    32,  32,  32,  32,  32,  32,  32,  33,  34,  35,  36,  11,  37,  38,  13,  39,
-+     9,   9,   9,  11,  11,  11,  13,  13,  40,  13,  13,  13,  41,  13,  13,  13,
-+    13,  13,  13,  42,   9,  43,  11,  11,  44,  45,  32,  46,  47,  48,  49,  50,
-+    51,  52,  48,  48,  53,  32,  54,  55,  48,  48,  48,  48,  48,  56,  57,  58,
-+    59,  60,  48,  32,  61,  48,  48,  48,  48,  48,  62,  63,  64,  48,  65,  66,
-+    48,  67,  68,  69,  48,  70,  71,  72,  72,  72,  48,  73,  72,  74,  75,  32,
-+    76,  48,  48,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
-+    90,  83,  84,  91,  92,  93,  94,  95,  96,  97,  84,  98,  99, 100,  88, 101,
-+   102,  83,  84, 103, 104, 105,  88, 106, 107, 108, 109, 110, 111, 112,  94, 113,
-+   114, 115,  84, 116, 117, 118,  88, 119, 120, 115,  84, 121, 122, 123,  88, 124,
-+   125, 115,  48, 126, 127, 128,  88, 129, 130, 131,  48, 132, 133, 134,  94, 135,
-+   136,  48,  48, 137, 138, 139,  72,  72, 140,  48, 141, 142, 143, 144,  72,  72,
-+   145, 146, 147, 148, 149,  48, 150, 151, 152, 153,  32, 154, 155, 156,  72,  72,
-+    48,  48, 157, 158, 159, 160, 161, 162, 163, 164,   9,   9, 165,  11,  11, 166,
-+    48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 167, 168,  48,  48,
-+   167,  48,  48, 169, 170, 171,  48,  48,  48, 170,  48,  48,  48, 172, 173, 174,
-+    48, 175,   9,   9,   9,   9,   9, 176, 177,  48,  48,  48,  48,  48,  48,  48,
-+    48,  48,  48,  48,  48,  48, 178,  48, 179, 180,  48,  48,  48,  48, 181, 182,
-+   183, 184,  48, 185,  48, 186, 183, 187,  48,  48,  48, 188, 189, 190, 191, 192,
-+   193, 191,  48,  48, 194,  48,  48, 195, 196,  48, 197,  48,  48,  48,  48, 198,
-+    48, 199, 200, 201, 202,  48, 203, 204,  48,  48, 205,  48, 206, 207, 208, 208,
-+    48, 209,  48,  48,  48, 210, 211, 212, 191, 191, 213, 214,  72,  72,  72,  72,
-+   215,  48,  48, 216, 217, 159, 218, 219, 220,  48, 221,  64,  48,  48, 222, 223,
-+    48,  48, 224, 225, 226,  64,  48, 227, 228,   9,   9, 229, 230, 231, 232, 233,
-+    11,  11, 234,  27,  27,  27, 235, 236,  11, 237,  27,  27,  32,  32,  32, 238,
-+    13,  13,  13,  13,  13,  13,  13,  13,  13, 239,  13,  13,  13,  13,  13,  13,
-+   240, 241, 240, 240, 241, 242, 240, 243, 244, 244, 244, 245, 246, 247, 248, 249,
-+   250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 260,  72, 261, 262, 263,
-+   264, 265, 266, 267, 268, 269, 270, 270, 271, 272, 273, 208, 274, 275, 208, 276,
-+   277, 277, 277, 277, 277, 277, 277, 277, 278, 208, 279, 208, 208, 208, 208, 280,
-+   208, 281, 277, 282, 208, 283, 284, 208, 208, 208, 285,  72, 286,  72, 269, 269,
-+   269, 287, 208, 208, 208, 208, 288, 269, 208, 208, 208, 208, 208, 208, 208, 208,
-+   208, 208, 208, 289, 290, 208, 208, 291, 208, 208, 208, 208, 208, 208, 292, 208,
-+   208, 208, 208, 208, 208, 208, 293, 294, 269, 295, 208, 208, 296, 277, 297, 277,
-+   298, 299, 277, 277, 277, 300, 277, 301, 208, 208, 208, 277, 302, 208, 208, 303,
-+   208, 304, 208, 208, 208, 208, 208, 208,   9,   9, 305,  11,  11, 306, 307, 308,
-+    13,  13,  13,  13,  13,  13, 309, 310,  11,  11, 311,  48,  48,  48, 312, 313,
-+    48, 314, 315, 315, 315, 315,  32,  32, 316, 317, 318, 319, 320,  72,  72,  72,
-+   208, 321, 208, 208, 208, 208, 208, 322, 208, 208, 208, 208, 208, 323,  72, 324,
-+   325, 326, 327, 328, 136,  48,  48,  48,  48, 329, 177,  48,  48,  48,  48, 330,
-+   331,  48,  48, 136,  48,  48,  48,  48, 199, 332,  48,  71, 208, 208, 322,  48,
-+   208, 333, 334, 208, 335, 336, 208, 208, 334, 208, 208, 336, 208, 208, 208, 208,
-+    48,  48,  48, 198, 208, 208, 208, 208,  48,  48,  48,  48,  48,  48,  48,  72,
-+    48, 337,  48,  48,  48,  48,  48,  48, 150, 208, 208, 208, 285,  48,  48, 227,
-+   338,  48, 339,  72,  13,  13, 340, 341,  13, 342,  48,  48,  48,  48, 343, 344,
-+    31, 345, 346, 347,  13,  13,  13, 348, 349, 350, 351, 352, 353,  72,  72, 354,
-+   355,  48, 356, 357,  48,  48,  48, 358, 359,  48,  48, 360, 361, 191,  32, 362,
-+    64,  48, 363,  48, 364, 365,  48, 150,  76,  48,  48, 366, 367, 368, 369, 370,
-+    48,  48, 371, 372, 373, 374,  48, 375,  48,  48,  48, 376, 377, 378, 379, 380,
-+   381, 382, 315,  11,  11, 383, 384,  11,  11,  11,  11,  11,  48,  48, 385, 191,
-+    48,  48, 386,  48, 387,  48,  48, 205, 388, 388, 388, 388, 388, 388, 388, 388,
-+   389, 389, 389, 389, 389, 389, 389, 389,  48,  48,  48,  48,  48,  48, 203,  48,
-+    48,  48,  48,  48,  48, 206,  72,  72, 390, 391, 392, 393, 394,  48,  48,  48,
-+    48,  48,  48, 395, 396, 397,  48,  48,  48,  48,  48, 398,  72,  48,  48,  48,
-+    48, 399,  48,  48, 400,  72,  72, 401,  32, 402,  32, 403, 404, 405, 406, 407,
-+    48,  48,  48,  48,  48,  48,  48, 408, 409,   2,   3,   4,   5, 410, 411, 412,
-+    48, 413,  48, 199, 414, 415, 416, 417, 418,  48, 171, 419, 203, 203,  72,  72,
-+    48,  48,  48,  48,  48,  48,  48,  71, 420, 269, 269, 421, 270, 270, 270, 422,
-+   423, 324, 424,  72,  72, 208, 208, 425,  72,  72,  72,  72,  72,  72,  72,  72,
-+    48, 150,  48,  48,  48, 100, 426, 427,  48,  48, 428,  48, 429,  48,  48, 430,
-+    48, 431,  48,  48, 432, 433,  72,  72,   9,   9, 434,  11,  11,  48,  48,  48,
-+    48, 203, 191,   9,   9, 435,  11, 436,  48,  48, 400,  48,  48,  48, 437,  72,
-+    48,  48,  48, 314,  48, 198, 400,  72, 438,  48,  48, 439,  48, 440,  48, 441,
-+    48, 199, 442,  72,  72,  72,  48, 443,  48, 444,  48, 445,  72,  72,  72,  72,
-+    48,  48,  48, 446, 269, 447, 269, 269, 448, 449,  48, 450, 451, 452,  48, 453,
-+    48, 454,  72,  72, 455,  48, 456, 457,  48,  48,  48, 458,  48, 459,  48, 460,
-+    48, 461, 462,  72,  72,  72,  72,  72,  48,  48,  48,  48, 195,  72,  72,  72,
-+     9,   9,   9, 463,  11,  11,  11, 464,  48,  48, 465, 191,  72,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72, 269, 466,  48, 454, 467,  48,  62, 468,  72,  72,
-+    72,  72,  72,  72,  72,  72,  48, 314, 469,  48,  48, 470, 471, 447, 472, 473,
-+   220,  48,  48, 474, 475,  48, 195, 191, 476,  48, 477, 478, 479,  48,  48, 480,
-+   220,  48,  48, 481, 482, 483, 484, 485,  48,  97, 486, 487,  72,  72,  72,  72,
-+   488, 489, 490,  48,  48, 491, 492, 191, 493,  83,  84, 494, 495, 496, 497, 498,
-+    48,  48,  48, 499, 500, 501,  72,  72,  48,  48,  48, 502, 503, 191,  72,  72,
-+    48,  48, 504, 505, 506, 507,  72,  72,  48,  48,  48, 508, 509, 191, 510,  72,
-+    48,  48, 511, 512, 191,  72,  72,  72,  48, 172, 513, 514,  72,  72,  72,  72,
-+    48,  48, 486, 515,  72,  72,  72,  72,  72,  72,   9,   9,  11,  11, 147, 516,
-+    72,  72, 517,  48,  48, 518, 519,  72, 520,  48,  48, 521, 522, 523,  48,  48,
-+   524, 525, 526,  72,  48,  48,  48, 195,  84,  48, 504, 527, 528, 147, 174, 529,
-+    48, 530, 531, 532,  72,  72,  72,  72, 533,  48,  48, 534, 535, 191, 536,  48,
-+   537, 538, 191,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  72,  48, 539,
-+    72,  72,  72,  72, 269, 540, 541, 542,  48, 206,  72,  72,  72,  72,  72,  72,
-+   270, 270, 270, 270, 270, 270, 543, 544,  48,  48,  48,  48, 386,  72,  72,  72,
-+    48,  48, 199, 545,  72,  72,  72,  72,  48,  48,  48,  48, 314,  72,  72,  72,
-+    48,  48,  48, 195,  48, 199, 368,  72,  72,  72,  72,  72,  72,  48, 203, 546,
-+    48,  48,  48, 547, 548, 549, 550, 551,  48,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72,  72,   9,   9,  11,  11, 269, 552,  72,  72,  72,  72,  72,  72,
-+    48,  48,  48,  48, 553, 554, 555, 555, 556, 557,  72,  72,  72,  72, 558,  72,
-+    48,  48,  48,  48,  48,  48,  48, 400,  48,  48,  48,  48,  48,  48,  48, 559,
-+    48, 199,  72,  72,  72, 559, 560,  48,  48,  48,  48,  48,  48,  48,  48, 205,
-+    48,  48,  48,  48,  48,  48,  71, 150, 195, 561, 562,  72,  72,  72,  72,  72,
-+   208, 208, 208, 208, 208, 208, 208, 323, 208, 208, 563, 208, 208, 208, 564, 565,
-+   566, 208, 567, 208, 208, 208, 568,  72, 208, 208, 208, 208, 569,  72,  72,  72,
-+    72,  72,  72,  72,  72,  72, 269, 570, 208, 208, 208, 208, 208, 285, 269, 451,
-+     9, 571,  11, 572, 573, 574, 240,   9, 575, 576, 577, 578, 579,   9, 571,  11,
-+   580, 581,  11, 582, 583, 584, 585,   9, 586,  11,   9, 571,  11, 572, 573,  11,
-+   240,   9, 575, 585,   9, 586,  11,   9, 571,  11, 587,   9, 588, 589, 590, 591,
-+    11, 592,   9, 593, 594, 595, 596,  11, 597,   9, 598,  11, 599, 600, 600, 600,
-+    32,  32,  32, 601,  32,  32, 602, 603, 604, 605,  45,  72,  72,  72,  72,  72,
-+   606, 607, 608,  72,  72,  72,  72,  72,  48,  48, 150, 609, 610,  72,  72,  72,
-+    72,  72,  72,  72,  48,  48, 611, 612,  48,  48,  48,  48, 613, 614,  72,  72,
-+     9,   9, 575,  11, 615, 368,  72,  72,  72,  72,  72,  72,  72,  72,  72, 484,
-+   269, 269, 616, 617,  72,  72,  72,  72, 484, 269, 618, 619,  72,  72,  72,  72,
-+   620,  48, 621, 622, 623, 624, 625, 626, 627, 205, 628, 205,  72,  72,  72, 629,
-+   208, 208, 324, 208, 208, 208, 208, 208, 208, 322, 333, 630, 630, 630, 208, 323,
-+   174, 208, 208, 208, 208, 208, 631, 208, 208, 208, 631,  72,  72,  72, 632, 208,
-+   633, 208, 208, 324, 568, 634, 323,  72, 208, 208, 208, 208, 208, 208, 208, 635,
-+   208, 208, 208, 208, 208, 323, 631, 286, 208, 208, 208, 208, 208, 208, 208, 322,
-+   208, 208, 208, 208, 208, 568, 324,  72, 324, 208, 208, 208, 636, 175, 208, 208,
-+   636, 208, 637,  72,  72,  72,  72,  72, 638, 208, 208, 208, 208, 208, 208, 639,
-+   208, 208, 640, 208, 641, 208, 208, 208, 208, 208, 208, 208, 208, 322, 637, 642,
-+   633, 323,  72,  72,  72,  72,  72,  72,  48,  48,  48,  48,  48, 314,  72,  72,
-+    48,  48,  48, 204,  48,  48,  48,  48,  48, 203,  48,  48,  48,  48,  48,  48,
-+    48,  48, 643,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48,  48, 100,  72,
-+    48, 203,  72,  72,  72,  72,  72,  72, 644,  72, 645, 645, 645, 645, 645, 645,
-+    32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  72,
-+   389, 389, 389, 389, 389, 389, 389, 646, 389, 389, 389, 389, 389, 389, 389, 647,
-+     0,   0,   0,   0,   0,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3,
-+     0,   0,   0,   0,   0,   4,   0,   4,   2,   2,   5,   2,   2,   2,   5,   2,
-+     2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-+     2,   2,   2,   2,   2,   2,   2,   6,   0,   0,   0,   0,   7,   8,   0,   0,
-+     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,  10,  11,
-+    12,  13,  14,  14,  15,  14,  14,  14,  14,  14,  14,  14,  16,  17,  14,  14,
-+    18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,
-+    19,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,  18,
-+    18,  18,  18,  18,  18,  18,  20,  21,  21,  21,  22,  20,  21,  21,  21,  21,
-+    21,  23,  24,  25,  25,  25,  25,  25,  25,  26,  25,  25,  25,  27,  28,  26,
-+    29,  30,  31,  32,  31,  31,  31,  31,  33,  34,  35,  31,  31,  31,  36,  31,
-+    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  29,  31,  31,  31,  31,
-+    37,  38,  37,  37,  37,  37,  37,  37,  37,  39,  31,  31,  31,  31,  31,  31,
-+    40,  40,  40,  40,  40,  40,  41,  26,  42,  42,  42,  42,  42,  42,  42,  43,
-+    44,  44,  44,  44,  44,  45,  44,  46,  47,  47,  47,  48,  37,  49,  26,  26,
-+    26,  26,  26,  26,  31,  31,  50,  51,  26,  26,  52,  31,  53,  31,  31,  31,
-+    54,  54,  54,  54,  54,  54,  54,  54,  54,  54,  55,  54,  56,  54,  54,  54,
-+    57,  58,  59,  60,  60,  61,  62,  63,  58,  64,  65,  66,  67,  60,  60,  68,
-+    69,  70,  71,  72,  72,  73,  74,  75,  70,  76,  77,  78,  79,  72,  80,  26,
-+    81,  82,  83,  84,  84,  85,  86,  87,  82,  88,  89,  26,  90,  84,  91,  92,
-+    93,  94,  95,  96,  96,  97,  98,  99,  94, 100, 101, 102, 103,  96,  96,  26,
-+   104, 105, 106, 107, 108, 105, 109, 110, 105, 106, 111,  26, 112, 109, 109, 113,
-+   114, 115, 116, 114, 114, 116, 114, 117, 115, 118, 119, 120, 121, 114, 122, 114,
-+   123, 124, 125, 123, 123, 125, 126, 127, 124, 128, 129, 130, 131, 123, 132,  26,
-+   133, 134, 135, 136, 136, 136, 136, 136, 134, 135, 137, 136, 138, 136, 136, 136,
-+   139, 140, 141, 142, 140, 140, 143, 144, 141, 145, 146, 140, 147, 140, 148,  26,
-+   149, 150, 150, 150, 150, 150, 150, 151, 150, 150, 150, 152,  26,  26,  26,  26,
-+   153, 154, 155, 155, 156, 155, 155, 157, 158, 157, 155, 159,  26,  26,  26,  26,
-+   160, 160, 160, 160, 160, 160, 160, 160, 160, 161, 160, 160, 160, 162, 161, 160,
-+   160, 160, 160, 161, 160, 160, 160, 163, 160, 163, 164, 165,  26,  26,  26,  26,
-+   166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166,
-+   166, 166, 166, 166, 167, 167, 167, 167, 168, 169, 167, 167, 167, 167, 167, 170,
-+   171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171,
-+   172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 174, 173, 172, 172, 172, 172,
-+   172, 173, 172, 172, 172, 172, 173, 174, 173, 172, 174, 172, 172, 172, 172, 172,
-+   172, 172, 173, 172, 172, 172, 172, 172, 172, 172, 172, 175, 172, 172, 172, 176,
-+   172, 172, 172, 177, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 179, 179,
-+   180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180,
-+   181, 181, 181, 182, 183, 183, 183, 183, 183, 183, 183, 183, 183, 184, 183, 185,
-+   186, 187, 188,  26, 189, 189, 190,  26, 191, 191, 192,  26, 193, 194, 195,  26,
-+   196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 197, 196, 198, 196, 198,
-+   199, 200, 201, 202, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 201, 203,
-+   201, 201, 201, 201, 201, 204, 180, 180, 180, 180, 180, 180, 180, 180, 205,  26,
-+   206, 206, 206, 207, 206, 208, 206, 208, 209, 206, 210, 210, 210, 211, 212,  26,
-+   213, 213, 213, 213, 213, 214, 213, 213, 213, 215, 213, 216, 196, 196, 196, 196,
-+   217, 217, 217, 218, 219, 219, 219, 219, 219, 219, 219, 220, 219, 219, 219, 221,
-+   219, 222, 219, 222, 219, 223,   9, 224,  26,  26,  26,  26,  26,  26,  26,  26,
-+   225, 225, 225, 225, 225, 225, 225, 225, 225, 226, 225, 225, 225, 225, 225, 227,
-+   228, 228, 228, 228, 228, 228, 228, 228, 229, 229, 229, 229, 229, 229, 230, 231,
-+   232, 232, 232, 232, 232, 232, 232, 233, 232, 234, 235, 235, 235, 235, 235, 235,
-+    18, 236, 167, 167, 167, 167, 167, 237, 228,  26, 238,   9, 239, 240, 241, 242,
-+     2,   2,   2,   2, 243, 244,   2,   2,   2,   2,   2, 245, 246, 247,   2, 248,
-+     2,   2,   2,   2,   2,   2,   2, 249,   9,   9,   9,   9,   9,   9,   9, 250,
-+    14,  14, 251, 251,  14,  14,  14,  14, 251, 251,  14, 252,  14,  14,  14, 251,
-+    14,  14,  14,  14,  14,  14, 253,  14, 253,  14, 254, 255,  14,  14, 256, 257,
-+     0, 258,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 259,   0, 260, 261,
-+     0, 262,   2, 263,   0,   0,   0,   0,  26,  26,   9,   9,   9,   9, 264,  26,
-+     0,   0,   0,   0, 265, 266,   4,   0,   0, 267,   0,   0,   2,   2,   2,   2,
-+     2, 268,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0, 262,  26,  26,  26,   0, 269,  26,  26,   0,   0,   0,   0,
-+   270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 271,   0,
-+     0,   0, 272,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   273, 273, 273, 273, 273, 274, 273, 273, 273, 273, 273, 274,   2,   2,   2,   2,
-+    17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17,  17, 275, 276,
-+   167, 167, 167, 167, 168, 169, 277, 277, 277, 277, 277, 277, 277, 278, 279, 278,
-+   172, 172, 174,  26, 174, 174, 174, 174, 174, 174, 174, 174,  18,  18,  18,  18,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  26,  26,  26,  26,  26,  26,
-+   280, 280, 280, 281, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 282,  26,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 283,  26,  26,  26,   0, 284,
-+   285,   0,   0,   0, 286, 287,   0, 288, 289, 290, 290, 290, 290, 290, 290, 290,
-+   290, 290, 291, 292, 293, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 295,
-+   296, 297, 297, 297, 297, 297, 298, 171, 171, 171, 171, 171, 171, 171, 171, 171,
-+   171, 299,   0,   0, 297, 297, 297, 300,   0,   0,   0,   0, 284,  26, 294, 294,
-+   171, 171, 171, 299,   0,   0,   0,   0,   0,   0,   0,   0, 171, 171, 171, 301,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 294, 294, 294, 294, 294, 302,
-+   294, 294, 294, 294, 294, 294, 294, 294, 294, 294, 294,   0,   0,   0,   0,   0,
-+   280, 280, 280, 280, 280, 280, 283,  26,   0,   0,   0,   0,   0,   0,   0,   0,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,  26,  26,
-+   303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303,
-+   303, 304, 303, 303, 303, 303, 303, 303, 305,  26, 306, 306, 306, 306, 306, 306,
-+   307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
-+   307, 307, 307, 307, 307, 308,  26,  26,  18,  18,  18,  18,  18,  18,  18,  18,
-+    18,  18,  18,  18, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,  26,
-+     0,   0,   0,   0, 310,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
-+     2, 311,   2,   2,   2,   2,   2,   2, 312,  26,  26,  26,  26,  26, 313,   2,
-+   314, 314, 314, 314, 314, 315,   0, 316, 317, 317, 317, 317, 317, 317, 317,  26,
-+   318, 318, 318, 318, 318, 318, 318, 318, 319, 320, 318, 321,  54,  54,  54,  54,
-+   322, 322, 322, 322, 322, 323, 324, 324, 324, 324, 325, 326, 171, 171, 171, 327,
-+   328, 328, 328, 328, 328, 328, 328, 328, 328, 329, 328, 330, 166, 166, 166, 331,
-+   332, 332, 332, 332, 332, 332, 333,  26, 332, 334, 332, 335, 166, 166, 166, 166,
-+   336, 336, 336, 336, 336, 336, 336, 336, 337,  26,  26, 338, 339, 339, 340,  26,
-+   341, 341, 341,  26, 174, 174,   2,   2,   2,   2,   2, 342, 343,  26, 178, 178,
-+   178, 178, 178, 178, 178, 178, 178, 178, 339, 339, 339, 339, 339, 344, 339, 345,
-+   171, 171, 171, 171, 346,  26, 171, 171, 299, 347, 171, 171, 171, 171, 171, 346,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 283, 280, 280,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 348,  26,  26,  26,  26,
-+   349,  26, 350, 351,  25,  25, 352, 353, 354,  25,  31,  31,  31,  31,  31,  31,
-+    31,  31,  31,  31,  31,  31,  31,  31, 355,  26,  52,  31,  31,  31,  31,  31,
-+    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,
-+    31,  31,  31,  31,  31,  31,  31, 356,  26,  26,  31,  31,  31,  31,  31,  31,
-+    31,  31, 357,  31,  31,  31,  31,  31,  31,  26,  26,  26,  26,  26,  31,  51,
-+     9,   9,   0, 316,   9, 358,   0,   0,   0,   0, 359,   0, 262, 284,  50,  31,
-+    31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31,  31, 360,
-+   361,   0,   0,   0,   1,   2,   2,   3,   1,   2,   2,   3, 362, 294, 293, 294,
-+   294, 294, 294, 363, 171, 171, 171, 299, 364, 364, 364, 365, 262, 262,  26, 366,
-+   367, 368, 367, 367, 369, 367, 367, 370, 367, 371, 367, 371,  26,  26,  26,  26,
-+   367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 367, 372,
-+   373,   0,   0,   0,   0,   0, 374,   0,  14,  14,  14,  14,  14,  14,  14,  14,
-+    14, 257,   0, 284, 375,  26,  26,  26,  26,  26,   0,   0,   0,   0,   0, 376,
-+   377, 377, 377, 378, 379, 379, 379, 379, 379, 379, 380,  26, 381,   0,   0, 284,
-+   382, 382, 382, 382, 383, 384, 385, 385, 385, 386, 387, 387, 387, 387, 387, 388,
-+   389, 389, 389, 390, 391, 391, 391, 391, 392, 391, 393,  26,  26,  26,  26,  26,
-+   394, 394, 394, 394, 394, 394, 394, 394, 394, 394, 395, 395, 395, 395, 395, 395,
-+   396, 396, 396, 397, 396, 398, 399, 399, 399, 399, 400, 399, 399, 399, 399, 400,
-+   401, 401, 401, 401, 401,  26, 402, 402, 402, 402, 402, 402, 403, 404,  26,  26,
-+   405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405, 405,
-+   405, 405, 405, 405, 405, 405, 406,  26, 405, 405, 407,  26, 405,  26,  26,  26,
-+   408, 409, 410, 410, 410, 410, 411, 412, 413, 413, 414, 413, 415, 415, 415, 415,
-+   416, 416, 416, 417, 418, 416,  26,  26,  26,  26,  26,  26, 419, 419, 420, 421,
-+   422, 422, 422, 423, 424, 424, 424, 425,  26,  26,  26,  26,  26,  26,  26,  26,
-+   426, 426, 426, 426, 427, 427, 427, 428, 427, 427, 429, 427, 427, 427, 427, 427,
-+   430, 431, 432, 433, 434, 434, 435, 436, 434, 437, 434, 437, 438, 438, 438, 438,
-+   439, 439, 439, 439,  26,  26,  26,  26, 440, 440, 440, 440, 441, 442, 441,  26,
-+   443, 443, 443, 443, 443, 443, 444, 445, 446, 446, 447, 446, 448, 448, 449, 448,
-+   450, 450, 451, 452,  26, 453,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   454, 454, 454, 454, 454, 454, 454, 454, 454, 455,  26,  26,  26,  26,  26,  26,
-+   456, 456, 456, 456, 456, 456, 457,  26, 456, 456, 456, 456, 456, 456, 457, 458,
-+     0,   0,   0,   0,   0,  26,   0, 316,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31,  31, 459,
-+     9,   9,   9,   9,   9,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31, 459,  26,
-+   460, 460, 460, 460, 460, 460, 460, 460, 460, 461, 462, 460, 460, 460,  26, 463,
-+   464, 464, 464, 464, 464, 464, 464, 464, 465, 466, 467, 467, 467, 468, 467, 469,
-+   470, 470, 470, 470, 470, 470, 471, 470, 472,  26, 473, 473, 473, 473, 474,  26,
-+   475, 475, 475, 475, 475, 475, 475, 475, 475, 476, 475, 475, 477, 140, 478,  26,
-+   479, 479, 480, 479, 479, 479, 479, 481,  26,  26,  26,  26,  26,  26,  26,  26,
-+   482, 483, 484, 485, 484, 486, 487, 487, 487, 487, 487, 487, 487, 488, 487, 489,
-+   490, 491, 492, 493, 493, 494, 495, 496, 491, 497, 498, 499, 500, 501, 501,  26,
-+   502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 503,  26,  26,  26,  26,
-+   504, 504, 504, 504, 504, 504, 504, 504, 504,  26, 504, 505,  26,  26,  26,  26,
-+   506, 506, 506, 506, 506, 506, 507, 506, 506, 506, 506, 507,  26,  26,  26,  26,
-+   508, 508, 508, 508, 508, 508, 508, 508, 509,  26, 508, 510, 201, 511,  26,  26,
-+   512, 512, 512, 512, 512, 512, 512, 513, 512, 514,  26,  26,  26,  26,  26,  26,
-+   515, 515, 515, 516, 515, 517, 515, 515,  26,  26,  26,  26,  26,  26,  26,  26,
-+    21,  21,  21,  21,  21,  21,  21, 518,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 520, 521,
-+    26,  26,  26,  26,  60, 522,  60,  60,  60,  60,  60, 522, 523,  26,  26,  26,
-+    18,  18,  18,  18,  18,  18,  18,  18,  18,  26,  54,  54,  54,  54,  54,  54,
-+    54,  54,  54,  54, 524,  26,  26,  26, 525, 525, 525, 525, 525, 525, 525, 526,
-+   527, 528, 527, 527, 527, 527, 529, 527, 530,  26, 527, 527, 527, 531, 532, 532,
-+   532, 532, 533, 532, 532, 534, 535,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   536, 537, 167, 167, 167, 167, 536, 538, 167,  26, 167, 539, 540, 541,  14,  14,
-+    14, 257,  15, 375,  14, 542,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  84,  84,  84,  89,
-+    26,  26,  26,  26,  26,  26,  26,  26, 109, 109, 109, 109, 109, 109, 543, 544,
-+   545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545,
-+   545, 545, 545, 546,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 547, 548,  26,
-+   545, 545, 545, 545, 545, 545, 545, 545, 549,  26,  26,  26,  26,  26,  26,  26,
-+   550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550,
-+   550, 550, 550, 550, 550, 551, 550, 552,  26,  26,  26,  26,  26,  26,  26,  26,
-+   553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
-+   553, 553, 553, 553, 553, 553, 553, 553, 554,  26,  26,  26,  26,  26,  26,  26,
-+   309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
-+   309, 309, 309, 309, 309, 309, 309, 555, 556, 556, 556, 557, 556, 558,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 559, 559, 559, 560, 560,  26,
-+   561, 561, 561, 561, 561, 561, 561, 561, 562,  26, 561, 563, 563, 561, 561, 564,
-+   561, 561,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  72,  72,  72,  72,  72,  72,  72,  72,
-+    72,  72,  72, 565,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   566, 566, 566, 566, 566, 566, 566, 566, 566, 567, 566, 566, 566, 566, 566, 566,
-+   566, 568, 566, 566,  26,  26,  26,  26,  26,  26,  26,  26, 569,  26,  26,  26,
-+   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570,
-+   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570,  26,
-+   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 571,  26,
-+   572, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
-+   290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
-+   290, 290, 290, 291,  26,  26,  26,  26,  26,  26, 573,  26, 574,  26, 171, 171,
-+   171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 346,
-+   575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 576, 575, 577,
-+   575, 578, 575, 579, 284,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 272,  26,
-+     0,   0,   0,   0, 262, 361,   0,   0,   0,   0,   0,   0, 580, 581,   0, 582,
-+   583, 584,   0,   0,   0, 585,   0,   0,   0,   0,   0,   0,   0, 586,  26,  26,
-+    14,  14,  14,  14,  14,  14,  14,  14, 251,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,   0,   0, 284,  26,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 262,  26,   0,   0,   0, 586,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 259,   0,   0,   0,   0,   0,
-+     0,   0,   0, 259, 587, 588,   0, 589, 590,   0,   0,   0,   0,   0,   0,   0,
-+   591, 592, 259, 259,   0,   0,   0, 593, 594, 595, 596,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0, 272,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0, 271,   0,   0,   0,   0,   0,   0,
-+   597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597,
-+   597, 598,  26, 599, 600, 597,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   274, 273, 273, 601, 602, 603,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   280, 280, 280, 280, 280, 604, 280, 283, 280, 605,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  25,  25,  25,  25,  25,  25,  25, 606,
-+   607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607,
-+   607, 607, 607, 607, 607, 607, 607, 607, 608, 607, 609,  26,  26,  26,  26,  26,
-+   610, 610, 610, 610, 610, 610, 610, 610, 610, 611, 610, 612,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 361,   0,
-+     0,   0,   0,   0,   0,   0, 613,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   361,   0,   0,   0,   0,   0,   0, 272,  26,  26,  26,  26,  26,  26,  26,  26,
-+   614,  31,  31,  31, 615, 616, 617, 618, 619, 620, 615, 621, 615, 617, 617, 622,
-+    31, 623,  31, 624, 625, 623,  31, 624,  26,  26,  26,  26,  26,  26, 355,  26,
-+     0,   0,   0,   0,   0, 284,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0, 284,  26,   0, 262, 361,   0, 361,   0, 361,   0,   0,   0, 272,  26,
-+     0, 613,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 613,   0,   0,
-+     0,   0,   0,   0,   0, 613,  26,  26,  26,  26,  26,  26, 626,   0,   0,   0,
-+   627,  26,   0,   0,   0,   0,   0, 284,   0, 586, 316,  26, 272,  26,  26,  26,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 272,  26,   0, 613,   0, 269,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 284,  26,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 586,   0, 284,  26,  26,
-+     0, 284,   0,   0,   0,   0,   0,   0,   0,  26,   0, 316,   0,   0,   0,   0,
-+     0,  26,   0,   0,   0, 272,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+     0, 590,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 593, 595,
-+     0,   0,   0,   0, 592, 628,   0,   0,   0, 592,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 284,  26,   0, 272, 284, 269,
-+   269,  26, 272,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 629,  26,  26,  26,  26,  26,
-+   280, 280, 280, 280, 280, 280, 604,  26, 280, 280, 280, 280, 280, 280, 280, 280,
-+   280, 280, 280, 283, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
-+   280, 280, 280, 280, 348,  26, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 630,  26,  26,  26,
-+   280, 280, 280, 283,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   631,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,
-+     9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
-+     0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
-+  1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
-+     0,1219,1226,1227,1228,1229,1233,   0,   0,1267,1268,1269,1273,1298,   0,1303,
-+   943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
-+     0,   0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
-+   991,1176, 993,1178, 994,1179,   0,   0,1004,1190,1005,1191,1006,1192,1014,1199,
-+  1007,   0,   0,   0,1016,1201,1020,1206,   0,1022,1208,1025,1211,1023,1209,   0,
-+     0,   0,   0,1032,1218,1037,1223,1035,1221,   0,   0,   0,1044,1230,1045,1231,
-+  1049,1235,   0,   0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
-+  1069,1255,1077,1264,1074,1261,   0,   0,1083,1270,1084,1271,1085,1272,1088,1275,
-+  1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310,   0,
-+  1053,1239,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1093,
-+  1280,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 949,1134,1010,
-+  1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366,   0,1320,1347,
-+  1418,1419,1323,1350,   0,   0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
-+  1202,   0,   0,   0, 987,1172,   0,   0,1031,1217,1321,1348,1322,1349,1338,1365,
-+   950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
-+  1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263,   0,   0, 997,1182,
-+     0,   0,   0,   0,   0,   0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
-+  1422,1423,1113,1301,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     8,   9,   0,  10,1425,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,
-+     0,   0,   0,   0,   0,1314,1427,   5,1434,1438,1443,   0,1450,   0,1455,1461,
-+  1514,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1446,1458,1468,1476,1480,1486,
-+  1517,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1489,1503,1494,1500,1508,   0,
-+     0,   0,   0,1520,1521,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1526,1528,   0,1525,   0,   0,   0,1522,   0,   0,   0,   0,1536,1532,1539,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1534,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1556,   0,   0,   0,   0,   0,   0,
-+  1548,1550,   0,1547,   0,   0,   0,1567,   0,   0,   0,   0,1558,1554,1561,   0,
-+     0,   0,   0,   0,   0,   0,1568,1569,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,1529,1551,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1523,1545,1524,1546,   0,   0,1527,1549,   0,   0,1570,1571,1530,1552,1531,1553,
-+     0,   0,1533,1555,1535,1557,1537,1559,   0,   0,1572,1573,1544,1566,1538,1560,
-+  1540,1562,1541,1563,1542,1564,   0,   0,1543,1565,   0,   0,   0,   0,   0,   0,
-+     0,   0,1606,1607,1609,1608,1610,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1613,   0,1611,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1612,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1620,   0,   0,   0,   0,   0,   0,
-+     0,1623,   0,   0,1624,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1614,1615,1616,1617,1618,1619,1621,1622,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1628,1629,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1625,1626,   0,1627,
-+     0,   0,   0,1634,   0,   0,1635,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1630,1631,1632,   0,   0,1633,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1639,   0,   0,1638,1640,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1636,1637,   0,   0,
-+     0,   0,   0,   0,1641,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1642,1644,1643,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1645,   0,   0,   0,   0,   0,   0,   0,
-+  1646,   0,   0,   0,   0,   0,   0,1648,1649,   0,1647,1650,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1651,1653,1652,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1654,   0,1655,1657,1656,   0,
-+     0,   0,   0,1659,   0,   0,   0,   0,   0,   0,   0,   0,   0,1660,   0,   0,
-+     0,   0,1661,   0,   0,   0,   0,1662,   0,   0,   0,   0,1663,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1658,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1664,   0,1665,1673,   0,1674,   0,   0,   0,   0,   0,   0,   0,
-+     0,1666,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1668,   0,   0,   0,   0,   0,   0,   0,   0,   0,1669,   0,   0,
-+     0,   0,1670,   0,   0,   0,   0,1671,   0,   0,   0,   0,1672,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1667,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,1675,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,1676,   0,1677,   0,1678,   0,1679,   0,1680,   0,
-+     0,   0,1681,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1682,   0,1683,   0,   0,
-+  1684,1685,   0,1686,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
-+   966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
-+   989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
-+  1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
-+  1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
-+  1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
-+  1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
-+  1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
-+  1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
-+  1119,1308,1122,1311,1123,1312,1186,1260,1293,1305,   0,1394,   0,   0,   0,   0,
-+   952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
-+  1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
-+  1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
-+  1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
-+  1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
-+  1409,1414,1109,1297,1117,1306,1116,1304,1112,1300,   0,   0,   0,   0,   0,   0,
-+  1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
-+  1477,1478,1729,1731,1730,1732,   0,   0,1435,1436,1733,1735,1734,1736,   0,   0,
-+  1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
-+  1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
-+  1495,1496,1777,1779,1778,1780,   0,   0,1451,1452,1781,1783,1782,1784,   0,   0,
-+  1504,1505,1785,1788,1786,1789,1787,1790,   0,1459,   0,1791,   0,1792,   0,1793,
-+  1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
-+  1467,  21,1475,  22,1479,  23,1485,  24,1493,  27,1499,  28,1507,  29,   0,   0,
-+  1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
-+  1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
-+  1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
-+  1470,1469,1822,1474,1465,   0,1473,1825,1429,1428,1426,  12,1432,   0,  26,   0,
-+     0,1315,1823,1484,1466,   0,1483,1829,1433,  13,1437,  14,1441,1826,1827,1828,
-+  1488,1487,1513,  19,   0,   0,1492,1515,1445,1444,1442,  15,   0,1831,1832,1833,
-+  1502,1501,1516,  25,1497,1498,1506,1518,1457,1456,1454,  17,1453,1313,  11,   3,
-+     0,   0,1824,1512,1519,   0,1511,1830,1449,  16,1460,  18,1464,   4,   0,   0,
-+    30,  31,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,  20,   0,   0,   0,   2,   6,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1834,1835,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1836,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1837,1839,1838,
-+     0,   0,   0,   0,1840,   0,   0,   0,   0,1841,   0,   0,1842,   0,   0,   0,
-+     0,   0,   0,   0,1843,   0,1844,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,1845,   0,   0,1846,   0,   0,1847,   0,1848,   0,   0,   0,   0,   0,   0,
-+   937,   0,1850,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1849, 936, 938,
-+  1851,1852,   0,   0,1853,1854,   0,   0,1855,1856,   0,   0,   0,   0,   0,   0,
-+  1857,1858,   0,   0,1861,1862,   0,   0,1863,1864,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1867,1868,1869,1870,
-+  1859,1860,1865,1866,   0,   0,   0,   0,   0,   0,1871,1872,1873,1874,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,  32,  33,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1875,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1877,   0,1878,   0,
-+  1879,   0,1880,   0,1881,   0,1882,   0,1883,   0,1884,   0,1885,   0,1886,   0,
-+  1887,   0,1888,   0,   0,1889,   0,1890,   0,1891,   0,   0,   0,   0,   0,   0,
-+  1892,1893,   0,1894,1895,   0,1896,1897,   0,1898,1899,   0,1900,1901,   0,   0,
-+     0,   0,   0,   0,1876,   0,   0,   0,   0,   0,   0,   0,   0,   0,1902,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1904,   0,1905,   0,
-+  1906,   0,1907,   0,1908,   0,1909,   0,1910,   0,1911,   0,1912,   0,1913,   0,
-+  1914,   0,1915,   0,   0,1916,   0,1917,   0,1918,   0,   0,   0,   0,   0,   0,
-+  1919,1920,   0,1921,1922,   0,1923,1924,   0,1925,1926,   0,1927,1928,   0,   0,
-+     0,   0,   0,   0,1903,   0,   0,1929,1930,1931,1932,   0,   0,   0,1933,   0,
-+   710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
-+   663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
-+   810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
-+   368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
-+   811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
-+   594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
-+   313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
-+   424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
-+   193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
-+   337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
-+   683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
-+   608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
-+   479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
-+   791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
-+   377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
-+   659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
-+   153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210,   0,   0,
-+   227,   0, 379,   0,   0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604,   0,
-+   661,   0, 703,   0,   0, 735, 743,   0,   0,   0, 793, 794, 795, 808, 741, 773,
-+   118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
-+   335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
-+   549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
-+   690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623,   0,   0,
-+   102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
-+   250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
-+   370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
-+   493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
-+   591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
-+   709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
-+   847, 857,  55,  65,  66, 883, 892, 916, 822, 824,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1586,   0,1605,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,
-+  1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,
-+  1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1948,1949,
-+  1950,1951,1952,1953,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,1957,1959,1958,
-+  1960,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131,
-+   132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37,
-+   157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
-+   181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
-+   197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
-+   153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
-+   836, 837, 247, 248, 249, 246, 251,  39,  40, 253, 255, 255, 838, 257, 258, 259,
-+   261, 839, 262, 263, 301, 264,  41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
-+   278, 281, 282,  42, 283, 284, 285, 286,  43, 843,  44, 289, 290, 291, 293, 934,
-+   298, 845, 845, 621, 300, 300,  45, 852, 894, 302, 304,  46, 306, 309, 310, 312,
-+   316,  48,  47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
-+   335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
-+   358, 356,  49, 363, 365, 367, 364,  50, 369, 371, 851, 376, 386, 378,  53, 381,
-+    52,  51, 140, 141, 387, 382, 614,  78, 388, 389, 390, 394, 392, 856,  54, 399,
-+   396, 402, 404, 858, 405, 401, 407,  55, 408, 409, 410, 413, 859, 415,  56, 417,
-+   860, 418,  57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
-+   437, 441, 438, 439, 442, 443, 864, 436, 449, 450,  58, 454, 453, 865, 447, 460,
-+   866, 867, 461, 466, 465, 464,  59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
-+   483, 485, 486, 871, 488, 489, 872, 873, 495, 497,  60, 498,  61,  61, 504, 505,
-+   507, 508, 511,  62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878,  63,  64,
-+   528, 880, 879, 881, 882, 530, 531, 531, 533,  66, 534,  67,  68, 884, 536, 538,
-+   541,  69, 885, 549, 886, 887, 556, 559,  70, 561, 562, 563, 888, 889, 889, 567,
-+    71, 890, 570, 571,  72, 891, 577,  73, 581, 579, 582, 893, 587,  74, 590, 592,
-+   596,  75, 895, 896,  76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
-+   853,  77, 615, 616,  79, 617, 252, 902, 903, 854, 855, 621, 622, 731,  80, 627,
-+   626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
-+   638, 643, 644, 645, 905, 907, 906,  81, 653, 654, 656, 911, 657, 908,  82,  83,
-+   909, 910,  84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675,  85,
-+   677, 678,  86, 681, 682, 912, 685, 686,  87, 689,  36, 913, 914,  88,  89, 696,
-+   702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
-+   918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762,  90,
-+   764, 922,  91, 775, 279, 780, 923, 925,  92,  93, 785, 926,  94, 927, 787, 787,
-+   789, 928, 792,  95, 796, 797, 798, 800,  96, 929, 802, 804, 806,  97,  98, 807,
-+   930,  99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935,   0,   0,
-+};
-+static const int16_t
-+_hb_ucd_i16[196] =
-+{
-+      0,    0,    0,    0,    1,   -1,    0,    0,    2,    0,   -2,    0,    0,    0,    0,    2,
-+      0,   -2,    0,    0,    0,    0,    0,   16,    0,    0,    0,  -16,    0,    0,    1,   -1,
-+      0,    0,    0,    1,   -1,    0,    0,    0,    0,    1,   -1,    0,    3,    3,    3,   -3,
-+     -3,   -3,    0,    0,    0, 2016,    0,    0,    0,    0,    0, 2527, 1923, 1914, 1918,    0,
-+   2250,    0,    0,    0,    0,    0,    0,  138,    0,    7,    0,    0,   -7,    0,    0,    0,
-+      1,   -1,    1,   -1,   -1,    1,   -1,    0, 1824,    0,    0,    0,    0,    0, 2104,    0,
-+   2108, 2106,    0, 2106, 1316,    0,    0,    0,    0,    1,   -1,    1,   -1, -138,    0,    0,
-+      1,   -1,    8,    8,    8,    0,    7,    7,    0,    0,   -8,   -8,   -8,   -7,   -7,    0,
-+      1,   -1,    0,    2,-1316,    1,   -1,    0,   -1,    1,   -1,    1,   -1,    3,    1,   -1,
-+     -3,    1,   -1,    1,   -1,    0,    0,-1914,-1918,    0,    0,-1923,-1824,    0,    0,    0,
-+      0,-2016,    0,    0,    1,   -1,    0,    1,    0,    0,-2104,    0,    0,    0,    0,-2106,
-+  -2108,-2106,    0,    0,    1,   -1,-2250,    0,    0,    0,-2527,    0,    0,   -2,    0,    1,
-+     -1,    0,    1,   -1,
-+};
-+
-+static inline uint_fast8_t
-+_hb_ucd_gc (unsigned u)
-+{
-+  return u<1114110u?_hb_ucd_u8[6432+(((_hb_ucd_u8[1248+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
-+}
-+static inline uint_fast8_t
-+_hb_ucd_ccc (unsigned u)
-+{
-+  return u<125259u?_hb_ucd_u8[8640+(((_hb_ucd_u8[7704+(((_hb_ucd_u8[7048+(((_hb_ucd_u8[6802+(u>>2>>3>>4)])<<4)+((u>>2>>3)&15u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u))]:0;
-+}
-+static inline unsigned
-+_hb_ucd_b4 (const uint8_t* a, unsigned i)
-+{
-+  return (a[i>>1]>>((i&1u)<<2))&15u;
-+}
-+static inline int_fast16_t
-+_hb_ucd_bmg (unsigned u)
-+{
-+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9372+(((_hb_ucd_u8[9252+(((_hb_ucd_b4(9124+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
-+}
-+static inline uint_fast8_t
-+_hb_ucd_sc (unsigned u)
-+{
-+  return u<918000u?_hb_ucd_u8[10822+(((_hb_ucd_u16[1920+(((_hb_ucd_u8[10150+(((_hb_ucd_u8[9700+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
-+}
-+static inline uint_fast16_t
-+_hb_ucd_dm (unsigned u)
-+{
-+  return u<195102u?_hb_ucd_u16[5632+(((_hb_ucd_u8[15974+(((_hb_ucd_b4(15878+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0;
-+}
-+
-+#endif
-+
-+
-+#endif /* HB_UCD_TABLE_HH */
-+
-+/* == End of generated table == */
-diff --git a/gfx/harfbuzz/src/hb-ucd.cc b/gfx/harfbuzz/src/hb-ucd.cc
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-ucd.cc
-@@ -0,0 +1,212 @@
-+/*
-+ * Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net>
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#include "hb.hh"
-+#include "hb-machinery.hh"
-+
-+#include "hb-ucd-table.hh"
-+
-+static hb_unicode_combining_class_t
-+hb_ucd_combining_class (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-+			hb_codepoint_t unicode,
-+			void *user_data HB_UNUSED)
-+{
-+  return (hb_unicode_combining_class_t) _hb_ucd_ccc (unicode);
-+}
-+
-+static hb_unicode_general_category_t
-+hb_ucd_general_category (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-+			 hb_codepoint_t unicode,
-+			 void *user_data HB_UNUSED)
-+{
-+  return (hb_unicode_general_category_t) _hb_ucd_gc (unicode);
-+}
-+
-+static hb_codepoint_t
-+hb_ucd_mirroring (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-+		  hb_codepoint_t unicode,
-+		  void *user_data HB_UNUSED)
-+{
-+  return unicode + _hb_ucd_bmg (unicode);
-+}
-+
-+static hb_script_t
-+hb_ucd_script (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-+	       hb_codepoint_t unicode,
-+	       void *user_data HB_UNUSED)
-+{
-+  return _hb_ucd_sc_map[_hb_ucd_sc (unicode)];
-+}
-+
-+
-+#define SBASE 0xAC00u
-+#define LBASE 0x1100u
-+#define VBASE 0x1161u
-+#define TBASE 0x11A7u
-+#define SCOUNT 11172u
-+#define LCOUNT 19u
-+#define VCOUNT 21u
-+#define TCOUNT 28u
-+#define NCOUNT (VCOUNT * TCOUNT)
-+
-+static inline bool
-+_hb_ucd_decompose_hangul (hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b)
-+{
-+  unsigned si = ab - SBASE;
-+
-+  if (si >= SCOUNT)
-+    return false;
-+
-+  if (si % TCOUNT)
-+  {
-+    /* LV,T */
-+    *a = SBASE + (si / TCOUNT) * TCOUNT;
-+    *b = TBASE + (si % TCOUNT);
-+    return true;
-+  } else {
-+    /* L,V */
-+    *a = LBASE + (si / NCOUNT);
-+    *b = VBASE + (si % NCOUNT) / TCOUNT;
-+    return true;
-+  }
-+}
-+
-+static inline bool
-+_hb_ucd_compose_hangul (hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab)
-+{
-+  if (a >= SBASE && a < (SBASE + SCOUNT) && b > TBASE && b < (TBASE + TCOUNT) &&
-+    !((a - SBASE) % TCOUNT))
-+  {
-+    /* LV,T */
-+    *ab = a + (b - TBASE);
-+    return true;
-+  }
-+  else if (a >= LBASE && a < (LBASE + LCOUNT) && b >= VBASE && b < (VBASE + VCOUNT))
-+  {
-+    /* L,V */
-+    int li = a - LBASE;
-+    int vi = b - VBASE;
-+    *ab = SBASE + li * NCOUNT + vi * TCOUNT;
-+    return true;
-+  }
-+  else
-+    return false;
-+}
-+
-+static int
-+_cmp_pair (const void *_key, const void *_item)
-+{
-+  uint64_t& a = * (uint64_t*) _key;
-+  uint64_t b = (* (uint64_t*) _item) & HB_CODEPOINT_ENCODE3(0x1FFFFFu, 0x1FFFFFu, 0);
-+
-+  return a < b ? -1 : a > b ? +1 : 0;
-+}
-+
-+static hb_bool_t
-+hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-+		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
-+		void *user_data HB_UNUSED)
-+{
-+  if (_hb_ucd_compose_hangul (a, b, ab)) return true;
-+
-+  uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
-+  uint64_t *v = (uint64_t*) hb_bsearch (&k, _hb_ucd_dm2_map,
-+					ARRAY_LENGTH (_hb_ucd_dm2_map),
-+					sizeof (*_hb_ucd_dm2_map),
-+					_cmp_pair);
-+  if (likely (!v)) return false;
-+
-+  hb_codepoint_t u = HB_CODEPOINT_DECODE3_3 (*v);
-+  if (unlikely (!u)) return false;
-+
-+  *ab = u;
-+  return true;
-+}
-+
-+static hb_bool_t
-+hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
-+		  hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b,
-+		  void *user_data HB_UNUSED)
-+{
-+  if (_hb_ucd_decompose_hangul (ab, a, b)) return true;
-+
-+  unsigned i = _hb_ucd_dm (ab);
-+
-+  if (likely (!i)) return false;
-+  i--;
-+
-+  if (i < ARRAY_LENGTH (_hb_ucd_dm1_map))
-+  {
-+    *a = _hb_ucd_dm1_map[i];
-+    *b = 0;
-+    return true;
-+  }
-+  i -= ARRAY_LENGTH (_hb_ucd_dm1_map);
-+
-+  uint64_t v = _hb_ucd_dm2_map[i];
-+  *a = HB_CODEPOINT_DECODE3_1 (v);
-+  *b = HB_CODEPOINT_DECODE3_2 (v);
-+  return true;
-+}
-+
-+
-+#if HB_USE_ATEXIT
-+static void free_static_ucd_funcs ();
-+#endif
-+
-+static struct hb_ucd_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucd_unicode_funcs_lazy_loader_t>
-+{
-+  static hb_unicode_funcs_t *create ()
-+  {
-+    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
-+
-+    hb_unicode_funcs_set_combining_class_func (funcs, hb_ucd_combining_class, nullptr, nullptr);
-+    hb_unicode_funcs_set_general_category_func (funcs, hb_ucd_general_category, nullptr, nullptr);
-+    hb_unicode_funcs_set_mirroring_func (funcs, hb_ucd_mirroring, nullptr, nullptr);
-+    hb_unicode_funcs_set_script_func (funcs, hb_ucd_script, nullptr, nullptr);
-+    hb_unicode_funcs_set_compose_func (funcs, hb_ucd_compose, nullptr, nullptr);
-+    hb_unicode_funcs_set_decompose_func (funcs, hb_ucd_decompose, nullptr, nullptr);
-+
-+    hb_unicode_funcs_make_immutable (funcs);
-+
-+#if HB_USE_ATEXIT
-+    atexit (free_static_ucd_funcs);
-+#endif
-+
-+    return funcs;
-+  }
-+} static_ucd_funcs;
-+
-+#if HB_USE_ATEXIT
-+static
-+void free_static_ucd_funcs ()
-+{
-+  static_ucd_funcs.free_instance ();
-+}
-+#endif
-+
-+extern "C" HB_INTERNAL
-+hb_unicode_funcs_t *
-+hb_ucd_get_unicode_funcs ();
-+
-+hb_unicode_funcs_t *
-+hb_ucd_get_unicode_funcs ()
-+{
-+#ifdef HB_NO_UCD
-+  return hb_unicode_funcs_get_empty ();
-+#endif
-+  return static_ucd_funcs.get_unconst ();
-+}
-diff --git a/gfx/harfbuzz/src/hb-ucdn.cc b/gfx/harfbuzz/src/hb-ucdn.cc
-deleted file mode 100644
---- a/gfx/harfbuzz/src/hb-ucdn.cc
-+++ /dev/null
-@@ -1,272 +0,0 @@
--/*
-- * Copyright (C) 2012 Grigori Goronzy <greg@kinoho.net>
-- *
-- * Permission to use, copy, modify, and/or distribute this software for any
-- * purpose with or without fee is hereby granted, provided that the above
-- * copyright notice and this permission notice appear in all copies.
-- *
-- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-- */
--
--#include "hb.hh"
--
--#include "hb-machinery.hh"
--
--#include "ucdn.h"
--
--static const hb_script_t ucdn_script_translate[] =
--{
--    HB_SCRIPT_COMMON,
--    HB_SCRIPT_LATIN,
--    HB_SCRIPT_GREEK,
--    HB_SCRIPT_CYRILLIC,
--    HB_SCRIPT_ARMENIAN,
--    HB_SCRIPT_HEBREW,
--    HB_SCRIPT_ARABIC,
--    HB_SCRIPT_SYRIAC,
--    HB_SCRIPT_THAANA,
--    HB_SCRIPT_DEVANAGARI,
--    HB_SCRIPT_BENGALI,
--    HB_SCRIPT_GURMUKHI,
--    HB_SCRIPT_GUJARATI,
--    HB_SCRIPT_ORIYA,
--    HB_SCRIPT_TAMIL,
--    HB_SCRIPT_TELUGU,
--    HB_SCRIPT_KANNADA,
--    HB_SCRIPT_MALAYALAM,
--    HB_SCRIPT_SINHALA,
--    HB_SCRIPT_THAI,
--    HB_SCRIPT_LAO,
--    HB_SCRIPT_TIBETAN,
--    HB_SCRIPT_MYANMAR,
--    HB_SCRIPT_GEORGIAN,
--    HB_SCRIPT_HANGUL,
--    HB_SCRIPT_ETHIOPIC,
--    HB_SCRIPT_CHEROKEE,
--    HB_SCRIPT_CANADIAN_SYLLABICS,
--    HB_SCRIPT_OGHAM,
--    HB_SCRIPT_RUNIC,
--    HB_SCRIPT_KHMER,
--    HB_SCRIPT_MONGOLIAN,
--    HB_SCRIPT_HIRAGANA,
--    HB_SCRIPT_KATAKANA,
--    HB_SCRIPT_BOPOMOFO,
--    HB_SCRIPT_HAN,
--    HB_SCRIPT_YI,
--    HB_SCRIPT_OLD_ITALIC,
--    HB_SCRIPT_GOTHIC,
--    HB_SCRIPT_DESERET,
--    HB_SCRIPT_INHERITED,
--    HB_SCRIPT_TAGALOG,
--    HB_SCRIPT_HANUNOO,
--    HB_SCRIPT_BUHID,
--    HB_SCRIPT_TAGBANWA,
--    HB_SCRIPT_LIMBU,
--    HB_SCRIPT_TAI_LE,
--    HB_SCRIPT_LINEAR_B,
--    HB_SCRIPT_UGARITIC,
--    HB_SCRIPT_SHAVIAN,
--    HB_SCRIPT_OSMANYA,
--    HB_SCRIPT_CYPRIOT,
--    HB_SCRIPT_BRAILLE,
--    HB_SCRIPT_BUGINESE,
--    HB_SCRIPT_COPTIC,
--    HB_SCRIPT_NEW_TAI_LUE,
--    HB_SCRIPT_GLAGOLITIC,
--    HB_SCRIPT_TIFINAGH,
--    HB_SCRIPT_SYLOTI_NAGRI,
--    HB_SCRIPT_OLD_PERSIAN,
--    HB_SCRIPT_KHAROSHTHI,
--    HB_SCRIPT_BALINESE,
--    HB_SCRIPT_CUNEIFORM,
--    HB_SCRIPT_PHOENICIAN,
--    HB_SCRIPT_PHAGS_PA,
--    HB_SCRIPT_NKO,
--    HB_SCRIPT_SUNDANESE,
--    HB_SCRIPT_LEPCHA,
--    HB_SCRIPT_OL_CHIKI,
--    HB_SCRIPT_VAI,
--    HB_SCRIPT_SAURASHTRA,
--    HB_SCRIPT_KAYAH_LI,
--    HB_SCRIPT_REJANG,
--    HB_SCRIPT_LYCIAN,
--    HB_SCRIPT_CARIAN,
--    HB_SCRIPT_LYDIAN,
--    HB_SCRIPT_CHAM,
--    HB_SCRIPT_TAI_THAM,
--    HB_SCRIPT_TAI_VIET,
--    HB_SCRIPT_AVESTAN,
--    HB_SCRIPT_EGYPTIAN_HIEROGLYPHS,
--    HB_SCRIPT_SAMARITAN,
--    HB_SCRIPT_LISU,
--    HB_SCRIPT_BAMUM,
--    HB_SCRIPT_JAVANESE,
--    HB_SCRIPT_MEETEI_MAYEK,
--    HB_SCRIPT_IMPERIAL_ARAMAIC,
--    HB_SCRIPT_OLD_SOUTH_ARABIAN,
--    HB_SCRIPT_INSCRIPTIONAL_PARTHIAN,
--    HB_SCRIPT_INSCRIPTIONAL_PAHLAVI,
--    HB_SCRIPT_OLD_TURKIC,
--    HB_SCRIPT_KAITHI,
--    HB_SCRIPT_BATAK,
--    HB_SCRIPT_BRAHMI,
--    HB_SCRIPT_MANDAIC,
--    HB_SCRIPT_CHAKMA,
--    HB_SCRIPT_MEROITIC_CURSIVE,
--    HB_SCRIPT_MEROITIC_HIEROGLYPHS,
--    HB_SCRIPT_MIAO,
--    HB_SCRIPT_SHARADA,
--    HB_SCRIPT_SORA_SOMPENG,
--    HB_SCRIPT_TAKRI,
--    HB_SCRIPT_UNKNOWN,
--    HB_SCRIPT_BASSA_VAH,
--    HB_SCRIPT_CAUCASIAN_ALBANIAN,
--    HB_SCRIPT_DUPLOYAN,
--    HB_SCRIPT_ELBASAN,
--    HB_SCRIPT_GRANTHA,
--    HB_SCRIPT_KHOJKI,
--    HB_SCRIPT_KHUDAWADI,
--    HB_SCRIPT_LINEAR_A,
--    HB_SCRIPT_MAHAJANI,
--    HB_SCRIPT_MANICHAEAN,
--    HB_SCRIPT_MENDE_KIKAKUI,
--    HB_SCRIPT_MODI,
--    HB_SCRIPT_MRO,
--    HB_SCRIPT_NABATAEAN,
--    HB_SCRIPT_OLD_NORTH_ARABIAN,
--    HB_SCRIPT_OLD_PERMIC,
--    HB_SCRIPT_PAHAWH_HMONG,
--    HB_SCRIPT_PALMYRENE,
--    HB_SCRIPT_PAU_CIN_HAU,
--    HB_SCRIPT_PSALTER_PAHLAVI,
--    HB_SCRIPT_SIDDHAM,
--    HB_SCRIPT_TIRHUTA,
--    HB_SCRIPT_WARANG_CITI,
--    HB_SCRIPT_AHOM,
--    HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
--    HB_SCRIPT_HATRAN,
--    HB_SCRIPT_MULTANI,
--    HB_SCRIPT_OLD_HUNGARIAN,
--    HB_SCRIPT_SIGNWRITING,
--    HB_SCRIPT_ADLAM,
--    HB_SCRIPT_BHAIKSUKI,
--    HB_SCRIPT_MARCHEN,
--    HB_SCRIPT_NEWA,
--    HB_SCRIPT_OSAGE,
--    HB_SCRIPT_TANGUT,
--    HB_SCRIPT_MASARAM_GONDI,
--    HB_SCRIPT_NUSHU,
--    HB_SCRIPT_SOYOMBO,
--    HB_SCRIPT_ZANABAZAR_SQUARE,
--    HB_SCRIPT_DOGRA,
--    HB_SCRIPT_GUNJALA_GONDI,
--    HB_SCRIPT_HANIFI_ROHINGYA,
--    HB_SCRIPT_MAKASAR,
--    HB_SCRIPT_MEDEFAIDRIN,
--    HB_SCRIPT_OLD_SOGDIAN,
--    HB_SCRIPT_SOGDIAN,
--    HB_SCRIPT_ELYMAIC,
--    HB_SCRIPT_NANDINAGARI,
--    HB_SCRIPT_NYIAKENG_PUACHUE_HMONG,
--    HB_SCRIPT_WANCHO,
--};
--
--static hb_unicode_combining_class_t
--hb_ucdn_combining_class(hb_unicode_funcs_t *ufuncs HB_UNUSED,
--			hb_codepoint_t unicode,
--			void *user_data HB_UNUSED)
--{
--    return (hb_unicode_combining_class_t) ucdn_get_combining_class(unicode);
--}
--
--static hb_unicode_general_category_t
--hb_ucdn_general_category(hb_unicode_funcs_t *ufuncs HB_UNUSED,
--			 hb_codepoint_t unicode,
--			 void *user_data HB_UNUSED)
--{
--    return (hb_unicode_general_category_t)ucdn_get_general_category(unicode);
--}
--
--static hb_codepoint_t
--hb_ucdn_mirroring(hb_unicode_funcs_t *ufuncs HB_UNUSED,
--		  hb_codepoint_t unicode,
--		  void *user_data HB_UNUSED)
--{
--    return ucdn_mirror(unicode);
--}
--
--static hb_script_t
--hb_ucdn_script(hb_unicode_funcs_t *ufuncs HB_UNUSED,
--	       hb_codepoint_t unicode,
--	       void *user_data HB_UNUSED)
--{
--    return ucdn_script_translate[ucdn_get_script(unicode)];
--}
--
--static hb_bool_t
--hb_ucdn_compose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
--		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
--		void *user_data HB_UNUSED)
--{
--    return ucdn_compose(ab, a, b);
--}
--
--static hb_bool_t
--hb_ucdn_decompose(hb_unicode_funcs_t *ufuncs HB_UNUSED,
--		  hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b,
--		  void *user_data HB_UNUSED)
--{
--    return ucdn_decompose(ab, a, b);
--}
--
--
--#if HB_USE_ATEXIT
--static void free_static_ucdn_funcs ();
--#endif
--
--static struct hb_ucdn_unicode_funcs_lazy_loader_t : hb_unicode_funcs_lazy_loader_t<hb_ucdn_unicode_funcs_lazy_loader_t>
--{
--  static hb_unicode_funcs_t *create ()
--  {
--    hb_unicode_funcs_t *funcs = hb_unicode_funcs_create (nullptr);
--
--    hb_unicode_funcs_set_combining_class_func (funcs, hb_ucdn_combining_class, nullptr, nullptr);
--    hb_unicode_funcs_set_general_category_func (funcs, hb_ucdn_general_category, nullptr, nullptr);
--    hb_unicode_funcs_set_mirroring_func (funcs, hb_ucdn_mirroring, nullptr, nullptr);
--    hb_unicode_funcs_set_script_func (funcs, hb_ucdn_script, nullptr, nullptr);
--    hb_unicode_funcs_set_compose_func (funcs, hb_ucdn_compose, nullptr, nullptr);
--    hb_unicode_funcs_set_decompose_func (funcs, hb_ucdn_decompose, nullptr, nullptr);
--
--    hb_unicode_funcs_make_immutable (funcs);
--
--#if HB_USE_ATEXIT
--    atexit (free_static_ucdn_funcs);
--#endif
--
--    return funcs;
--  }
--} static_ucdn_funcs;
--
--#if HB_USE_ATEXIT
--static
--void free_static_ucdn_funcs ()
--{
--  static_ucdn_funcs.free_instance ();
--}
--#endif
--
--extern "C" HB_INTERNAL
--hb_unicode_funcs_t *
--hb_ucdn_get_unicode_funcs ();
--
--hb_unicode_funcs_t *
--hb_ucdn_get_unicode_funcs ()
--{
--  return static_ucdn_funcs.get_unconst ();
--}
-diff --git a/gfx/harfbuzz/src/hb-unicode.cc b/gfx/harfbuzz/src/hb-unicode.cc
---- a/gfx/harfbuzz/src/hb-unicode.cc
-+++ b/gfx/harfbuzz/src/hb-unicode.cc
-@@ -55,23 +55,25 @@
- static hb_unicode_combining_class_t
- hb_unicode_combining_class_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
- 				hb_codepoint_t      unicode   HB_UNUSED,
- 				void               *user_data HB_UNUSED)
- {
-   return HB_UNICODE_COMBINING_CLASS_NOT_REORDERED;
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- static unsigned int
- hb_unicode_eastasian_width_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
- 				hb_codepoint_t      unicode   HB_UNUSED,
- 				void               *user_data HB_UNUSED)
- {
-   return 1;
- }
-+#endif
- 
- static hb_unicode_general_category_t
- hb_unicode_general_category_nil (hb_unicode_funcs_t *ufuncs    HB_UNUSED,
- 				 hb_codepoint_t      unicode   HB_UNUSED,
- 				 void               *user_data HB_UNUSED)
- {
-   return HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER;
- }
-@@ -108,48 +110,50 @@ hb_unicode_decompose_nil (hb_unicode_fun
- 			  hb_codepoint_t     *a         HB_UNUSED,
- 			  hb_codepoint_t     *b         HB_UNUSED,
- 			  void               *user_data HB_UNUSED)
- {
-   return false;
- }
- 
- 
-+#ifndef HB_DISABLE_DEPRECATED
- static unsigned int
- hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs     HB_UNUSED,
- 					hb_codepoint_t      u          HB_UNUSED,
- 					hb_codepoint_t     *decomposed HB_UNUSED,
- 					void               *user_data  HB_UNUSED)
- {
-   return 0;
- }
-+#endif
- 
- 
-+extern "C" hb_unicode_funcs_t *hb_ucd_get_unicode_funcs ();
- extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs ();
- extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs ();
--extern "C" hb_unicode_funcs_t *hb_ucdn_get_unicode_funcs ();
- 
- hb_unicode_funcs_t *
- hb_unicode_funcs_get_default ()
- {
--#if defined(HAVE_UCDN)
--  return hb_ucdn_get_unicode_funcs ();
--#elif defined(HAVE_GLIB)
-+#if !defined(HB_NO_UNICODE_FUNCS) && !defined(HB_NO_UCD)
-+  return hb_ucd_get_unicode_funcs ();
-+#elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_GLIB)
-   return hb_glib_get_unicode_funcs ();
--#elif defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
-+#elif !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN)
-   return hb_icu_get_unicode_funcs ();
- #else
- #define HB_UNICODE_FUNCS_NIL 1
-   return hb_unicode_funcs_get_empty ();
- #endif
- }
- 
- #if !defined(HB_NO_UNICODE_FUNCS) && defined(HB_UNICODE_FUNCS_NIL)
- #error "Could not find any Unicode functions implementation, you have to provide your own"
--#error "Consider building hb-ucdn.c.  If you absolutely want to build without any, check the code."
-+#error "Consider building hb-ucd.cc.  If you absolutely want to build without any, check the code."
- #endif
- 
- /**
-  * hb_unicode_funcs_create: (Xconstructor)
-  * @parent: (nullable):
-  *
-  *
-  *
-@@ -420,16 +424,17 @@ hb_bool_t
- hb_unicode_decompose (hb_unicode_funcs_t *ufuncs,
- 		      hb_codepoint_t      ab,
- 		      hb_codepoint_t     *a,
- 		      hb_codepoint_t     *b)
- {
-   return ufuncs->decompose (ab, a, b);
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_unicode_decompose_compatibility:
-  * @ufuncs: Unicode functions.
-  * @u:
-  * @decomposed: (out):
-  *
-  *
-  *
-@@ -440,16 +445,17 @@ hb_unicode_decompose (hb_unicode_funcs_t
-  **/
- unsigned int
- hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
- 				    hb_codepoint_t      u,
- 				    hb_codepoint_t     *decomposed)
- {
-   return ufuncs->decompose_compatibility (u, decomposed);
- }
-+#endif
- 
- 
- /* See hb-unicode.hh for details. */
- const uint8_t
- _hb_modified_combining_class[256] =
- {
-   0, /* HB_UNICODE_COMBINING_CLASS_NOT_REORDERED */
-   1, /* HB_UNICODE_COMBINING_CLASS_OVERLAY */
-diff --git a/gfx/harfbuzz/src/hb-unicode.hh b/gfx/harfbuzz/src/hb-unicode.hh
---- a/gfx/harfbuzz/src/hb-unicode.hh
-+++ b/gfx/harfbuzz/src/hb-unicode.hh
-@@ -37,29 +37,29 @@
- extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
- 
- /*
-  * hb_unicode_funcs_t
-  */
- 
- #define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS \
-   HB_UNICODE_FUNC_IMPLEMENT (combining_class) \
--  HB_UNICODE_FUNC_IMPLEMENT (eastasian_width) \
-+  HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (eastasian_width)) \
-   HB_UNICODE_FUNC_IMPLEMENT (general_category) \
-   HB_UNICODE_FUNC_IMPLEMENT (mirroring) \
-   HB_UNICODE_FUNC_IMPLEMENT (script) \
-   HB_UNICODE_FUNC_IMPLEMENT (compose) \
-   HB_UNICODE_FUNC_IMPLEMENT (decompose) \
--  HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility) \
-+  HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (decompose_compatibility)) \
-   /* ^--- Add new callbacks here */
- 
- /* Simple callbacks are those taking a hb_codepoint_t and returning a hb_codepoint_t */
- #define HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE \
-   HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_combining_class_t, combining_class) \
--  HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width) \
-+  HB_IF_NOT_DEPRECATED (HB_UNICODE_FUNC_IMPLEMENT (unsigned int, eastasian_width)) \
-   HB_UNICODE_FUNC_IMPLEMENT (hb_unicode_general_category_t, general_category) \
-   HB_UNICODE_FUNC_IMPLEMENT (hb_codepoint_t, mirroring) \
-   HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
-   /* ^--- Add new simple callbacks here */
- 
- struct hb_unicode_funcs_t
- {
-   hb_object_header_t header;
-@@ -84,17 +84,21 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIM
-   {
-     *a = ab; *b = 0;
-     return func.decompose (this, ab, a, b, user_data.decompose);
-   }
- 
-   unsigned int decompose_compatibility (hb_codepoint_t  u,
- 					hb_codepoint_t *decomposed)
-   {
-+#ifdef HB_DISABLE_DEPRECATED
-+    unsigned int ret  = 0;
-+#else
-     unsigned int ret = func.decompose_compatibility (this, u, decomposed, user_data.decompose_compatibility);
-+#endif
-     if (ret == 1 && u == decomposed[0]) {
-       decomposed[0] = 0;
-       return 0;
-     }
-     decomposed[ret] = 0;
-     return ret;
-   }
- 
-diff --git a/gfx/harfbuzz/src/hb-uniscribe.cc b/gfx/harfbuzz/src/hb-uniscribe.cc
---- a/gfx/harfbuzz/src/hb-uniscribe.cc
-+++ b/gfx/harfbuzz/src/hb-uniscribe.cc
-@@ -278,34 +278,34 @@ hb_uniscribe_shaper_get_funcs ()
-   return static_uniscribe_shaper_funcs.get_unconst ();
- }
- 
- 
- struct active_feature_t {
-   OPENTYPE_FEATURE_RECORD rec;
-   unsigned int order;
- 
--  static int cmp (const void *pa, const void *pb) {
-+  HB_INTERNAL static int cmp (const void *pa, const void *pb) {
-     const active_feature_t *a = (const active_feature_t *) pa;
-     const active_feature_t *b = (const active_feature_t *) pb;
-     return a->rec.tagFeature < b->rec.tagFeature ? -1 : a->rec.tagFeature > b->rec.tagFeature ? 1 :
- 	   a->order < b->order ? -1 : a->order > b->order ? 1 :
- 	   a->rec.lParameter < b->rec.lParameter ? -1 : a->rec.lParameter > b->rec.lParameter ? 1 :
- 	   0;
-   }
-   bool operator== (const active_feature_t *f)
-   { return cmp (this, f) == 0; }
- };
- 
- struct feature_event_t {
-   unsigned int index;
-   bool start;
-   active_feature_t feature;
- 
--  static int cmp (const void *pa, const void *pb)
-+  HB_INTERNAL static int cmp (const void *pa, const void *pb)
-   {
-     const feature_event_t *a = (const feature_event_t *) pa;
-     const feature_event_t *b = (const feature_event_t *) pb;
-     return a->index < b->index ? -1 : a->index > b->index ? 1 :
- 	   a->start < b->start ? -1 : a->start > b->start ? 1 :
- 	   active_feature_t::cmp (&a->feature, &b->feature);
-   }
- };
-@@ -391,28 +391,28 @@ static hb_blob_t *
-   {
-     hb_blob_destroy (blob);
-     return nullptr;
-   }
- 
-   memcpy(new_sfnt_data, orig_sfnt_data, length);
- 
-   OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
--  name.format.set (0);
--  name.count.set (ARRAY_LENGTH (name_IDs));
--  name.stringOffset.set (name.get_size ());
-+  name.format = 0;
-+  name.count = ARRAY_LENGTH (name_IDs);
-+  name.stringOffset = name.get_size ();
-   for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
-   {
-     OT::NameRecord &record = name.nameRecordZ[i];
--    record.platformID.set (3);
--    record.encodingID.set (1);
--    record.languageID.set (0x0409u); /* English */
--    record.nameID.set (name_IDs[i]);
--    record.length.set (name_str_len * 2);
--    record.offset.set (0);
-+    record.platformID = 3;
-+    record.encodingID = 1;
-+    record.languageID = 0x0409u; /* English */
-+    record.nameID = name_IDs[i];
-+    record.length = name_str_len * 2;
-+    record.offset = 0;
-   }
- 
-   /* Copy string data from new_name, converting wchar_t to UTF16BE. */
-   unsigned char *p = &StructAfter<unsigned char> (name);
-   for (unsigned int i = 0; i < name_str_len; i++)
-   {
-     *p++ = new_name[i] >> 8;
-     *p++ = new_name[i] & 0xff;
-@@ -426,18 +426,18 @@ static hb_blob_t *
-     /* Note: doing multiple edits (ie. TTC) can be unsafe.  There may be
-      * toe-stepping.  But we don't really care. */
-     const OT::OpenTypeFontFace &face = file.get_face (face_index);
-     unsigned int index;
-     if (face.find_table_index (HB_OT_TAG_name, &index))
-     {
-       OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index));
-       record.checkSum.set_for_data (&name, padded_name_table_length);
--      record.offset.set (name_table_offset);
--      record.length.set (name_table_length);
-+      record.offset = name_table_offset;
-+      record.length = name_table_length;
-     }
-     else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */
-     {
-       free (new_sfnt_data);
-       hb_blob_destroy (blob);
-       return nullptr;
-     }
-   }
-@@ -693,17 +693,17 @@ hb_bool_t
-       if (event->start)
-       {
- 	active_features.push (event->feature);
-       }
-       else
-       {
-         active_feature_t *feature = active_features.find (&event->feature);
- 	if (feature)
--	  active_features.remove (feature - active_features.arrayZ ());
-+	  active_features.remove (feature - active_features.arrayZ);
-       }
-     }
- 
-     if (!range_records.length) /* No active feature found. */
-       num_features = 0;
- 
-     /* Fixup the pointers. */
-     for (unsigned int i = 0; i < range_records.length; i++)
-@@ -723,22 +723,22 @@ hb_bool_t
- 
- retry:
- 
-   unsigned int scratch_size;
-   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
- 
- #define ALLOCATE_ARRAY(Type, name, len) \
-   Type *name = (Type *) scratch; \
--  { \
-+  do { \
-     unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
-     assert (_consumed <= scratch_size); \
-     scratch += _consumed; \
-     scratch_size -= _consumed; \
--  }
-+  } while (0)
- 
- #define utf16_index() var1.u32
- 
-   ALLOCATE_ARRAY (WCHAR, pchars, buffer->len * 2);
- 
-   unsigned int chars_len = 0;
-   for (unsigned int i = 0; i < buffer->len; i++)
-   {
-@@ -884,18 +884,18 @@ retry:
-     items[i].a.fLogicalOrder = true;
- 
-   retry_shape:
-     hr = funcs->ScriptShapeOpenType (font_data->hdc,
- 				     &font_data->script_cache,
- 				     &items[i].a,
- 				     script_tags[i],
- 				     language_tag,
--				     range_char_counts.arrayZ (),
--				     range_properties.arrayZ (),
-+				     range_char_counts.arrayZ,
-+				     range_properties.arrayZ,
- 				     range_properties.length,
- 				     pchars + chars_offset,
- 				     item_chars_len,
- 				     glyphs_size - glyphs_offset,
- 				     /* out */
- 				     log_clusters + chars_offset,
- 				     char_props + chars_offset,
- 				     glyphs + glyphs_offset,
-@@ -925,18 +925,18 @@ retry:
-     for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
-       log_clusters[j] += glyphs_offset;
- 
-     hr = funcs->ScriptPlaceOpenType (font_data->hdc,
- 				     &font_data->script_cache,
- 				     &items[i].a,
- 				     script_tags[i],
- 				     language_tag,
--				     range_char_counts.arrayZ (),
--				     range_properties.arrayZ (),
-+				     range_char_counts.arrayZ,
-+				     range_properties.arrayZ,
- 				     range_properties.length,
- 				     pchars + chars_offset,
- 				     log_clusters + chars_offset,
- 				     char_props + chars_offset,
- 				     item_chars_len,
- 				     glyphs + glyphs_offset,
- 				     glyph_props + glyphs_offset,
- 				     glyphs_len,
-@@ -962,17 +962,17 @@ retry:
-   /* Ok, we've got everything we need, now compose output buffer,
-    * very, *very*, carefully! */
- 
-   /* Calculate visual-clusters.  That's what we ship. */
-   for (unsigned int i = 0; i < glyphs_len; i++)
-     vis_clusters[i] = (uint32_t) -1;
-   for (unsigned int i = 0; i < buffer->len; i++) {
-     uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
--    *p = MIN (*p, buffer->info[i].cluster);
-+    *p = hb_min (*p, buffer->info[i].cluster);
-   }
-   for (unsigned int i = 1; i < glyphs_len; i++)
-     if (vis_clusters[i] == (uint32_t) -1)
-       vis_clusters[i] = vis_clusters[i - 1];
- 
- #undef utf16_index
- 
-   if (unlikely (!buffer->ensure (glyphs_len)))
-diff --git a/gfx/harfbuzz/src/hb-vector.hh b/gfx/harfbuzz/src/hb-vector.hh
---- a/gfx/harfbuzz/src/hb-vector.hh
-+++ b/gfx/harfbuzz/src/hb-vector.hh
-@@ -33,113 +33,151 @@
- 
- 
- template <typename Type>
- struct hb_vector_t
- {
-   typedef Type item_t;
-   static constexpr unsigned item_size = hb_static_size (Type);
- 
--  HB_NO_COPY_ASSIGN_TEMPLATE (hb_vector_t, Type);
-   hb_vector_t ()  { init (); }
-+  hb_vector_t (const hb_vector_t &o)
-+  {
-+    init ();
-+    alloc (o.length);
-+    hb_copy (o, *this);
-+  }
-+  hb_vector_t (hb_vector_t &&o)
-+  {
-+    allocated = o.allocated;
-+    length = o.length;
-+    arrayZ = o.arrayZ;
-+    o.init ();
-+  }
-   ~hb_vector_t () { fini (); }
- 
--  unsigned int length;
-   private:
-   int allocated; /* == -1 means allocation failed. */
--  Type *arrayZ_;
-   public:
-+  unsigned int length;
-+  public:
-+  Type *arrayZ;
- 
-   void init ()
-   {
-     allocated = length = 0;
--    arrayZ_ = nullptr;
-+    arrayZ = nullptr;
-   }
- 
-   void fini ()
-   {
--    if (arrayZ_)
--      free (arrayZ_);
-+    free (arrayZ);
-     init ();
-   }
-   void fini_deep ()
-   {
--    Type *array = arrayZ();
-     unsigned int count = length;
-     for (unsigned int i = 0; i < count; i++)
--      array[i].fini ();
-+      arrayZ[i].fini ();
-     fini ();
-   }
- 
--  const Type * arrayZ () const { return arrayZ_; }
--        Type * arrayZ ()       { return arrayZ_; }
-+  void reset () { resize (0); }
-+
-+  hb_vector_t& operator = (const hb_vector_t &o)
-+  {
-+    reset ();
-+    alloc (o.length);
-+    hb_copy (o, *this);
-+    return *this;
-+  }
-+  hb_vector_t& operator = (hb_vector_t &&o)
-+  {
-+    fini ();
-+    allocated = o.allocated;
-+    length = o.length;
-+    arrayZ = o.arrayZ;
-+    o.init ();
-+    return *this;
-+  }
-+
-+  hb_bytes_t as_bytes () const
-+  { return hb_bytes_t ((const char *) arrayZ, length * item_size); }
-+
-+  bool operator == (const hb_vector_t &o) const { return as_array () == o.as_array (); }
-+  bool operator != (const hb_vector_t &o) const { return !(*this == o); }
-+  uint32_t hash () const { return as_array ().hash (); }
- 
-   Type& operator [] (int i_)
-   {
-     unsigned int i = (unsigned int) i_;
-     if (unlikely (i >= length))
-       return Crap (Type);
--    return arrayZ()[i];
-+    return arrayZ[i];
-   }
-   const Type& operator [] (int i_) const
-   {
-     unsigned int i = (unsigned int) i_;
-     if (unlikely (i >= length))
-       return Null(Type);
--    return arrayZ()[i];
-+    return arrayZ[i];
-   }
- 
--  explicit_operator bool () const { return length; }
-+  Type& tail () { return (*this)[length - 1]; }
-+  const Type& tail () const { return (*this)[length - 1]; }
-+
-+  explicit operator bool () const { return length; }
-+  unsigned get_size () const { return length * item_size; }
-+
-+  /* Sink interface. */
-+  template <typename T>
-+  hb_vector_t& operator << (T&& v) { push (hb_forward<T> (v)); return *this; }
- 
--  hb_array_t<Type> as_array ()
--  { return hb_array (arrayZ(), length); }
--  hb_array_t<const Type> as_array () const
--  { return hb_array (arrayZ(), length); }
-+  hb_array_t<      Type> as_array ()       { return hb_array (arrayZ, length); }
-+  hb_array_t<const Type> as_array () const { return hb_array (arrayZ, length); }
-+
-+  /* Iterator. */
-+  typedef hb_array_t<const Type>   iter_t;
-+  typedef hb_array_t<      Type> writer_t;
-+    iter_t   iter () const { return as_array (); }
-+  writer_t writer ()       { return as_array (); }
-+  operator   iter_t () const { return   iter (); }
-+  operator writer_t ()       { return writer (); }
- 
-   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int count) const
-   { return as_array ().sub_array (start_offset, count);}
-   hb_array_t<const Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
-   { return as_array ().sub_array (start_offset, count);}
-   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int count)
-   { return as_array ().sub_array (start_offset, count);}
-   hb_array_t<Type> sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
-   { return as_array ().sub_array (start_offset, count);}
- 
-   hb_sorted_array_t<Type> as_sorted_array ()
--  { return hb_sorted_array (arrayZ(), length); }
-+  { return hb_sorted_array (arrayZ, length); }
-   hb_sorted_array_t<const Type> as_sorted_array () const
--  { return hb_sorted_array (arrayZ(), length); }
-+  { return hb_sorted_array (arrayZ, length); }
- 
--  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int count) const
--  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
--  hb_array_t<const Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */) const
--  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
--  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int count)
--  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
--  hb_array_t<Type> sorted_sub_array (unsigned int start_offset, unsigned int *count = nullptr /* IN/OUT */)
--  { return as_sorted_array ().sorted_sub_array (start_offset, count);}
-+  template <typename T> explicit operator T * () { return arrayZ; }
-+  template <typename T> explicit operator const T * () const { return arrayZ; }
- 
--  template <typename T> explicit_operator T * () { return arrayZ(); }
--  template <typename T> explicit_operator const T * () const { return arrayZ(); }
--  operator hb_array_t<Type> ()             { return as_array (); }
--  operator hb_array_t<const Type> () const { return as_array (); }
--
--  Type * operator  + (unsigned int i) { return arrayZ() + i; }
--  const Type * operator  + (unsigned int i) const { return arrayZ() + i; }
-+  Type * operator  + (unsigned int i) { return arrayZ + i; }
-+  const Type * operator  + (unsigned int i) const { return arrayZ + i; }
- 
-   Type *push ()
-   {
-     if (unlikely (!resize (length + 1)))
-       return &Crap(Type);
--    return &arrayZ()[length - 1];
-+    return &arrayZ[length - 1];
-   }
--  Type *push (const Type& v)
-+  template <typename T>
-+  Type *push (T&& v)
-   {
-     Type *p = push ();
--    *p = v;
-+    *p = hb_forward<T> (v);
-     return p;
-   }
- 
-   bool in_error () const { return allocated < 0; }
- 
-   /* Allocate for size but don't adjust length. */
-   bool alloc (unsigned int size)
-   {
-@@ -156,105 +194,117 @@ struct hb_vector_t
-       new_allocated += (new_allocated >> 1) + 8;
- 
-     Type *new_array = nullptr;
-     bool overflows =
-       (int) new_allocated < 0 ||
-       (new_allocated < (unsigned) allocated) ||
-       hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
-     if (likely (!overflows))
--      new_array = (Type *) realloc (arrayZ_, new_allocated * sizeof (Type));
-+      new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
- 
-     if (unlikely (!new_array))
-     {
-       allocated = -1;
-       return false;
-     }
- 
--    arrayZ_ = new_array;
-+    arrayZ = new_array;
-     allocated = new_allocated;
- 
-     return true;
-   }
- 
-   bool resize (int size_)
-   {
-     unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-     if (!alloc (size))
-       return false;
- 
-     if (size > length)
--      memset (arrayZ() + length, 0, (size - length) * sizeof (*arrayZ()));
-+      memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
- 
-     length = size;
-     return true;
-   }
- 
--  void pop ()
-+  Type pop ()
-   {
--    if (!length) return;
--    length--;
-+    if (!length) return Null(Type);
-+    return hb_move (arrayZ[--length]); /* Does this move actually work? */
-   }
- 
-   void remove (unsigned int i)
-   {
-     if (unlikely (i >= length))
-       return;
--    Type *array = arrayZ();
--    memmove (static_cast<void *> (&array[i]),
--	     static_cast<void *> (&array[i + 1]),
-+    memmove (static_cast<void *> (&arrayZ[i]),
-+	     static_cast<void *> (&arrayZ[i + 1]),
- 	     (length - i - 1) * sizeof (Type));
-     length--;
-   }
- 
-   void shrink (int size_)
-   {
-     unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-      if (size < length)
-        length = size;
-   }
- 
-   template <typename T>
-   Type *find (T v)
-   {
--    Type *array = arrayZ();
-     for (unsigned int i = 0; i < length; i++)
--      if (array[i] == v)
--	return &array[i];
-+      if (arrayZ[i] == v)
-+	return &arrayZ[i];
-     return nullptr;
-   }
-   template <typename T>
-   const Type *find (T v) const
-   {
--    const Type *array = arrayZ();
-     for (unsigned int i = 0; i < length; i++)
--      if (array[i] == v)
--	return &array[i];
-+      if (arrayZ[i] == v)
-+	return &arrayZ[i];
-     return nullptr;
-   }
- 
-   void qsort (int (*cmp)(const void*, const void*))
-   { as_array ().qsort (cmp); }
-   void qsort (unsigned int start = 0, unsigned int end = (unsigned int) -1)
-   { as_array ().qsort (start, end); }
- 
-   template <typename T>
-   Type *lsearch (const T &x, Type *not_found = nullptr)
-   { return as_array ().lsearch (x, not_found); }
-   template <typename T>
-   const Type *lsearch (const T &x, const Type *not_found = nullptr) const
-   { return as_array ().lsearch (x, not_found); }
-+};
-+
-+template <typename Type>
-+struct hb_sorted_vector_t : hb_vector_t<Type>
-+{
-+  hb_sorted_array_t<      Type> as_array ()       { return hb_sorted_array (this->arrayZ, this->length); }
-+  hb_sorted_array_t<const Type> as_array () const { return hb_sorted_array (this->arrayZ, this->length); }
-+
-+  /* Iterator. */
-+  typedef hb_sorted_array_t<const Type> const_iter_t;
-+  typedef hb_sorted_array_t<      Type>       iter_t;
-+  const_iter_t  iter () const { return as_array (); }
-+  const_iter_t citer () const { return as_array (); }
-+        iter_t  iter ()       { return as_array (); }
-+  operator       iter_t ()       { return iter (); }
-+  operator const_iter_t () const { return iter (); }
- 
-   template <typename T>
-   Type *bsearch (const T &x, Type *not_found = nullptr)
--  { return as_sorted_array ().bsearch (x, not_found); }
-+  { return as_array ().bsearch (x, not_found); }
-   template <typename T>
-   const Type *bsearch (const T &x, const Type *not_found = nullptr) const
--  { return as_sorted_array ().bsearch (x, not_found); }
-+  { return as_array ().bsearch (x, not_found); }
-   template <typename T>
-   bool bfind (const T &x, unsigned int *i = nullptr,
- 		     hb_bfind_not_found_t not_found = HB_BFIND_NOT_FOUND_DONT_STORE,
- 		     unsigned int to_store = (unsigned int) -1) const
--  { return as_sorted_array ().bfind (x, i, not_found, to_store); }
-+  { return as_array ().bfind (x, i, not_found, to_store); }
- };
- 
--
- #endif /* HB_VECTOR_HH */
-diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h
---- a/gfx/harfbuzz/src/hb-version.h
-+++ b/gfx/harfbuzz/src/hb-version.h
-@@ -32,20 +32,20 @@
- #define HB_VERSION_H
- 
- #include "hb-common.h"
- 
- HB_BEGIN_DECLS
- 
- 
- #define HB_VERSION_MAJOR 2
--#define HB_VERSION_MINOR 4
--#define HB_VERSION_MICRO 0
-+#define HB_VERSION_MINOR 5
-+#define HB_VERSION_MICRO 1
- 
--#define HB_VERSION_STRING "2.4.0"
-+#define HB_VERSION_STRING "2.5.1"
- 
- #define HB_VERSION_ATLEAST(major,minor,micro) \
- 	((major)*10000+(minor)*100+(micro) <= \
- 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
- 
- 
- HB_EXTERN void
- hb_version (unsigned int *major,
-diff --git a/gfx/harfbuzz/src/hb-warning.cc b/gfx/harfbuzz/src/hb-warning.cc
---- a/gfx/harfbuzz/src/hb-warning.cc
-+++ b/gfx/harfbuzz/src/hb-warning.cc
-@@ -21,17 +21,17 @@
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- 
--#if defined(HB_ATOMIC_INT_NIL)
-+#ifdef HB_ATOMIC_INT_NIL
- #error "Could not find any system to define atomic_int macros, library WILL NOT be thread-safe"
- #error "Check hb-atomic.hh for possible resolutions."
- #endif
- 
--#if defined(HB_MUTEX_IMPL_NIL)
-+#ifdef HB_MUTEX_IMPL_NIL
- #error "Could not find any system to define mutex macros, library WILL NOT be thread-safe"
- #error "Check hb-mutex.hh for possible resolutions."
- #endif
-diff --git a/gfx/harfbuzz/src/hb.hh b/gfx/harfbuzz/src/hb.hh
---- a/gfx/harfbuzz/src/hb.hh
-+++ b/gfx/harfbuzz/src/hb.hh
-@@ -24,18 +24,19 @@
-  *
-  * Red Hat Author(s): Behdad Esfahbod
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #ifndef HB_HH
- #define HB_HH
- 
-+
- #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
--#if defined(_MSC_VER)
-+#ifdef _MSC_VER
- #pragma warning( disable: 4068 ) /* Unknown pragma */
- #endif
- #if defined(__GNUC__) || defined(__clang__)
- /* Rules:
-  *
-  * - All pragmas are declared GCC even if they are clang ones.  Otherwise GCC
-  *   nags, even though we instruct it to ignore -Wunknown-pragmas. ¯\_(ツ)_/¯
-  *
-@@ -60,19 +61,22 @@
- #endif
- 
- /* Error.  Should never happen. */
- #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
- #pragma GCC diagnostic error   "-Wc++11-narrowing"
- #pragma GCC diagnostic error   "-Wcast-align"
- #pragma GCC diagnostic error   "-Wcast-function-type"
- #pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
-+#pragma GCC diagnostic error   "-Wdouble-promotion"
-+#pragma GCC diagnostic error   "-Wextra-semi-stmt"
- #pragma GCC diagnostic error   "-Wformat-security"
- #pragma GCC diagnostic error   "-Wimplicit-function-declaration"
- #pragma GCC diagnostic error   "-Winit-self"
-+#pragma GCC diagnostic error   "-Winjected-class-name"
- #pragma GCC diagnostic error   "-Wmissing-braces"
- #pragma GCC diagnostic error   "-Wmissing-declarations"
- #pragma GCC diagnostic error   "-Wmissing-prototypes"
- #pragma GCC diagnostic error   "-Wnested-externs"
- #pragma GCC diagnostic error   "-Wold-style-definition"
- #pragma GCC diagnostic error   "-Wpointer-arith"
- #pragma GCC diagnostic error   "-Wredundant-decls"
- #pragma GCC diagnostic error   "-Wreorder"
-@@ -88,16 +92,17 @@
- #pragma GCC diagnostic error   "-Wunused-variable"
- #pragma GCC diagnostic error   "-Wvla"
- #pragma GCC diagnostic error   "-Wwrite-strings"
- #endif
- 
- /* Warning.  To be investigated if happens. */
- #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
- #pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
-+#pragma GCC diagnostic warning "-Wdeprecated"
- #pragma GCC diagnostic warning "-Wdisabled-optimization"
- #pragma GCC diagnostic warning "-Wformat=2"
- #pragma GCC diagnostic warning "-Wignored-pragma-optimize"
- #pragma GCC diagnostic warning "-Wlogical-op"
- #pragma GCC diagnostic warning "-Wmaybe-uninitialized"
- #pragma GCC diagnostic warning "-Wmissing-format-attribute"
- #pragma GCC diagnostic warning "-Wundef"
- #endif
-@@ -115,24 +120,25 @@
- #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_IGNORED
- #pragma GCC diagnostic ignored "-Wclass-memaccess"
- #pragma GCC diagnostic ignored "-Wformat-nonliteral"
- #pragma GCC diagnostic ignored "-Wformat-zero-length"
- #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
- #pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang
- #pragma GCC diagnostic ignored "-Wstrict-aliasing"
- #pragma GCC diagnostic ignored "-Wtype-limits"
-+#pragma GCC diagnostic ignored "-Wc++11-compat" // only gcc raises it
- #endif
- 
- #endif
- #endif
- 
--#ifdef HAVE_CONFIG_H
--#include "config.h"
--#endif
-+
-+#include "hb-config.hh"
-+
- 
- /*
-  * Following added based on what AC_USE_SYSTEM_EXTENSIONS adds to
-  * config.h.in.  Copied here for the convenience of those embedding
-  * HarfBuzz and not using our build system.
-  */
- /* Enable extensions on AIX 3, Interix.  */
- #ifndef _ALL_SOURCE
-@@ -161,18 +167,17 @@
- 
- #include "hb.h"
- #define HB_H_IN
- #include "hb-ot.h"
- #define HB_OT_H_IN
- #include "hb-aat.h"
- #define HB_AAT_H_IN
- 
--#include "hb-aat.h"
--
-+#include <limits.h>
- #include <math.h>
- #include <stdlib.h>
- #include <stddef.h>
- #include <string.h>
- #include <assert.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdarg.h>
-@@ -195,83 +200,30 @@ extern "C" void* hb_malloc_impl(size_t s
- extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
- extern "C" void* hb_realloc_impl(void *ptr, size_t size);
- extern "C" void  hb_free_impl(void *ptr);
- #define malloc hb_malloc_impl
- #define calloc hb_calloc_impl
- #define realloc hb_realloc_impl
- #define free hb_free_impl
- 
--#if defined(hb_memalign_impl)
-+#ifdef hb_memalign_impl
- extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
- #define posix_memalign hb_memalign_impl
- #else
- #undef HAVE_POSIX_MEMALIGN
- #endif
- 
- #endif
- 
- 
- /*
-  * Compiler attributes
-  */
- 
--/* https://github.com/harfbuzz/harfbuzz/issues/1634 */
--#if __cplusplus < 201103L && !defined(_MSC_VER)
--
--#ifndef nullptr
--#define nullptr NULL
--#endif
--
--#ifndef constexpr
--#define constexpr const
--#endif
--
--#ifndef static_assert
--#define static_assert(e, msg) \
--	HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
--#endif // static_assert
--
--#if defined(__GNUC__)
--#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8))
--#define thread_local __thread
--#endif
--#else
--#define thread_local
--#endif
--
--template <typename T>
--struct _hb_alignof
--{
--  struct s
--  {
--    char c;
--    T t;
--  };
--  static constexpr size_t value = offsetof (s, t);
--};
--#ifndef alignof
--#define alignof(x) (_hb_alignof<x>::value)
--#endif
--
--/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
--#ifndef explicit_operator
--#define explicit_operator operator
--#endif
--
--#else /* __cplusplus >= 201103L */
--
--/* https://github.com/harfbuzz/harfbuzz/issues/1127 */
--#ifndef explicit_operator
--#define explicit_operator explicit operator
--#endif
--
--#endif /* __cplusplus < 201103L */
--
--
- #if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
- #define likely(expr) (__builtin_expect (!!(expr), 1))
- #define unlikely(expr) (__builtin_expect (!!(expr), 0))
- #else
- #define likely(expr) (expr)
- #define unlikely(expr) (expr)
- #endif
- 
-@@ -307,16 +259,23 @@ struct _hb_alignof
-    /* We do not try to export internal symbols on Visual Studio */
- #  define HB_INTERNAL
- #else
- #  define HB_INTERNAL
- #  define HB_NO_VISIBILITY 1
- # endif
- #endif
- 
-+/* https://github.com/harfbuzz/harfbuzz/issues/1651 */
-+#if defined(__clang__) && __clang_major__ < 10
-+#define static_const static
-+#else
-+#define static_const static const
-+#endif
-+
- #if defined(__GNUC__) && (__GNUC__ >= 3)
- #define HB_FUNC __PRETTY_FUNCTION__
- #elif defined(_MSC_VER)
- #define HB_FUNC __FUNCSIG__
- #else
- #define HB_FUNC __func__
- #endif
- 
-@@ -353,17 +312,17 @@ struct _hb_alignof
-     * https://msdn.microsoft.com/en-us/library/ms235402%28VS.80%29.aspx
-     */
- #  include <sal.h>
- #  define HB_FALLTHROUGH __fallthrough
- #else
- #  define HB_FALLTHROUGH /* FALLTHROUGH */
- #endif
- 
--#if defined(__clang__)
-+#ifdef __clang__
- /* Disable certain sanitizer errors. */
- /* https://github.com/harfbuzz/harfbuzz/issues/1247 */
- #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow")))
- #else
- #define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW
- #endif
- 
- 
-@@ -384,29 +343,37 @@ struct _hb_alignof
- #  endif
- #  ifndef STRICT
- #    define STRICT 1
- #  endif
- 
- #  if defined(_WIN32_WCE)
-      /* Some things not defined on Windows CE. */
- #    define vsnprintf _vsnprintf
--#    define getenv(Name) nullptr
-+#    ifndef HB_NO_GETENV
-+#      define HB_NO_GETENV
-+#    endif
- #    if _WIN32_WCE < 0x800
- #      define setlocale(Category, Locale) "C"
- static int errno = 0; /* Use something better? */
- #    endif
- #  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
--#    define getenv(Name) nullptr
-+#    ifndef HB_NO_GETENV
-+#      define HB_NO_GETENV
-+#    endif
- #  endif
- #  if defined(_MSC_VER) && _MSC_VER < 1900
- #    define snprintf _snprintf
- #  endif
- #endif
- 
-+#ifdef HB_NO_GETENV
-+#define getenv(Name) nullptr
-+#endif
-+
- #if defined(HAVE_ATEXIT) && !defined(HB_USE_ATEXIT)
- /* atexit() is only safe to be called from shared libraries on certain
-  * platforms.  Whitelist.
-  * https://bugs.freedesktop.org/show_bug.cgi?id=82246 */
- #  if defined(__linux) && defined(__GLIBC_PREREQ)
- #    if __GLIBC_PREREQ(2,3)
- /* From atexit() manpage, it's safe with glibc 2.2.3 on Linux. */
- #      define HB_USE_ATEXIT 1
-@@ -455,99 +422,57 @@ static_assert ((sizeof (int32_t) == 4), 
- static_assert ((sizeof (uint32_t) == 4), "");
- static_assert ((sizeof (int64_t) == 8), "");
- static_assert ((sizeof (uint64_t) == 8), "");
- static_assert ((sizeof (hb_codepoint_t) == 4), "");
- static_assert ((sizeof (hb_position_t) == 4), "");
- static_assert ((sizeof (hb_mask_t) == 4), "");
- static_assert ((sizeof (hb_var_int_t) == 4), "");
- 
--
--#if __cplusplus >= 201103L
--
--/* We only enable these with C++11 or later, since earlier language
-- * does not allow structs with constructors in unions, and we need
-- * those. */
--
--#define HB_NO_COPY_ASSIGN(TypeName) \
--  TypeName(const TypeName&); \
--  void operator=(const TypeName&)
--#define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) \
--  TypeName(const TypeName<T>&); \
--  void operator=(const TypeName<T>&)
--#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \
--  TypeName(const TypeName<T1, T2>&); \
--  void operator=(const TypeName<T1, T2>&)
--#define HB_NO_CREATE_COPY_ASSIGN(TypeName) \
--  TypeName(); \
--  TypeName(const TypeName&); \
--  void operator=(const TypeName&)
--#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) \
--  TypeName(); \
--  TypeName(const TypeName<T>&); \
--  void operator=(const TypeName<T>&)
--#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) \
--  TypeName(); \
--  TypeName(const TypeName<T1, T2>&); \
--  void operator=(const TypeName<T1, T2>&)
--
--#else /* __cpluspplus >= 201103L */
--
--#define HB_NO_COPY_ASSIGN(TypeName) static_assert (true, "")
--#define HB_NO_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "")
--#define HB_NO_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "")
--#define HB_NO_CREATE_COPY_ASSIGN(TypeName) static_assert (true, "")
--#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE(TypeName, T) static_assert (true, "")
--#define HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2(TypeName, T1, T2) static_assert (true, "")
--
--#endif /* __cpluspplus >= 201103L */
-+#define HB_DELETE_COPY_ASSIGN(TypeName) \
-+  TypeName(const TypeName&) = delete; \
-+  void operator=(const TypeName&) = delete
-+#define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \
-+  TypeName() = delete; \
-+  TypeName(const TypeName&) = delete; \
-+  void operator=(const TypeName&) = delete
- 
- 
- /*
-  * Compiler-assisted vectorization parameters.
-  */
- 
- /*
-  * Disable vectorization for now.  To correctly use them, we should
-  * use posix_memalign() to allocate in hb_vector_t.  Otherwise, can
-  * cause misaligned access.
-  *
-  * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
-  */
--#if !defined(HB_VECTOR_SIZE)
-+#ifndef HB_VECTOR_SIZE
- #  define HB_VECTOR_SIZE 0
- #endif
- 
- /* The `vector_size' attribute was introduced in gcc 3.1. */
--#if !defined(HB_VECTOR_SIZE)
-+#ifndef HB_VECTOR_SIZE
- #  if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
- #    define HB_VECTOR_SIZE 128
- #  else
- #    define HB_VECTOR_SIZE 0
- #  endif
- #endif
- static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2.");
- static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64.");
- #if HB_VECTOR_SIZE
- typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
- #else
- typedef uint64_t hb_vector_size_impl_t;
- #endif
- 
- 
--/* HB_NDEBUG disables some sanity checks that are very safe to disable and
-- * should be disabled in production systems.  If NDEBUG is defined, enable
-- * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
-- * light-weight) to be enabled, then HB_DEBUG can be defined to disable
-- * the costlier checks. */
--#ifdef NDEBUG
--#define HB_NDEBUG 1
--#endif
--
--
- /* Flags */
- 
- /* Enable bitwise ops on enums marked as flags_t */
- /* To my surprise, looks like the function resolver is happy to silently cast
-  * one enum to another...  So this doesn't provide the type-checking that I
-  * originally had in mind... :(.
-  *
-  * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
-@@ -619,41 +544,119 @@ static inline int
-   return 0;
- }
- #if !defined(posix_memalign) && !defined(HAVE_POSIX_MEMALIGN)
- #define posix_memalign _hb_memalign
- #endif
- 
- 
- /*
-+ * Big-endian integers.  Here because fundamental.
-+ */
-+
-+template <typename Type, int Bytes> struct BEInt;
-+
-+template <typename Type>
-+struct BEInt<Type, 1>
-+{
-+  public:
-+  BEInt<Type, 1>& operator = (Type V)
-+  {
-+    v = V;
-+    return *this;
-+  }
-+  operator Type () const { return v; }
-+  private: uint8_t v;
-+};
-+template <typename Type>
-+struct BEInt<Type, 2>
-+{
-+  public:
-+  BEInt<Type, 2>& operator = (Type V)
-+  {
-+    v[0] = (V >>  8) & 0xFF;
-+    v[1] = (V      ) & 0xFF;
-+    return *this;
-+  }
-+  operator Type () const
-+  {
-+#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
-+    defined(__BYTE_ORDER) && \
-+    (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
-+    /* Spoon-feed the compiler a big-endian integer with alignment 1.
-+     * https://github.com/harfbuzz/harfbuzz/pull/1398 */
-+    struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
-+#if __BYTE_ORDER == __LITTLE_ENDIAN
-+    return __builtin_bswap16 (((packed_uint16_t *) this)->v);
-+#else /* __BYTE_ORDER == __BIG_ENDIAN */
-+    return ((packed_uint16_t *) this)->v;
-+#endif
-+#endif
-+    return (v[0] <<  8)
-+         + (v[1]      );
-+  }
-+  private: uint8_t v[2];
-+};
-+template <typename Type>
-+struct BEInt<Type, 3>
-+{
-+  public:
-+  BEInt<Type, 3>& operator = (Type V)
-+  {
-+    v[0] = (V >> 16) & 0xFF;
-+    v[1] = (V >>  8) & 0xFF;
-+    v[2] = (V      ) & 0xFF;
-+    return *this;
-+  }
-+  operator Type () const
-+  {
-+    return (v[0] << 16)
-+         + (v[1] <<  8)
-+         + (v[2]      );
-+  }
-+  private: uint8_t v[3];
-+};
-+template <typename Type>
-+struct BEInt<Type, 4>
-+{
-+  public:
-+  BEInt<Type, 4>& operator = (Type V)
-+  {
-+    v[0] = (V >> 24) & 0xFF;
-+    v[1] = (V >> 16) & 0xFF;
-+    v[2] = (V >>  8) & 0xFF;
-+    v[3] = (V      ) & 0xFF;
-+    return *this;
-+  }
-+  operator Type () const
-+  {
-+    return (v[0] << 24)
-+         + (v[1] << 16)
-+         + (v[2] <<  8)
-+         + (v[3]      );
-+  }
-+  private: uint8_t v[4];
-+};
-+
-+
-+/*
-  * For lack of a better place, put Zawgyi script hack here.
-  * https://github.com/harfbuzz/harfbuzz/issues/1162
-  */
- 
- #define HB_SCRIPT_MYANMAR_ZAWGYI	((hb_script_t) HB_TAG ('Q','a','a','g'))
- 
- 
--/* Some really basic things everyone wants. */
--template <typename T> struct hb_remove_const { typedef T value; };
--template <typename T> struct hb_remove_const<const T> { typedef T value; };
--#define hb_remove_const(T) hb_remove_const<T>::value
--template <typename T> struct hb_remove_reference { typedef T value; };
--template <typename T> struct hb_remove_reference<T &> { typedef T value; };
--#define hb_remove_reference(T) hb_remove_reference<T>::value
--template <typename T> struct hb_remove_pointer { typedef T value; };
--template <typename T> struct hb_remove_pointer<T *> { typedef T value; };
--#define hb_remove_pointer(T) hb_remove_pointer<T>::value
--
--
- /* Headers we include for everyone.  Keep topologically sorted by dependency.
-  * They express dependency amongst themselves, but no other file should include
-  * them directly.*/
--#include "hb-atomic.hh"
-+#include "hb-meta.hh"
- #include "hb-mutex.hh"
--#include "hb-null.hh"
--#include "hb-dsalgs.hh"	// Requires: hb-null
--#include "hb-iter.hh"	// Requires: hb-null
--#include "hb-debug.hh"	// Requires: hb-atomic hb-dsalgs
--#include "hb-array.hh"	// Requires: hb-dsalgs hb-iter hb-null
-+#include "hb-atomic.hh"	// Requires: hb-meta
-+#include "hb-null.hh"	// Requires: hb-meta
-+#include "hb-algs.hh"	// Requires: hb-meta hb-null
-+#include "hb-iter.hh"	// Requires: hb-algs hb-meta
-+#include "hb-debug.hh"	// Requires: hb-algs hb-atomic
-+#include "hb-array.hh"	// Requires: hb-algs hb-iter hb-null
- #include "hb-vector.hh"	// Requires: hb-array hb-null
- #include "hb-object.hh"	// Requires: hb-atomic hb-mutex hb-vector
- 
- #endif /* HB_HH */
-diff --git a/gfx/harfbuzz/src/moz.build b/gfx/harfbuzz/src/moz.build
---- a/gfx/harfbuzz/src/moz.build
-+++ b/gfx/harfbuzz/src/moz.build
-@@ -49,17 +49,16 @@ UNIFIED_SOURCES += [
-     'hb-face.cc',
-     'hb-font.cc',
-     'hb-ot-color.cc',
-     'hb-ot-face.cc',
-     'hb-ot-font.cc',
-     'hb-ot-layout.cc',
-     'hb-ot-map.cc',
-     'hb-ot-math.cc',
--    'hb-ot-name-language.cc',
-     'hb-ot-name.cc',
-     'hb-ot-shape-complex-arabic.cc',
-     'hb-ot-shape-complex-default.cc',
-     'hb-ot-shape-complex-hangul.cc',
-     'hb-ot-shape-complex-hebrew.cc',
-     'hb-ot-shape-complex-indic-table.cc',
-     'hb-ot-shape-complex-myanmar.cc',
-     'hb-ot-shape-complex-thai.cc',
-@@ -98,12 +97,13 @@ if CONFIG['CC_TYPE'] == 'clang-cl':
- 
- FINAL_LIBRARY = 'gkmedias'
- 
- DEFINES['PACKAGE_VERSION'] = '"moz"'
- DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
- DEFINES['HAVE_OT'] = 1
- DEFINES['HAVE_ROUND'] = 1
- DEFINES['HB_NO_MT'] = True
-+DEFINES['HB_NO_UCD'] = True
- DEFINES['HB_NO_UNICODE_FUNCS'] = True
- # Cancel the effect of the -DDEBUG macro if present,
- # because harfbuzz uses that name for its own purposes
- DEFINES['DEBUG'] = False
-diff --git a/gfx/harfbuzz/src/test-algs.cc b/gfx/harfbuzz/src/test-algs.cc
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/test-algs.cc
-@@ -0,0 +1,91 @@
-+/*
-+ * Copyright © 2019  Facebook, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Facebook Author(s): Behdad Esfahbod
-+ */
-+
-+#include "hb.hh"
-+#include "hb-algs.hh"
-+
-+
-+static char *
-+test_func (int a, char **b)
-+{
-+  return b ? b[a] : nullptr;
-+}
-+
-+struct A
-+{
-+  void a () {}
-+};
-+
-+int
-+main (int argc, char **argv)
-+{
-+  int i = 1;
-+  auto p = hb_pair (1, i);
-+
-+  p.second = 2;
-+  assert (i == 2);
-+
-+  const int c = 3;
-+  auto pc = hb_pair (1, c);
-+  assert (pc.second == 3);
-+
-+  auto q = p;
-+  assert (&q != &p);
-+  q.second = 4;
-+  assert (i == 4);
-+
-+  hb_invoke (test_func, 0, nullptr);
-+
-+  A a;
-+  hb_invoke (&A::a, a);
-+
-+  assert (1 == hb_min (8, 1));
-+  assert (8 == hb_max (8, 1));
-+
-+  int x = 1, y = 2;
-+  hb_min (x, 3);
-+  hb_min (3, x);
-+  hb_min (x, 4 + 3);
-+  int &z = hb_min (x, y);
-+  z = 3;
-+  assert (x == 3);
-+
-+  hb_pair_t<const int*, int> xp = hb_pair_t<int *, long> (nullptr, 0);
-+  xp = hb_pair_t<int *, double> (nullptr, 1);
-+  xp = hb_pair_t<const int*, int> (nullptr, 1);
-+
-+  assert (3 == hb_partial (hb_min, 3) (4));
-+  assert (3 == hb_partial<1> (hb_min, 4) (3));
-+
-+  auto M0 = hb_partial<2> (hb_max, 0);
-+  assert (M0 (-2) == 0);
-+  assert (M0 (+2) == 2);
-+
-+  assert (hb_add (2) (5) == 7);
-+  assert (hb_add (5) (2) == 7);
-+
-+  return 0;
-+}
-diff --git a/gfx/harfbuzz/src/test-size-params.cc b/gfx/harfbuzz/src/test-gpos-size-params.cc
-rename from gfx/harfbuzz/src/test-size-params.cc
-rename to gfx/harfbuzz/src/test-gpos-size-params.cc
-diff --git a/gfx/harfbuzz/src/test-would-substitute.cc b/gfx/harfbuzz/src/test-gsub-would-substitute.cc
-rename from gfx/harfbuzz/src/test-would-substitute.cc
-rename to gfx/harfbuzz/src/test-gsub-would-substitute.cc
-diff --git a/gfx/harfbuzz/src/test-iter.cc b/gfx/harfbuzz/src/test-iter.cc
---- a/gfx/harfbuzz/src/test-iter.cc
-+++ b/gfx/harfbuzz/src/test-iter.cc
-@@ -24,61 +24,258 @@
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- #include "hb-iter.hh"
- 
- #include "hb-array.hh"
- #include "hb-set.hh"
-+#include "hb-ot-layout-common.hh"
- 
- 
- template <typename T>
--struct array_iter_t : hb_iter_t<array_iter_t<T>, T>, hb_iter_mixin_t<array_iter_t<T>, T>
-+struct array_iter_t : hb_iter_with_fallback_t<array_iter_t<T>, T&>
- {
-   array_iter_t (hb_array_t<T> arr_) : arr (arr_) {}
- 
--  typedef T __item_type__;
-+  typedef T& __item_t__;
-+  static constexpr bool is_random_access_iterator = true;
-   T& __item_at__ (unsigned i) const { return arr[i]; }
-   void __forward__ (unsigned n) { arr += n; }
-   void __rewind__ (unsigned n) { arr -= n; }
-   unsigned __len__ () const { return arr.length; }
--  bool __random_access__ () const { return true; }
-+  bool operator != (const array_iter_t& o) { return arr != o.arr; }
- 
-   private:
-   hb_array_t<T> arr;
- };
- 
- template <typename T>
- struct some_array_t
- {
-   some_array_t (hb_array_t<T> arr_) : arr (arr_) {}
- 
-   typedef array_iter_t<T> iter_t;
-   array_iter_t<T> iter () { return array_iter_t<T> (arr); }
-   operator array_iter_t<T> () { return iter (); }
--  operator hb_iter_t<array_iter_t<T> > () { return iter (); }
-+  operator hb_iter_t<array_iter_t<T>> () { return iter (); }
- 
-   private:
-   hb_array_t<T> arr;
- };
- 
-+
-+template <typename Iter,
-+	  hb_requires (hb_is_iterator (Iter))>
-+static void
-+test_iterator_non_default_constructable (Iter it)
-+{
-+  /* Iterate over a copy of it. */
-+  for (auto c = it.iter (); c; c++)
-+    *c;
-+
-+  /* Same. */
-+  for (auto c = +it; c; c++)
-+    *c;
-+
-+  /* Range-based for over a copy. */
-+  for (auto _ : +it)
-+    (void) _;
-+
-+  it += it.len ();
-+  it = it + 10;
-+  it = 10 + it;
-+
-+  assert (*it == it[0]);
-+
-+  static_assert (true || it.is_random_access_iterator, "");
-+  static_assert (true || it.is_sorted_iterator, "");
-+}
-+
-+template <typename Iter,
-+	  hb_requires (hb_is_iterator (Iter))>
-+static void
-+test_iterator (Iter it)
-+{
-+  Iter default_constructed;
-+  assert (!default_constructed);
-+
-+  test_iterator_non_default_constructable (it);
-+}
-+
-+template <typename Iterable,
-+	  hb_requires (hb_is_iterable (Iterable))>
-+static void
-+test_iterable (const Iterable &lst = Null(Iterable))
-+{
-+  for (auto _ : lst)
-+    (void) _;
-+
-+  // Test that can take iterator from.
-+  test_iterator (lst.iter ());
-+}
-+
- int
- main (int argc, char **argv)
- {
-   const int src[10] = {};
-   int dst[20];
-   hb_vector_t<int> v;
- 
-   array_iter_t<const int> s (src); /* Implicit conversion from static array. */
-   array_iter_t<const int> s2 (v); /* Implicit conversion from vector. */
-   array_iter_t<int> t (dst);
- 
-+  static_assert (array_iter_t<int>::is_random_access_iterator, "");
-+
-   some_array_t<const int> a (src);
- 
-   s2 = s;
- 
-+  hb_iter (src);
-+  hb_iter (src, 2);
-+
-   hb_fill (t, 42);
--  hb_copy (t, s);
-- // hb_copy (t, a.iter ());
-+  hb_copy (s, t);
-+  hb_copy (a.iter (), t);
-+
-+  test_iterable (v);
-+  hb_set_t st;
-+  st << 1 << 15 << 43;
-+  test_iterable (st);
-+  hb_sorted_array_t<int> sa;
-+  (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::item_t>&> (sa);
-+  (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, hb_sorted_array_t<int>::__item_t__>&> (sa);
-+  (void) static_cast<hb_iter_t<hb_sorted_array_t<int>, int&>&>(sa);
-+  (void) static_cast<hb_iter_t<hb_sorted_array_t<int>>&>(sa);
-+  (void) static_cast<hb_iter_t<hb_array_t<int>, int&>&> (sa);
-+  test_iterable (sa);
-+
-+  test_iterable<hb_array_t<int>> ();
-+  test_iterable<hb_sorted_array_t<const int>> ();
-+  test_iterable<hb_vector_t<float>> ();
-+  test_iterable<hb_set_t> ();
-+  test_iterable<OT::Coverage> ();
-+
-+  test_iterator (hb_zip (st, v));
-+  test_iterator_non_default_constructable (hb_enumerate (st));
-+  test_iterator_non_default_constructable (hb_enumerate (st, -5));
-+  test_iterator_non_default_constructable (hb_enumerate (hb_iter (st)));
-+  test_iterator_non_default_constructable (hb_enumerate (hb_iter (st) + 1));
-+  test_iterator_non_default_constructable (hb_iter (st) | hb_filter ());
-+  test_iterator_non_default_constructable (hb_iter (st) | hb_map (hb_lidentity));
-+
-+  assert (true == hb_all (st));
-+  assert (false == hb_all (st, 42u));
-+  assert (true == hb_any (st));
-+  assert (false == hb_any (st, 14u));
-+  assert (true == hb_any (st, 14u, [] (unsigned _) { return _ - 1u; }));
-+  assert (true == hb_any (st, [] (unsigned _) { return _ == 15u; }));
-+  assert (true == hb_any (st, 15u));
-+  assert (false == hb_none (st));
-+  assert (false == hb_none (st, 15u));
-+  assert (true == hb_none (st, 17u));
-+
-+  hb_array_t<hb_vector_t<int>> pa;
-+  pa->as_array ();
-+
-+  hb_map_t m;
-+
-+  hb_iter (st);
-+  hb_iter (&st);
-+
-+  + hb_iter (src)
-+  | hb_map (m)
-+  | hb_map (&m)
-+  | hb_filter ()
-+  | hb_filter (st)
-+  | hb_filter (&st)
-+  | hb_filter (hb_bool)
-+  | hb_filter (hb_bool, hb_identity)
-+  | hb_sink (st)
-+  ;
-+
-+  + hb_iter (src)
-+  | hb_sink (hb_array (dst))
-+  ;
-+
-+  + hb_iter (src)
-+  | hb_apply (&st)
-+  ;
-+
-+  + hb_iter (src)
-+  | hb_map ([] (int i) { return 1; })
-+  | hb_reduce ([=] (int acc, int value) { return acc; }, 2)
-+  ;
-+
-+  using map_pair_t = hb_item_type<hb_map_t>;
-+  + hb_iter (m)
-+  | hb_map ([] (map_pair_t p) { return p.first * p.second; })
-+  ;
-+
-+  m.keys ();
-+  using map_key_t = decltype (*m.keys());
-+  + hb_iter (m.keys ())
-+  | hb_filter ([] (map_key_t k) { return k < 42; })
-+  | hb_drain
-+  ;
-+
-+  m.values ();
-+  using map_value_t = decltype (*m.values());
-+  + hb_iter (m.values ())
-+  | hb_filter ([] (map_value_t k) { return k < 42; })
-+  | hb_drain
-+  ;
-+
-+  unsigned int temp1 = 10;
-+  unsigned int temp2 = 0;
-+  hb_map_t *result =
-+  + hb_iter (src)
-+  | hb_map ([&] (int i) -> hb_set_t *
-+	    {
-+	      hb_set_t *set = hb_set_create ();
-+	      for (unsigned int i = 0; i < temp1; ++i)
-+	        hb_set_add (set, i);
-+	      temp1++;
-+	      return set;
-+	    })
-+  | hb_reduce ([&] (hb_map_t *acc, hb_set_t *value) -> hb_map_t *
-+	       {
-+		 hb_map_set (acc, temp2++, hb_set_get_population (value));
-+		 /* This is not a memory managed language, take care! */
-+		 hb_set_destroy (value);
-+		 return acc;
-+	       }, hb_map_create ())
-+  ;
-+  /* The result should be something like 0->10, 1->11, ..., 9->19 */
-+  assert (hb_map_get (result, 9) == 19);
-+
-+  unsigned int temp3 = 0;
-+  + hb_iter(src)
-+  | hb_map([&] (int i) { return ++temp3; })
-+  | hb_reduce([&] (float acc, int value) { return acc + value; }, 0)
-+  ;
-+  hb_map_destroy (result);
-+
-+  + hb_iter (src)
-+  | hb_drain
-+  ;
-+
-+  t << 1;
-+  long vl;
-+  s >> vl;
-+
-+  hb_iota ();
-+  hb_iota (3);
-+  hb_iota (3, 2);
-+  hb_range ();
-+  assert (hb_range (9).len () == 9);
-+  assert (hb_range (2, 9).len () == 7);
-+  assert (hb_range (2, 9, 3).len () == 3);
-+  assert (hb_range (2, 8, 3).len () == 2);
-+  assert (hb_range (2, 7, 3).len () == 2);
-+  assert (hb_range (-2, -9, -3).len () == 3);
-+  assert (hb_range (-2, -8, -3).len () == 2);
-+  assert (hb_range (-2, -7, -3).len () == 2);
- 
-   return 0;
- }
-diff --git a/gfx/harfbuzz/src/test-meta.cc b/gfx/harfbuzz/src/test-meta.cc
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/test-meta.cc
-@@ -0,0 +1,128 @@
-+/*
-+ * Copyright © 2019  Facebook, Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Facebook Author(s): Behdad Esfahbod
-+ */
-+
-+#include "hb.hh"
-+#include "hb-meta.hh"
-+
-+#include <type_traits>
-+
-+int
-+main (int argc, char **argv)
-+{
-+  static_assert (hb_is_convertible (void, void), "");
-+  static_assert (hb_is_convertible (void, const void), "");
-+  static_assert (hb_is_convertible (const void, void), "");
-+
-+  static_assert (hb_is_convertible (int,  int), "");
-+  static_assert (hb_is_convertible (char, int), "");
-+  static_assert (hb_is_convertible (long, int), "");
-+
-+  static_assert (hb_is_convertible (int, int), "");
-+
-+  static_assert (hb_is_convertible (const int, int), "");
-+  static_assert (hb_is_convertible (int, const int), "");
-+  static_assert (hb_is_convertible (const int, const int), "");
-+
-+  static_assert (hb_is_convertible (int&, int), "");
-+  static_assert (!hb_is_convertible (int, int&), "");
-+
-+  static_assert (hb_is_convertible (int, const int&), "");
-+  static_assert (!hb_is_convertible (const int, int&), "");
-+  static_assert (hb_is_convertible (const int, const int&), "");
-+  static_assert (hb_is_convertible (int&, const int), "");
-+  static_assert (hb_is_convertible (const int&, int), "");
-+  static_assert (hb_is_convertible (const int&, const int), "");
-+  static_assert (hb_is_convertible (const int&, const int), "");
-+
-+  struct X {};
-+  struct Y : X {};
-+
-+  static_assert (hb_is_convertible (const X &, const X), "");
-+  static_assert (hb_is_convertible (X &, const X), "");
-+  static_assert (hb_is_convertible (X &, const X &), "");
-+  static_assert (hb_is_convertible (X, const X &), "");
-+  static_assert (hb_is_convertible (const X, const X &), "");
-+  static_assert (!hb_is_convertible (const X, X &), "");
-+  static_assert (!hb_is_convertible (X, X &), "");
-+  static_assert (hb_is_convertible (X &, X &), "");
-+
-+  static_assert (hb_is_convertible (int&, long), "");
-+  static_assert (!hb_is_convertible (int&, long&), "");
-+
-+  static_assert (hb_is_convertible (int *, int *), "");
-+  static_assert (hb_is_convertible (int *, const int *), "");
-+  static_assert (!hb_is_convertible (const int *, int *), "");
-+  static_assert (!hb_is_convertible (int *, long *), "");
-+  static_assert (hb_is_convertible (int *, void *), "");
-+  static_assert (!hb_is_convertible (void *, int *), "");
-+
-+  static_assert (hb_is_base_of (void, void), "");
-+  static_assert (hb_is_base_of (void, int), "");
-+  static_assert (!hb_is_base_of (int, void), "");
-+
-+  static_assert (hb_is_base_of (int, int), "");
-+  static_assert (hb_is_base_of (const int, int), "");
-+  static_assert (hb_is_base_of (int, const int), "");
-+
-+  static_assert (hb_is_base_of (X, X), "");
-+  static_assert (hb_is_base_of (X, Y), "");
-+  static_assert (hb_is_base_of (const X, Y), "");
-+  static_assert (hb_is_base_of (X, const Y), "");
-+  static_assert (!hb_is_base_of (Y, X), "");
-+
-+  static_assert (hb_is_constructible (int), "");
-+  static_assert (hb_is_constructible (int, int), "");
-+  static_assert (hb_is_constructible (int, char), "");
-+  static_assert (hb_is_constructible (int, long), "");
-+  static_assert (!hb_is_constructible (int, X), "");
-+  static_assert (!hb_is_constructible (int, int, int), "");
-+  static_assert (hb_is_constructible (X), "");
-+  static_assert (!hb_is_constructible (X, int), "");
-+  static_assert (hb_is_constructible (X, X), "");
-+  static_assert (!hb_is_constructible (X, X, X), "");
-+  static_assert (hb_is_constructible (X, Y), "");
-+  static_assert (!hb_is_constructible (Y, X), "");
-+
-+  static_assert (hb_is_trivially_default_constructible (X), "");
-+  static_assert (hb_is_trivially_default_constructible (Y), "");
-+  static_assert (hb_is_trivially_copy_constructible (X), "");
-+  static_assert (hb_is_trivially_copy_constructible (Y), "");
-+  static_assert (hb_is_trivially_move_constructible (X), "");
-+  static_assert (hb_is_trivially_move_constructible (Y), "");
-+  static_assert (hb_is_trivially_destructible (Y), "");
-+
-+  static_assert (hb_is_trivially_copyable (int), "");
-+  static_assert (hb_is_trivially_copyable (X), "");
-+  static_assert (hb_is_trivially_copyable (Y), "");
-+
-+  static_assert (hb_is_trivial (int), "");
-+  static_assert (hb_is_trivial (X), "");
-+  static_assert (hb_is_trivial (Y), "");
-+
-+  /* TODO Add more meaningful tests. */
-+
-+  return 0;
-+}
-diff --git a/gfx/harfbuzz/src/test-name-table.cc b/gfx/harfbuzz/src/test-ot-name.cc
-rename from gfx/harfbuzz/src/test-name-table.cc
-rename to gfx/harfbuzz/src/test-ot-name.cc
-diff --git a/gfx/harfbuzz/update.sh b/gfx/harfbuzz/update.sh
---- a/gfx/harfbuzz/update.sh
-+++ b/gfx/harfbuzz/update.sh
-@@ -1,16 +1,16 @@
- #!/bin/sh
- 
- # Script to update the mozilla in-tree copy of the HarfBuzz library.
- # Run this within the /gfx/harfbuzz directory of the source tree.
- 
- MY_TEMP_DIR=`mktemp -d -t harfbuzz_update.XXXXXX` || exit 1
- 
--VERSION=2.4.0
-+VERSION=2.5.1
- 
- git clone https://github.com/harfbuzz/harfbuzz ${MY_TEMP_DIR}/harfbuzz
- git -C ${MY_TEMP_DIR}/harfbuzz checkout ${VERSION}
- 
- COMMIT=$(git -C ${MY_TEMP_DIR}/harfbuzz rev-parse HEAD)
- perl -p -i -e "s/(\d+\.)(\d+\.)(\d+)/${VERSION}/" README-mozilla;
- perl -p -i -e "s/\[commit [0-9a-f]{40}\]/[commit ${COMMIT}]/" README-mozilla;
- 

+ 0 - 13112
frg/work-js/mozilla-release/patches/mozilla-central_480696.patch

@@ -1,13112 +0,0 @@
-# HG changeset patch
-# User Ryan VanderMeulen <ryanvm@gmail.com>
-# Date 1561829376 0
-#      Sat Jun 29 17:29:36 2019 +0000
-# Node ID 4f4de7a970353de0c86ee8cf7470ea00feb0cec9
-# Parent  a120e7b0d3058a947f39618faa2d40ab2863b4a8
-Bug 1560439 - Update HarfBuzz to 2.5.3. r=jfkthame
-
-Differential Revision: https://phabricator.services.mozilla.com/D36282
-
-diff --git a/gfx/harfbuzz/Makefile.am b/gfx/harfbuzz/Makefile.am
---- a/gfx/harfbuzz/Makefile.am
-+++ b/gfx/harfbuzz/Makefile.am
-@@ -8,16 +8,17 @@ SUBDIRS = src util test docs
- 
- EXTRA_DIST = \
- 	autogen.sh \
- 	harfbuzz.doap \
- 	README.md \
- 	README.mingw.md \
- 	README.python.md \
- 	BUILD.md \
-+	CONFIG.md \
- 	RELEASING.md \
- 	TESTING.md \
- 	CMakeLists.txt \
- 	replace-enum-strings.cmake \
- 	mingw-configure.sh \
- 	mingw-ldd.py \
- 	mingw32.sh \
- 	mingw64.sh \
-diff --git a/gfx/harfbuzz/NEWS b/gfx/harfbuzz/NEWS
---- a/gfx/harfbuzz/NEWS
-+++ b/gfx/harfbuzz/NEWS
-@@ -1,8 +1,27 @@
-+Overview of changes leading to 2.5.3
-+Wednesday, June 26, 2019
-+====================================
-+- Fix UCD script data for Unicode 10+ scripts.  This was broken since 2.5.0.
-+- More optimizations for HB_TINY.
-+
-+
-+Overview of changes leading to 2.5.2
-+Thursday, June 20, 2019
-+====================================
-+- More hb-config.hh facilities to shrink library size, namely when built as
-+  HB_TINY.
-+- New documentation of custom configurations in CONFIG.md.
-+- Fix build on gcc 4.8.  That's supported again.
-+- Universal Shaping Engine improvements thanks to David Corbett.
-+- API Changes: Undeprecate some horizontal-kerning API and re-enable in hb-ft,
-+  such that Type1 fonts will continue kerning.
-+
-+
- Overview of changes leading to 2.5.1
- Friday, May 31, 2019
- ====================================
- - Fix build with various versions of Visual Studio.
- - Improved documentation, thanks to Nathan Willis.
- - Bugfix in subsetting glyf table.
- - Improved scripts for cross-compiling for Windows using mingw.
- - Rename HB_MATH_GLYPH_PART_FLAG_EXTENDER to HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER.
-diff --git a/gfx/harfbuzz/README-mozilla b/gfx/harfbuzz/README-mozilla
---- a/gfx/harfbuzz/README-mozilla
-+++ b/gfx/harfbuzz/README-mozilla
-@@ -1,12 +1,12 @@
- This directory contains the HarfBuzz source from the upstream repo:
- https://github.com/harfbuzz/harfbuzz
- 
--Current version: 2.5.1 [commit 93c455567fe3d92a7efe65bf0e9ac2af794e2c4f]
-+Current version: 2.5.3 [commit b14e413fae8f14b75c5956e9b38e413c878ded0c]
- 
- UPDATING:
- 
- Our in-tree copy of HarfBuzz does not depend on any generated files from the
- upstream build system. Therefore, it should be sufficient to simply overwrite
- the in-tree files one the updated ones from upstream to perform updates.
- 
- To simplify this, the in-tree copy can be updated by running
-diff --git a/gfx/harfbuzz/README.md b/gfx/harfbuzz/README.md
---- a/gfx/harfbuzz/README.md
-+++ b/gfx/harfbuzz/README.md
-@@ -12,11 +12,13 @@ This is HarfBuzz, a text shaping library
- For bug reports, mailing list, and other information please visit:
- 
-   http://harfbuzz.org/
- 
- For license information, see [COPYING](COPYING).
- 
- For build information, see [BUILD.md](BUILD.md).
- 
-+For custom configurations, see [CONFIG.md](CONFIG.md).
-+
- For test execution, see [TESTING.md](TESTING.md).
- 
- Documentation: https://harfbuzz.github.io
-diff --git a/gfx/harfbuzz/configure.ac b/gfx/harfbuzz/configure.ac
---- a/gfx/harfbuzz/configure.ac
-+++ b/gfx/harfbuzz/configure.ac
-@@ -1,11 +1,11 @@
- AC_PREREQ([2.64])
- AC_INIT([HarfBuzz],
--        [2.5.1],
-+        [2.5.3],
-         [https://github.com/harfbuzz/harfbuzz/issues/new],
-         [harfbuzz],
-         [http://harfbuzz.org/])
- 
- AC_CONFIG_MACRO_DIR([m4])
- AC_CONFIG_SRCDIR([src/harfbuzz.pc.in])
- AC_CONFIG_HEADERS([config.h])
- 
-@@ -72,23 +72,17 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]
- 	if test "x$enable_gtk_doc" = xyes; then
- 		have_gtk_doc=true
- 	fi
- ], [
- 	AM_CONDITIONAL([ENABLE_GTK_DOC], false)
- ])
- 
- # Functions and headers
--AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l posix_memalign)
--
--save_libs="$LIBS"
--LIBS="$LIBS -lm"
--AC_CHECK_FUNCS([round], ,[AC_CHECK_DECLS([round], , ,[#include <math.h>])])
--LIBS="$save_libs"
--
-+AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l)
- AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h stdbool.h)
- 
- # Compiler flags
- AC_CANONICAL_HOST
- AC_CHECK_ALIGNOF([struct{char;}])
- if test "x$GCC" = "xyes"; then
- 
- 	# Make symbols link locally
-@@ -137,24 +131,16 @@ have_pthread=false
- AX_PTHREAD([have_pthread=true])
- if $have_pthread; then
- 	AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads])
- fi
- AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
- 
- dnl ==========================================================================
- 
--have_fallback=true
--if $have_fallback; then
--	AC_DEFINE(HAVE_FALLBACK, 1, [Have simple TrueType Layout backend])
--fi
--AM_CONDITIONAL(HAVE_FALLBACK, $have_fallback)
--
--dnl ===========================================================================
--
- AC_ARG_WITH(glib,
- 	[AS_HELP_STRING([--with-glib=@<:@yes/no/auto@:>@],
- 			[Use glib @<:@default=auto@:>@])],,
- 	[with_glib=auto])
- have_glib=false
- GLIB_DEPS="glib-2.0 >= 2.19.1"
- AC_SUBST(GLIB_DEPS)
- if test "x$with_glib" = "xyes" -o "x$with_glib" = "xauto"; then
-diff --git a/gfx/harfbuzz/src/Makefile.am b/gfx/harfbuzz/src/Makefile.am
---- a/gfx/harfbuzz/src/Makefile.am
-+++ b/gfx/harfbuzz/src/Makefile.am
-@@ -23,20 +23,16 @@ include Makefile.sources
- HBCFLAGS =
- HBLIBS =
- HBNONPCLIBS =
- HBDEPS =
- HBSOURCES =  $(HB_BASE_sources)
- HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
- HBHEADERS = $(HB_BASE_headers)
- 
--if HAVE_FALLBACK
--HBSOURCES += $(HB_FALLBACK_sources)
--endif
--
- if HAVE_PTHREAD
- HBCFLAGS += $(PTHREAD_CFLAGS)
- HBNONPCLIBS += $(PTHREAD_LIBS)
- endif
- 
- if HAVE_GLIB
- HBCFLAGS += $(GLIB_CFLAGS)
- HBLIBS   += $(GLIB_LIBS)
-@@ -423,16 +419,17 @@ HarfBuzz_0_0_gir_CFLAGS = \
- 	-DHB_H \
- 	-DHB_H_IN \
- 	-DHB_OT_H \
- 	-DHB_OT_H_IN \
- 	-DHB_AAT_H \
- 	-DHB_AAT_H_IN \
- 	-DHB_GOBJECT_H \
- 	-DHB_GOBJECT_H_IN \
-+	-DHAVE_GOBJECT \
- 	-DHB_EXTERN= \
- 	$(NULL)
- HarfBuzz_0_0_gir_LIBS = \
- 	libharfbuzz.la \
- 	libharfbuzz-gobject.la \
- 	$(NULL)
- HarfBuzz_0_0_gir_FILES = \
- 	$(HBHEADERS) \
-diff --git a/gfx/harfbuzz/src/Makefile.sources b/gfx/harfbuzz/src/Makefile.sources
---- a/gfx/harfbuzz/src/Makefile.sources
-+++ b/gfx/harfbuzz/src/Makefile.sources
-@@ -31,23 +31,25 @@ HB_BASE_sources = \
- 	hb-cff1-interp-cs.hh \
- 	hb-cff2-interp-cs.hh \
- 	hb-common.cc \
- 	hb-config.hh \
- 	hb-debug.hh \
- 	hb-dispatch.hh \
- 	hb-face.cc \
- 	hb-face.hh \
-+	hb-fallback-shape.cc \
- 	hb-font.cc \
- 	hb-font.hh \
- 	hb-iter.hh \
- 	hb-kern.hh \
- 	hb-machinery.hh \
- 	hb-map.cc \
- 	hb-map.hh \
-+	hb-bimap.hh \
- 	hb-meta.hh \
- 	hb-mutex.hh \
- 	hb-null.hh \
- 	hb-object.hh \
- 	hb-open-file.hh \
- 	hb-open-type.hh \
- 	hb-ot-cff-common.hh \
- 	hb-ot-cff1-table.cc \
-@@ -58,16 +60,17 @@ HB_BASE_sources = \
- 	hb-ot-color-cbdt-table.hh \
- 	hb-ot-color-colr-table.hh \
- 	hb-ot-color-cpal-table.hh \
- 	hb-ot-color-sbix-table.hh \
- 	hb-ot-color-svg-table.hh \
- 	hb-ot-color.cc \
- 	hb-ot-face.cc \
- 	hb-ot-face.hh \
-+	hb-ot-face-table-list.hh \
- 	hb-ot-font.cc \
- 	hb-ot-gasp-table.hh \
- 	hb-ot-glyf-table.hh \
- 	hb-ot-hdmx-table.hh \
- 	hb-ot-head-table.hh \
- 	hb-ot-hhea-table.hh \
- 	hb-ot-hmtx-table.hh \
- 	hb-ot-kern-table.hh \
-@@ -195,20 +198,16 @@ HB_BASE_headers = \
- 	hb-set.h \
- 	hb-shape-plan.h \
- 	hb-shape.h \
- 	hb-unicode.h \
- 	hb-version.h \
- 	hb.h \
- 	$(NULL)
- 
--HB_FALLBACK_sources = \
--	hb-fallback-shape.cc	\
--	$(NULL)
--
- # Optional Sources and Headers with external deps
- 
- HB_FT_sources = hb-ft.cc
- HB_FT_headers = hb-ft.h
- 
- HB_GLIB_sources = hb-glib.cc
- HB_GLIB_headers = hb-glib.h
- 
-diff --git a/gfx/harfbuzz/src/gen-ucd-table.py b/gfx/harfbuzz/src/gen-ucd-table.py
---- a/gfx/harfbuzz/src/gen-ucd-table.py
-+++ b/gfx/harfbuzz/src/gen-ucd-table.py
-@@ -1,123 +1,162 @@
- #!/usr/bin/env python
- 
- from __future__ import print_function, division, absolute_import
- 
- import io, os.path, sys, re
-+import logging
-+logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO)
- 
- if len (sys.argv) != 2:
--	print("usage: ./gen-ucd-table ucd.nonunihan.grouped.xml", file=sys.stderr)
-+	print("usage: ./gen-ucd-table ucd.nounihan.grouped.xml", file=sys.stderr)
- 	sys.exit(1)
- 
--
- # https://github.com/harfbuzz/packtab
- import packTab
- import packTab.ucdxml
- 
-+logging.info('Loading UCDXML...')
- ucdxml = packTab.ucdxml.load_ucdxml(sys.argv[1])
- ucd = packTab.ucdxml.ucdxml_get_repertoire(ucdxml)
- 
-+logging.info('Preparing data tables...')
- 
- gc = [u['gc'] for u in ucd]
- ccc = [int(u['ccc']) for u in ucd]
- bmg = [int(v, 16) - int(u) if v else 0 for u,v in enumerate(u['bmg'] for u in ucd)]
- #gc_ccc_non0 = set((cat,klass) for cat,klass in zip(gc,ccc) if klass)
- #gc_bmg_non0 = set((cat,mirr) for cat,mirr in zip(gc, bmg) if mirr)
- 
- sc = [u['sc'] for u in ucd]
- 
- dm = {i:tuple(int(v, 16) for v in u['dm'].split()) for i,u in enumerate(ucd)
-       if u['dm'] != '#' and u['dt'] == 'can' and not (0xAC00 <= i < 0xAC00+11172)}
- ce = {i for i,u in enumerate(ucd) if u['Comp_Ex'] == 'Y'}
- 
- assert not any(v for v in dm.values() if len(v) not in (1,2))
- dm1 = sorted(set(v for v in dm.values() if len(v) == 1))
--dm1_array = ['0x%04Xu' % v for v in dm1]
-+assert all((v[0] >> 16) in (0,2) for v in dm1)
-+dm1_p0_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 0]
-+dm1_p2_array = ['0x%04Xu' % (v[0] & 0xFFFF) for v in dm1 if (v[0] >> 16) == 2]
- dm1_order = {v:i+1 for i,v in enumerate(dm1)}
--dm2 = sorted((v, i) for i,v in dm.items() if len(v) == 2)
--dm2 = [("HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" %
--        (v+(i if i not in ce and not ccc[i] else 0,)), v)
--       for v,i in dm2]
--dm2_array = [s for s,v in dm2]
--l = 1 + len(dm1_array)
-+
-+dm2 = sorted((v+(i if i not in ce and not ccc[i] else 0,), v)
-+             for i,v in dm.items() if len(v) == 2)
-+
-+filt = lambda v: ((v[0] & 0xFFFFF800) == 0x0000 and
-+                  (v[1] & 0xFFFFFF80) == 0x0300 and
-+                  (v[2] & 0xFFF0C000) == 0x0000)
-+dm2_u32_array = [v for v in dm2 if filt(v[0])]
-+dm2_u64_array = [v for v in dm2 if not filt(v[0])]
-+assert dm2_u32_array + dm2_u64_array == dm2
-+dm2_u32_array = ["HB_CODEPOINT_ENCODE3_11_7_14 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % v[0] for v in dm2_u32_array]
-+dm2_u64_array = ["HB_CODEPOINT_ENCODE3 (0x%04Xu, 0x%04Xu, 0x%04Xu)" % v[0] for v in dm2_u64_array]
-+
-+l = 1 + len(dm1_p0_array) + len(dm1_p2_array)
- dm2_order = {v[1]:i+l for i,v in enumerate(dm2)}
-+
- dm_order = {None: 0}
- dm_order.update(dm1_order)
- dm_order.update(dm2_order)
- 
--gc_order = packTab.AutoMapping()
--for _ in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
--          'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
--          'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',):
--    gc_order[_]
-+gc_order = dict()
-+for i,v in enumerate(('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Ll', 'Lm', 'Lo', 'Lt', 'Lu',
-+                      'Mc', 'Me', 'Mn', 'Nd', 'Nl', 'No', 'Pc', 'Pd', 'Pe', 'Pf',
-+                      'Pi', 'Po', 'Ps', 'Sc', 'Sk', 'Sm', 'So', 'Zl', 'Zp', 'Zs',)):
-+    gc_order[i] = v
-+    gc_order[v] = i
- 
--sc_order = packTab.AutoMapping()
-+sc_order = dict()
- sc_array = []
--sc_re = re.compile(" (HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
-+sc_re = re.compile(r"\b(HB_SCRIPT_[_A-Z]*).*HB_TAG [(]'(.)','(.)','(.)','(.)'[)]")
- for line in open('hb-common.h'):
-     m = sc_re.search (line)
-     if not m: continue
-     name = m.group(1)
-     tag = ''.join(m.group(i) for i in range(2, 6))
--    i = sc_order[tag]
--    assert i == len(sc_array)
-+    i = len(sc_array)
-+    sc_order[tag] = i
-+    sc_order[i] = tag
-     sc_array.append(name)
- 
--# TODO Currently if gc_order or sc_order do not capture all values, we get in
--# trouble because they silently add new values.  We should be able to "freeze"
--# them, or just do the mapping ourselves.
--
- DEFAULT = 1
- COMPACT = 3
-+SLOPPY  = 5
- 
- 
-+logging.info('Generating output...')
- print("/* == Start of generated table == */")
- print("/*")
- print(" * The following table is generated by running:")
- print(" *")
--print(" *   ./gen-ucd-table.py ucd.nonunihan.grouped.xml")
-+print(" *   ./gen-ucd-table.py ucd.nounihan.grouped.xml")
- print(" *")
- print(" * on file with this description:", ucdxml.description)
- print(" */")
- print()
- print("#ifndef HB_UCD_TABLE_HH")
- print("#define HB_UCD_TABLE_HH")
- print()
--
--print()
- print('#include "hb.hh"')
- print()
- 
- code = packTab.Code('_hb_ucd')
- sc_array, _ = code.addArray('hb_script_t', 'sc_map', sc_array)
--dm1_array, _ = code.addArray('hb_codepoint_t', 'dm1_map', dm1_array)
--dm2_array, _ = code.addArray('uint64_t', 'dm2_map', dm2_array)
-+dm1_p0_array, _ = code.addArray('uint16_t', 'dm1_p0_map', dm1_p0_array)
-+dm1_p2_array, _ = code.addArray('uint16_t', 'dm1_p2_map', dm1_p2_array)
-+dm2_u32_array, _ = code.addArray('uint32_t', 'dm2_u32_map', dm2_u32_array)
-+dm2_u64_array, _ = code.addArray('uint64_t', 'dm2_u64_map', dm2_u64_array)
- code.print_c(linkage='static inline')
- 
--for compression in (DEFAULT, COMPACT):
-+datasets = [
-+    ('gc', gc, 'Cn', gc_order),
-+    ('ccc', ccc, 0, None),
-+    ('bmg', bmg, 0, None),
-+    ('sc', sc, 'Zzzz', sc_order),
-+    ('dm', dm, None, dm_order),
-+]
-+
-+for compression in (DEFAULT, COMPACT, SLOPPY):
-+    logging.info('  Compression=%d:' % compression)
-     print()
-     if compression == DEFAULT:
-         print('#ifndef HB_OPTIMIZE_SIZE')
-+    elif compression == COMPACT:
-+        print('#elif !defined(HB_NO_UCD_UNASSIGNED)')
-     else:
-         print('#else')
-     print()
- 
-+    if compression == SLOPPY:
-+        for i in range(len(gc)):
-+            if (i % 128) and gc[i] == 'Cn':
-+                gc[i] = gc[i - 1]
-+        for i in range(len(gc) - 2, -1, -1):
-+            if ((i + 1) % 128) and gc[i] == 'Cn':
-+                gc[i] = gc[i + 1]
-+        for i in range(len(sc)):
-+            if (i % 128) and sc[i] == 'Zzzz':
-+                sc[i] = sc[i - 1]
-+        for i in range(len(sc) - 2, -1, -1):
-+            if ((i + 1) % 128) and sc[i] == 'Zzzz':
-+                sc[i] = sc[i + 1]
-+
-+
-     code = packTab.Code('_hb_ucd')
- 
--    packTab.pack_table(gc, 'Cn', mapping=gc_order, compression=compression).genCode(code, 'gc')
--    packTab.pack_table(ccc, 0, compression=compression).genCode(code, 'ccc')
--    packTab.pack_table(bmg, 0, compression=compression).genCode(code, 'bmg')
--    packTab.pack_table(sc, 'Zzzz', mapping=sc_order, compression=compression).genCode(code, 'sc')
--    packTab.pack_table(dm, None, mapping=dm_order, compression=compression).genCode(code, 'dm')
-+    for name,data,default,mapping in datasets:
-+        sol = packTab.pack_table(data, default, mapping=mapping, compression=compression)
-+        logging.info('      Dataset=%-8s FullCost=%d' % (name, sol.fullCost))
-+        sol.genCode(code, name)
- 
-     code.print_c(linkage='static inline')
- 
-+    print()
- 
--    if compression != DEFAULT:
--        print()
--        print('#endif')
--    print()
-+print('#endif')
-+print()
- 
- print()
- print("#endif /* HB_UCD_TABLE_HH */")
- print()
- print("/* == End of generated table == */")
-+logging.info('Done.')
-diff --git a/gfx/harfbuzz/src/hb-aat-layout.cc b/gfx/harfbuzz/src/hb-aat-layout.cc
---- a/gfx/harfbuzz/src/hb-aat-layout.cc
-+++ b/gfx/harfbuzz/src/hb-aat-layout.cc
-@@ -20,31 +20,69 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
--#include "hb-open-type.hh"
-+#include "hb.hh"
- 
--#include "hb-ot-face.hh"
- #include "hb-aat-layout.hh"
- #include "hb-aat-fdsc-table.hh" // Just so we compile it; unused otherwise.
- #include "hb-aat-layout-ankr-table.hh"
- #include "hb-aat-layout-bsln-table.hh" // Just so we compile it; unused otherwise.
- #include "hb-aat-layout-feat-table.hh"
- #include "hb-aat-layout-just-table.hh" // Just so we compile it; unused otherwise.
- #include "hb-aat-layout-kerx-table.hh"
- #include "hb-aat-layout-morx-table.hh"
- #include "hb-aat-layout-trak-table.hh"
- #include "hb-aat-ltag-table.hh"
- 
- 
-+/*
-+ * hb_aat_apply_context_t
-+ */
-+
-+/* Note: This context is used for kerning, even without AAT, hence the condition. */
-+#if !defined(HB_NO_AAT) || !defined(HB_NO_OT_KERN)
-+
-+AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
-+						     hb_font_t *font_,
-+						     hb_buffer_t *buffer_,
-+						     hb_blob_t *blob) :
-+						       plan (plan_),
-+						       font (font_),
-+						       face (font->face),
-+						       buffer (buffer_),
-+						       sanitizer (),
-+						       ankr_table (&Null(AAT::ankr)),
-+						       lookup_index (0),
-+						       debug_depth (0)
-+{
-+  sanitizer.init (blob);
-+  sanitizer.set_num_glyphs (face->get_num_glyphs ());
-+  sanitizer.start_processing ();
-+  sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
-+}
-+
-+AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t ()
-+{ sanitizer.end_processing (); }
-+
-+void
-+AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
-+{ ankr_table = ankr_table_; }
-+
-+#endif
-+
-+
-+#ifndef HB_NO_AAT
-+
-+
- /**
-  * SECTION:hb-aat-layout
-  * @title: hb-aat-layout
-  * @short_description: Apple Advanced Typography Layout
-  * @include: hb-aat.h
-  *
-  * Functions for querying OpenType Layout features in the font face.
-  **/
-@@ -130,74 +168,33 @@ static const hb_aat_feature_mapping_t fe
-   {HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING,            HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT,          (hb_aat_layout_feature_selector_t) 7},
-   {HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON,   HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
-   {HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS,      HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON,                HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
- };
- 
- const hb_aat_feature_mapping_t *
- hb_aat_layout_find_feature_mapping (hb_tag_t tag)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return nullptr;
--#endif
--
--  return (const hb_aat_feature_mapping_t *) bsearch (&tag,
--						     feature_mappings,
--						     ARRAY_LENGTH (feature_mappings),
--						     sizeof (feature_mappings[0]),
--						     hb_aat_feature_mapping_t::cmp);
-+  return (const hb_aat_feature_mapping_t *) hb_bsearch (&tag,
-+							feature_mappings,
-+							ARRAY_LENGTH (feature_mappings),
-+							sizeof (feature_mappings[0]),
-+							hb_aat_feature_mapping_t::cmp);
- }
- 
- 
- /*
-- * hb_aat_apply_context_t
-- */
--
--/* Note: This context is used for kerning, even without AAT. */
--
--AAT::hb_aat_apply_context_t::hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
--						     hb_font_t *font_,
--						     hb_buffer_t *buffer_,
--						     hb_blob_t *blob) :
--						       plan (plan_),
--						       font (font_),
--						       face (font->face),
--						       buffer (buffer_),
--						       sanitizer (),
--						       ankr_table (&Null(AAT::ankr)),
--						       lookup_index (0),
--						       debug_depth (0)
--{
--  sanitizer.init (blob);
--  sanitizer.set_num_glyphs (face->get_num_glyphs ());
--  sanitizer.start_processing ();
--  sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
--}
--
--AAT::hb_aat_apply_context_t::~hb_aat_apply_context_t ()
--{ sanitizer.end_processing (); }
--
--void
--AAT::hb_aat_apply_context_t::set_ankr_table (const AAT::ankr *ankr_table_)
--{ ankr_table = ankr_table_; }
--
--
--/*
-  * mort/morx/kerx/trak
-  */
- 
- 
- void
- hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
- 			   hb_aat_map_t *map)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return;
--#endif
--
-   const AAT::morx& morx = *mapper->face->table.morx;
-   if (morx.has_data ())
-   {
-     morx.compile_flags (mapper, map);
-     return;
-   }
- 
-   const AAT::mort& mort = *mapper->face->table.mort;
-@@ -214,33 +211,25 @@ hb_aat_layout_compile_map (const hb_aat_
-  * @face:
-  *
-  * Returns:
-  * Since: 2.3.0
-  */
- hb_bool_t
- hb_aat_layout_has_substitution (hb_face_t *face)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return false;
--#endif
--
-   return face->table.morx->has_data () ||
- 	 face->table.mort->has_data ();
- }
- 
- void
- hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
- 			  hb_font_t *font,
- 			  hb_buffer_t *buffer)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return;
--#endif
--
-   hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
-   const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
-   if (morx.has_data ())
-   {
-     AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
-     morx.apply (&c);
-     return;
-   }
-@@ -253,20 +242,16 @@ hb_aat_layout_substitute (const hb_ot_sh
-     mort.apply (&c);
-     return;
-   }
- }
- 
- void
- hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return;
--#endif
--
-   unsigned int count = buffer->len;
-   hb_glyph_info_t *info = buffer->info;
-   hb_glyph_position_t *pos = buffer->pos;
-   for (unsigned int i = 0; i < count; i++)
-     if (unlikely (info[i].codepoint == AAT::DELETED_GLYPH))
-       pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
- }
- 
-@@ -274,49 +259,37 @@ static bool
- is_deleted_glyph (const hb_glyph_info_t *info)
- {
-   return info->codepoint == AAT::DELETED_GLYPH;
- }
- 
- void
- hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return;
--#endif
--
-   hb_ot_layout_delete_glyphs_inplace (buffer, is_deleted_glyph);
- }
- 
- /*
-  * hb_aat_layout_has_positioning:
-  * @face:
-  *
-  * Returns:
-  * Since: 2.3.0
-  */
- hb_bool_t
- hb_aat_layout_has_positioning (hb_face_t *face)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return false;
--#endif
--
-   return face->table.kerx->has_data ();
- }
- 
- void
- hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
- 			hb_font_t *font,
- 			hb_buffer_t *buffer)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return;
--#endif
--
-   hb_blob_t *kerx_blob = font->face->table.kerx.get_blob ();
-   const AAT::kerx& kerx = *kerx_blob->as<AAT::kerx> ();
- 
-   AAT::hb_aat_apply_context_t c (plan, font, buffer, kerx_blob);
-   c.set_ankr_table (font->face->table.ankr.get ());
-   kerx.apply (&c);
- }
- 
-@@ -326,32 +299,24 @@ hb_aat_layout_position (const hb_ot_shap
-  * @face:
-  *
-  * Returns:
-  * Since: 2.3.0
-  */
- hb_bool_t
- hb_aat_layout_has_tracking (hb_face_t *face)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return false;
--#endif
--
-   return face->table.trak->has_data ();
- }
- 
- void
- hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
- 		     hb_font_t *font,
- 		     hb_buffer_t *buffer)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return;
--#endif
--
-   const AAT::trak& trak = *font->face->table.trak;
- 
-   AAT::hb_aat_apply_context_t c (plan, font, buffer);
-   trak.apply (&c);
- }
- 
- /**
-  * hb_aat_layout_get_feature_types:
-@@ -365,42 +330,32 @@ hb_aat_layout_track (const hb_ot_shape_p
-  * Since: 2.2.0
-  */
- unsigned int
- hb_aat_layout_get_feature_types (hb_face_t                    *face,
- 				 unsigned int                  start_offset,
- 				 unsigned int                 *feature_count, /* IN/OUT.  May be NULL. */
- 				 hb_aat_layout_feature_type_t *features       /* OUT.     May be NULL. */)
- {
--#ifdef HB_NO_SHAPE_AAT
--  if (feature_count)
--    *feature_count = 0;
--  return 0;
--#endif
--
-   return face->table.feat->get_feature_types (start_offset, feature_count, features);
- }
- 
- /**
-  * hb_aat_layout_feature_type_get_name_id:
-  * @face: a face object
-  * @feature_type: feature id
-  *
-  * Return value: Name ID index
-  *
-  * Since: 2.2.0
-  */
- hb_ot_name_id_t
- hb_aat_layout_feature_type_get_name_id (hb_face_t                    *face,
- 					hb_aat_layout_feature_type_t  feature_type)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return HB_OT_NAME_ID_INVALID;
--#endif
--
-   return face->table.feat->get_feature_name_id (feature_type);
- }
- 
- /**
-  * hb_aat_layout_feature_type_get_selectors:
-  * @face:    a face object
-  * @feature_type: feature id
-  * @start_offset:    iteration's start offset
-@@ -419,16 +374,13 @@ hb_aat_layout_feature_type_get_name_id (
- unsigned int
- hb_aat_layout_feature_type_get_selector_infos (hb_face_t                             *face,
- 					       hb_aat_layout_feature_type_t           feature_type,
- 					       unsigned int                           start_offset,
- 					       unsigned int                          *selector_count, /* IN/OUT.  May be NULL. */
- 					       hb_aat_layout_feature_selector_info_t *selectors,      /* OUT.     May be NULL. */
- 					       unsigned int                          *default_index   /* OUT.     May be NULL. */)
- {
--#ifdef HB_NO_SHAPE_AAT
--  if (selector_count)
--    *selector_count = 0;
--  return 0;
--#endif
--
-   return face->table.feat->get_selector_infos (feature_type, start_offset, selector_count, selectors, default_index);
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-aat-layout.hh b/gfx/harfbuzz/src/hb-aat-layout.hh
---- a/gfx/harfbuzz/src/hb-aat-layout.hh
-+++ b/gfx/harfbuzz/src/hb-aat-layout.hh
-@@ -73,17 +73,9 @@ hb_aat_layout_position (const hb_ot_shap
- 			hb_buffer_t *buffer);
- 
- HB_INTERNAL void
- hb_aat_layout_track (const hb_ot_shape_plan_t *plan,
- 		     hb_font_t *font,
- 		     hb_buffer_t *buffer);
- 
- 
--inline hb_language_t
--_hb_aat_language_get (hb_face_t *face,
--                      unsigned int i)
--{
--  return face->table.ltag->get_language (i);
--}
--
--
- #endif /* HB_AAT_LAYOUT_HH */
-diff --git a/gfx/harfbuzz/src/hb-aat-map.cc b/gfx/harfbuzz/src/hb-aat-map.cc
---- a/gfx/harfbuzz/src/hb-aat-map.cc
-+++ b/gfx/harfbuzz/src/hb-aat-map.cc
-@@ -21,28 +21,28 @@
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Red Hat Author(s): Behdad Esfahbod
-  * Google Author(s): Behdad Esfahbod
-  */
- 
-+#include "hb.hh"
-+
-+#ifndef HB_NO_SHAPE_AAT
-+
- #include "hb-aat-map.hh"
- 
- #include "hb-aat-layout.hh"
- 
- 
- void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
- 					unsigned int value)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return;
--#endif
--
-   if (tag == HB_TAG ('a','a','l','t'))
-   {
-     feature_info_t *info = features.push();
-     info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
-     info->setting = (hb_aat_layout_feature_selector_t) value;
-     return;
-   }
- 
-@@ -52,25 +52,24 @@ void hb_aat_map_builder_t::add_feature (
-   feature_info_t *info = features.push();
-   info->type = mapping->aatFeatureType;
-   info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
- }
- 
- void
- hb_aat_map_builder_t::compile (hb_aat_map_t  &m)
- {
--#ifdef HB_NO_SHAPE_AAT
--  return;
--#endif
--
-   /* Sort features and merge duplicates */
-   if (features.length)
-   {
-     features.qsort ();
-     unsigned int j = 0;
-     for (unsigned int i = 1; i < features.length; i++)
-       if (features[i].type != features[j].type)
- 	features[++j] = features[i];
-     features.shrink (j + 1);
-   }
- 
-   hb_aat_layout_compile_map (this, &m);
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-algs.hh b/gfx/harfbuzz/src/hb-algs.hh
---- a/gfx/harfbuzz/src/hb-algs.hh
-+++ b/gfx/harfbuzz/src/hb-algs.hh
-@@ -1,11 +1,11 @@
- /*
-  * Copyright © 2017  Google, Inc.
-- * Copyright © 2019  Google, Inc.
-+ * Copyright © 2019  Facebook, Inc.
-  *
-  *  This is part of HarfBuzz, a text shaping library.
-  *
-  * Permission is hereby granted, without written agreement and without
-  * license or royalty fees, to use, copy, modify, and distribute this
-  * software and its documentation for any purpose, provided that the
-  * above copyright notice and the following two paragraphs appear in
-  * all copies of this software.
-@@ -36,16 +36,21 @@
- 
- /* Encodes three unsigned integers in one 64-bit number.  If the inputs have more than 21 bits,
-  * values will be truncated / overlap, and might not decode exactly. */
- #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z))
- #define HB_CODEPOINT_DECODE3_1(v) ((hb_codepoint_t) ((v) >> 42))
- #define HB_CODEPOINT_DECODE3_2(v) ((hb_codepoint_t) ((v) >> 21) & 0x1FFFFFu)
- #define HB_CODEPOINT_DECODE3_3(v) ((hb_codepoint_t) (v) & 0x1FFFFFu)
- 
-+/* Custom encoding used by hb-ucd. */
-+#define HB_CODEPOINT_ENCODE3_11_7_14(x,y,z) (((uint32_t) ((x) & 0x07FFu) << 21) | (((uint32_t) (y) & 0x007Fu) << 14) | (uint32_t) ((z) & 0x3FFFu))
-+#define HB_CODEPOINT_DECODE3_11_7_14_1(v) ((hb_codepoint_t) ((v) >> 21))
-+#define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300)
-+#define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu)
- 
- struct
- {
-   /* Note.  This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */
-   template <typename T> auto
-   operator () (T&& v) const HB_AUTO_RETURN ( hb_forward<T> (v) )
- }
- HB_FUNCOBJ (hb_identity);
-@@ -162,29 +167,47 @@ struct hb_partial_t
-   private:
-   hb_reference_wrapper<Appl> a;
-   V v;
- };
- template <unsigned Pos=1, typename Appl, typename V>
- auto hb_partial (Appl&& a, V&& v) HB_AUTO_RETURN
- (( hb_partial_t<Pos, Appl, V> (a, v) ))
- 
--/* The following hacky replacement version is to make Visual Stuiod build:. */ \
-+/* The following, HB_PARTIALIZE, macro uses a particular corner-case
-+ * of C++11 that is not particularly well-supported by all compilers.
-+ * What's happening is that it's using "this" in a trailing return-type
-+ * via decltype().  Broken compilers deduce the type of "this" pointer
-+ * in that context differently from what it resolves to in the body
-+ * of the function.
-+ *
-+ * One probable cause of this is that at the time of trailing return
-+ * type declaration, "this" points to an incomplete type, whereas in
-+ * the function body the type is complete.  That doesn't justify the
-+ * error in any way, but is probably what's happening.
-+ *
-+ * In the case of MSVC, we get around this by using C++14 "decltype(auto)"
-+ * which deduces the type from the actual return statement.  For gcc 4.8
-+ * we use "+this" instead of "this" which produces an rvalue that seems
-+ * to be deduced as the same type with this particular compiler, and seem
-+ * to be fine as default code path as well.
-+ */
-+#ifdef _MSC_VER
- /* https://github.com/harfbuzz/harfbuzz/issues/1730 */ \
--#ifdef _MSC_VER
- #define HB_PARTIALIZE(Pos) \
-   template <typename _T> \
-   decltype(auto) operator () (_T&& _v) const \
-   { return hb_partial<Pos> (this, hb_forward<_T> (_v)); } \
-   static_assert (true, "")
- #else
-+/* https://github.com/harfbuzz/harfbuzz/issues/1724 */
- #define HB_PARTIALIZE(Pos) \
-   template <typename _T> \
-   auto operator () (_T&& _v) const HB_AUTO_RETURN \
--  (hb_partial<Pos> (this, hb_forward<_T> (_v))) \
-+  (hb_partial<Pos> (+this, hb_forward<_T> (_v))) \
-   static_assert (true, "")
- #endif
- 
- 
- struct
- {
-   private:
- 
-@@ -395,17 +418,17 @@ hb_bit_storage (T v)
- 
-   if (sizeof (T) <= sizeof (unsigned long))
-     return sizeof (unsigned long) * 8 - __builtin_clzl (v);
- 
-   if (sizeof (T) <= sizeof (unsigned long long))
-     return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
- #endif
- 
--#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
-   if (sizeof (T) <= sizeof (unsigned int))
-   {
-     unsigned long where;
-     _BitScanReverse (&where, v);
-     return 1 + where;
-   }
- # if defined(_WIN64)
-   if (sizeof (T) <= 8)
-@@ -469,17 +492,17 @@ hb_ctz (T v)
- 
-   if (sizeof (T) <= sizeof (unsigned long))
-     return __builtin_ctzl (v);
- 
-   if (sizeof (T) <= sizeof (unsigned long long))
-     return __builtin_ctzll (v);
- #endif
- 
--#if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-+#if (defined(_MSC_VER) && _MSC_VER >= 1500) || (defined(__MINGW32__) && (__GNUC__ < 4))
-   if (sizeof (T) <= sizeof (unsigned int))
-   {
-     unsigned long where;
-     _BitScanForward (&where, v);
-     return where;
-   }
- # if defined(_WIN64)
-   if (sizeof (T) <= 8)
-@@ -598,171 +621,248 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, 
- {
-   return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
- }
- 
- 
- /*
-  * Sort and search.
-  */
--
-+template <typename ...Ts>
- static inline void *
- hb_bsearch (const void *key, const void *base,
- 	    size_t nmemb, size_t size,
--	    int (*compar)(const void *_key, const void *_item))
--{
--  int min = 0, max = (int) nmemb - 1;
--  while (min <= max)
--  {
--    int mid = (min + max) / 2;
--    const void *p = (const void *) (((const char *) base) + (mid * size));
--    int c = compar (key, p);
--    if (c < 0)
--      max = mid - 1;
--    else if (c > 0)
--      min = mid + 1;
--    else
--      return (void *) p;
--  }
--  return nullptr;
--}
--
--static inline void *
--hb_bsearch_r (const void *key, const void *base,
--	      size_t nmemb, size_t size,
--	      int (*compar)(const void *_key, const void *_item, void *_arg),
--	      void *arg)
-+	    int (*compar)(const void *_key, const void *_item, Ts... _ds),
-+	    Ts... ds)
- {
-   int min = 0, max = (int) nmemb - 1;
-   while (min <= max)
-   {
-     int mid = ((unsigned int) min + (unsigned int) max) / 2;
-     const void *p = (const void *) (((const char *) base) + (mid * size));
--    int c = compar (key, p, arg);
-+    int c = compar (key, p, ds...);
-     if (c < 0)
-       max = mid - 1;
-     else if (c > 0)
-       min = mid + 1;
-     else
-       return (void *) p;
-   }
-   return nullptr;
- }
- 
- 
- /* From https://github.com/noporpoise/sort_r
-- * With following modifications:
-- *
-- * 10 November 2018:
-- * https://github.com/noporpoise/sort_r/issues/7
-- */
-+   Feb 5, 2019 (c8c65c1e)
-+   Modified to support optional argument using templates */
- 
- /* Isaac Turner 29 April 2014 Public Domain */
- 
- /*
--
--hb_sort_r function to be exported.
--
-+hb_qsort function to be exported.
- Parameters:
-   base is the array to be sorted
-   nel is the number of elements in the array
-   width is the size in bytes of each element of the array
-   compar is the comparison function
--  arg is a pointer to be passed to the comparison function
-+  arg (optional) is a pointer to be passed to the comparison function
- 
--void hb_sort_r(void *base, size_t nel, size_t width,
--               int (*compar)(const void *_a, const void *_b, void *_arg),
--               void *arg);
-+void hb_qsort(void *base, size_t nel, size_t width,
-+              int (*compar)(const void *_a, const void *_b, [void *_arg]),
-+              [void *arg]);
- */
- 
-+#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
-+
-+/* swap a and b */
-+/* a and b must not be equal! */
-+static inline void sort_r_swap(char *__restrict a, char *__restrict b,
-+                               size_t w)
-+{
-+  char tmp, *end = a+w;
-+  for(; a < end; a++, b++) { SORT_R_SWAP(*a, *b, tmp); }
-+}
- 
- /* swap a, b iff a>b */
-+/* a and b must not be equal! */
- /* __restrict is same as restrict but better support on old machines */
--static int sort_r_cmpswap(char *__restrict a, char *__restrict b, size_t w,
--			  int (*compar)(const void *_a, const void *_b,
--					void *_arg),
--			  void *arg)
-+template <typename ...Ts>
-+static inline int sort_r_cmpswap(char *__restrict a,
-+                                 char *__restrict b, size_t w,
-+                                 int (*compar)(const void *_a,
-+                                               const void *_b,
-+                                               Ts... _ds),
-+                                 Ts... ds)
- {
--  char tmp, *end = a+w;
--  if(compar(a, b, arg) > 0) {
--    for(; a < end; a++, b++) { tmp = *a; *a = *b; *b = tmp; }
-+  if(compar(a, b, ds...) > 0) {
-+    sort_r_swap(a, b, w);
-     return 1;
-   }
-   return 0;
- }
- 
-+/*
-+Swap consecutive blocks of bytes of size na and nb starting at memory addr ptr,
-+with the smallest swap so that the blocks are in the opposite order. Blocks may
-+be internally re-ordered e.g.
-+  12345ab  ->   ab34512
-+  123abc   ->   abc123
-+  12abcde  ->   deabc12
-+*/
-+static inline void sort_r_swap_blocks(char *ptr, size_t na, size_t nb)
-+{
-+  if(na > 0 && nb > 0) {
-+    if(na > nb) { sort_r_swap(ptr, ptr+na, nb); }
-+    else { sort_r_swap(ptr, ptr+nb, na); }
-+  }
-+}
-+
-+/* Implement recursive quicksort ourselves */
- /* Note: quicksort is not stable, equivalent values may be swapped */
-+template <typename ...Ts>
- static inline void sort_r_simple(void *base, size_t nel, size_t w,
--				 int (*compar)(const void *_a, const void *_b,
--					       void *_arg),
--				 void *arg)
-+                                 int (*compar)(const void *_a,
-+                                               const void *_b,
-+                                               Ts... _ds),
-+                                 Ts... ds)
- {
-   char *b = (char *)base, *end = b + nel*w;
--  if(nel < 7) {
-+
-+  /* for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
-+  printf("\n"); */
-+
-+  if(nel < 10) {
-     /* Insertion sort for arbitrarily small inputs */
-     char *pi, *pj;
-     for(pi = b+w; pi < end; pi += w) {
--      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,arg); pj -= w) {}
-+      for(pj = pi; pj > b && sort_r_cmpswap(pj-w,pj,w,compar,ds...); pj -= w) {}
-     }
-   }
-   else
-   {
--    /* nel > 6; Quicksort */
-+    /* nel > 9; Quicksort */
- 
--    /* Use median of first, middle and last items as pivot */
--    char *x, *y, *xend, ch;
--    char *pl, *pm, *pr;
-+    int cmp;
-+    char *pl, *ple, *pr, *pre, *pivot;
-     char *last = b+w*(nel-1), *tmp;
-+
-+    /*
-+    Use median of second, middle and second-last items as pivot.
-+    First and last may have been swapped with pivot and therefore be extreme
-+    */
-     char *l[3];
--    l[0] = b;
-+    l[0] = b + w;
-     l[1] = b+w*(nel/2);
--    l[2] = last;
-+    l[2] = last - w;
- 
--    if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
--    if(compar(l[1],l[2],arg) > 0) {
--      tmp=l[1]; l[1]=l[2]; l[2]=tmp; /* swap(l[1],l[2]) */
--      if(compar(l[0],l[1],arg) > 0) { tmp=l[0]; l[0]=l[1]; l[1]=tmp; }
-+    /* printf("pivots: %i, %i, %i\n", *(int*)l[0], *(int*)l[1], *(int*)l[2]); */
-+
-+    if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
-+    if(compar(l[1],l[2],ds...) > 0) {
-+      SORT_R_SWAP(l[1], l[2], tmp);
-+      if(compar(l[0],l[1],ds...) > 0) { SORT_R_SWAP(l[0], l[1], tmp); }
-     }
- 
--    /* swap l[id], l[2] to put pivot as last element */
--    for(x = l[1], y = last, xend = x+w; x<xend; x++, y++) {
--      ch = *x; *x = *y; *y = ch;
--    }
-+    /* swap mid value (l[1]), and last element to put pivot as last element */
-+    if(l[1] != last) { sort_r_swap(l[1], last, w); }
-+
-+    /*
-+    pl is the next item on the left to be compared to the pivot
-+    pr is the last item on the right that was compared to the pivot
-+    ple is the left position to put the next item that equals the pivot
-+    ple is the last right position where we put an item that equals the pivot
-+                                           v- end (beyond the array)
-+      EEEEEELLLLLLLLuuuuuuuuGGGGGGGEEEEEEEE.
-+      ^- b  ^- ple  ^- pl   ^- pr  ^- pre ^- last (where the pivot is)
-+    Pivot comparison key:
-+      E = equal, L = less than, u = unknown, G = greater than, E = equal
-+    */
-+    pivot = last;
-+    ple = pl = b;
-+    pre = pr = last;
- 
--    pl = b;
--    pr = last;
--
-+    /*
-+    Strategy:
-+    Loop into the list from the left and right at the same time to find:
-+    - an item on the left that is greater than the pivot
-+    - an item on the right that is less than the pivot
-+    Once found, they are swapped and the loop continues.
-+    Meanwhile items that are equal to the pivot are moved to the edges of the
-+    array.
-+    */
-     while(pl < pr) {
--      pm = pl+((pr-pl+1)>>1);
--      for(; pl < pm; pl += w) {
--        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
--          pr -= w; /* pivot now at pl */
--          break;
-+      /* Move left hand items which are equal to the pivot to the far left.
-+         break when we find an item that is greater than the pivot */
-+      for(; pl < pr; pl += w) {
-+        cmp = compar(pl, pivot, ds...);
-+        if(cmp > 0) { break; }
-+        else if(cmp == 0) {
-+          if(ple < pl) { sort_r_swap(ple, pl, w); }
-+          ple += w;
-         }
-       }
--      pm = pl+((pr-pl)>>1);
--      for(; pm < pr; pr -= w) {
--        if(sort_r_cmpswap(pl, pr, w, compar, arg)) {
--          pl += w; /* pivot now at pr */
-+      /* break if last batch of left hand items were equal to pivot */
-+      if(pl >= pr) { break; }
-+      /* Move right hand items which are equal to the pivot to the far right.
-+         break when we find an item that is less than the pivot */
-+      for(; pl < pr; ) {
-+        pr -= w; /* Move right pointer onto an unprocessed item */
-+        cmp = compar(pr, pivot, ds...);
-+        if(cmp == 0) {
-+          pre -= w;
-+          if(pr < pre) { sort_r_swap(pr, pre, w); }
-+        }
-+        else if(cmp < 0) {
-+          if(pl < pr) { sort_r_swap(pl, pr, w); }
-+          pl += w;
-           break;
-         }
-       }
-     }
- 
--    sort_r_simple(b, (pl-b)/w, w, compar, arg);
--    sort_r_simple(pl+w, (end-(pl+w))/w, w, compar, arg);
-+    pl = pr; /* pr may have gone below pl */
-+
-+    /*
-+    Now we need to go from: EEELLLGGGGEEEE
-+                        to: LLLEEEEEEEGGGG
-+    Pivot comparison key:
-+      E = equal, L = less than, u = unknown, G = greater than, E = equal
-+    */
-+    sort_r_swap_blocks(b, ple-b, pl-ple);
-+    sort_r_swap_blocks(pr, pre-pr, end-pre);
-+
-+    /*for(size_t i=0; i<nel; i++) {printf("%4i", *(int*)(b + i*sizeof(int)));}
-+    printf("\n");*/
-+
-+    sort_r_simple(b, (pl-ple)/w, w, compar, ds...);
-+    sort_r_simple(end-(pre-pr), (pre-pr)/w, w, compar, ds...);
-   }
- }
- 
- static inline void
--hb_sort_r (void *base, size_t nel, size_t width,
--	   int (*compar)(const void *_a, const void *_b, void *_arg),
--	   void *arg)
-+hb_qsort (void *base, size_t nel, size_t width,
-+	  int (*compar)(const void *_a, const void *_b))
- {
--    sort_r_simple(base, nel, width, compar, arg);
-+#if defined(__OPTIMIZE_SIZE__) && !defined(HB_USE_INTERNAL_QSORT)
-+  qsort (base, nel, width, compar);
-+#else
-+  sort_r_simple (base, nel, width, compar);
-+#endif
-+}
-+
-+static inline void
-+hb_qsort (void *base, size_t nel, size_t width,
-+	  int (*compar)(const void *_a, const void *_b, void *_arg),
-+	  void *arg)
-+{
-+#ifdef HAVE_GNU_QSORT_R
-+  qsort_r (base, nel, width, compar, arg);
-+#else
-+  sort_r_simple (base, nel, width, compar, arg);
-+#endif
- }
- 
- 
- template <typename T, typename T2, typename T3> static inline void
- hb_stable_sort (T *array, unsigned int len, int(*compar)(const T2 *, const T2 *), T3 *array2)
- {
-   for (unsigned int i = 1; i < len; i++)
-   {
-@@ -840,16 +940,22 @@ HB_FUNCOBJ (hb_bitwise_xor);
- struct hb_bitwise_sub
- { HB_PARTIALIZE(2);
-   static constexpr bool passthru_left = true;
-   static constexpr bool passthru_right = false;
-   template <typename T> auto
-   operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b)
- }
- HB_FUNCOBJ (hb_bitwise_sub);
-+struct
-+{
-+  template <typename T> auto
-+  operator () (const T &a) const HB_AUTO_RETURN (~a)
-+}
-+HB_FUNCOBJ (hb_bitwise_neg);
- 
- struct
- { HB_PARTIALIZE(2);
-   template <typename T, typename T2> auto
-   operator () (const T &a, const T2 &b) const HB_AUTO_RETURN (a + b)
- }
- HB_FUNCOBJ (hb_add);
- struct
-@@ -888,64 +994,49 @@ struct
-   operator () (const T &a) const HB_AUTO_RETURN (-a)
- }
- HB_FUNCOBJ (hb_neg);
- 
- 
- /* Compiler-assisted vectorization. */
- 
- /* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))),
-- * using vectorized operations if HB_VECTOR_SIZE is set to **bit** numbers (eg 128).
-- * Define that to 0 to disable. */
-+ * basically a fixed-size bitset. */
- template <typename elt_t, unsigned int byte_size>
- struct hb_vector_size_t
- {
--  elt_t& operator [] (unsigned int i) { return u.v[i]; }
--  const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
-+  elt_t& operator [] (unsigned int i) { return v[i]; }
-+  const elt_t& operator [] (unsigned int i) const { return v[i]; }
- 
-   void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
- 
-   template <typename Op>
-+  hb_vector_size_t process (const Op& op) const
-+  {
-+    hb_vector_size_t r;
-+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
-+      r.v[i] = op (v[i]);
-+    return r;
-+  }
-+  template <typename Op>
-   hb_vector_size_t process (const Op& op, const hb_vector_size_t &o) const
-   {
-     hb_vector_size_t r;
--#if HB_VECTOR_SIZE
--    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
--      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
--	r.u.vec[i] = op (u.vec[i], o.u.vec[i]);
--    else
--#endif
--      for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
--	r.u.v[i] = op (u.v[i], o.u.v[i]);
-+    for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
-+      r.v[i] = op (v[i], o.v[i]);
-     return r;
-   }
-   hb_vector_size_t operator | (const hb_vector_size_t &o) const
-   { return process (hb_bitwise_or, o); }
-   hb_vector_size_t operator & (const hb_vector_size_t &o) const
-   { return process (hb_bitwise_and, o); }
-   hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
-   { return process (hb_bitwise_xor, o); }
-   hb_vector_size_t operator ~ () const
--  {
--    hb_vector_size_t r;
--#if HB_VECTOR_SIZE && 0
--    if (HB_VECTOR_SIZE && 0 == (byte_size * 8) % HB_VECTOR_SIZE)
--      for (unsigned int i = 0; i < ARRAY_LENGTH (u.vec); i++)
--	r.u.vec[i] = ~u.vec[i];
--    else
--#endif
--    for (unsigned int i = 0; i < ARRAY_LENGTH (u.v); i++)
--      r.u.v[i] = ~u.v[i];
--    return r;
--  }
-+  { return process (hb_bitwise_neg); }
- 
-   private:
--  static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size, "");
--  union {
--    elt_t v[byte_size / sizeof (elt_t)];
--#if HB_VECTOR_SIZE
--    hb_vector_size_impl_t vec[byte_size / sizeof (hb_vector_size_impl_t)];
--#endif
--  } u;
-+  static_assert (0 == byte_size % sizeof (elt_t), "");
-+  elt_t v[byte_size / sizeof (elt_t)];
- };
- 
- 
- #endif /* HB_ALGS_HH */
-diff --git a/gfx/harfbuzz/src/hb-array.hh b/gfx/harfbuzz/src/hb-array.hh
---- a/gfx/harfbuzz/src/hb-array.hh
-+++ b/gfx/harfbuzz/src/hb-array.hh
-@@ -136,31 +136,31 @@ struct hb_array_t : hb_iter_with_fallbac
-       if (!this->arrayZ[i].cmp (x))
- 	return &this->arrayZ[i];
-     return not_found;
-   }
- 
-   hb_sorted_array_t<Type> qsort (int (*cmp_)(const void*, const void*))
-   {
-     if (likely (length))
--      ::qsort (arrayZ, length, this->item_size, cmp_);
-+      hb_qsort (arrayZ, length, this->item_size, cmp_);
-     return hb_sorted_array_t<Type> (*this);
-   }
-   hb_sorted_array_t<Type> qsort ()
-   {
-     if (likely (length))
--      ::qsort (arrayZ, length, this->item_size, Type::cmp);
-+      hb_qsort (arrayZ, length, this->item_size, Type::cmp);
-     return hb_sorted_array_t<Type> (*this);
-   }
-   void qsort (unsigned int start, unsigned int end)
-   {
-     end = hb_min (end, length);
-     assert (start <= end);
-     if (likely (start < end))
--      ::qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
-+      hb_qsort (arrayZ + start, end - start, this->item_size, Type::cmp);
-   }
- 
-   /*
-    * Other methods.
-    */
- 
-   unsigned int get_size () const { return length * this->item_size; }
- 
-diff --git a/gfx/harfbuzz/src/hb-atomic.hh b/gfx/harfbuzz/src/hb-atomic.hh
---- a/gfx/harfbuzz/src/hb-atomic.hh
-+++ b/gfx/harfbuzz/src/hb-atomic.hh
-@@ -102,17 +102,17 @@ static inline bool
- 
- 
- #elif !defined(HB_NO_MT) && defined(_WIN32)
- 
- #include <windows.h>
- 
- static inline void _hb_memory_barrier ()
- {
--#ifndef MemoryBarrier
-+#if !defined(MemoryBarrier) && !defined(__MINGW32_VERSION)
-   /* MinGW has a convoluted history of supporting MemoryBarrier. */
-   LONG dummy = 0;
-   InterlockedExchange (&dummy, 1);
- #else
-   MemoryBarrier ();
- #endif
- }
- #define _hb_memory_barrier()			_hb_memory_barrier ()
-diff --git a/gfx/harfbuzz/src/hb-bimap.hh b/gfx/harfbuzz/src/hb-bimap.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-bimap.hh
-@@ -0,0 +1,139 @@
-+/*
-+ * Copyright © 2019 Adobe Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Adobe Author(s): Michiharu Ariza
-+ */
-+
-+#ifndef HB_BIMAP_HH
-+#define HB_BIMAP_HH
-+
-+#include "hb.hh"
-+
-+/* Bi-directional map */
-+struct hb_bimap_t
-+{
-+  hb_bimap_t () { init (); }
-+  ~hb_bimap_t () { fini (); }
-+
-+  void init ()
-+  {
-+    forw_map.init ();
-+    back_map.init ();
-+  }
-+
-+  void fini ()
-+  {
-+    forw_map.fini ();
-+    back_map.fini ();
-+  }
-+
-+  void reset ()
-+  {
-+    forw_map.reset ();
-+    back_map.reset ();
-+  }
-+
-+  bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
-+
-+  void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
-+  {
-+    forw_map.set (lhs, rhs);
-+    back_map.set (rhs, lhs);
-+  }
-+
-+  hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
-+  hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); }
-+
-+  hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
-+  bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); }
-+
-+  void del (hb_codepoint_t lhs)
-+  {
-+    back_map.del (get (lhs));
-+    forw_map.del (lhs);
-+  }
-+
-+  void clear ()
-+  {
-+    forw_map.clear ();
-+    back_map.clear ();
-+  }
-+
-+  bool is_empty () const { return get_population () == 0; }
-+
-+  unsigned int get_population () const { return forw_map.get_population (); }
-+
-+  protected:
-+  hb_map_t  forw_map;
-+  hb_map_t  back_map;
-+};
-+
-+/* Inremental bimap: only lhs is given, rhs is incrementally assigned */
-+struct hb_inc_bimap_t : hb_bimap_t
-+{
-+  /* Add a mapping from lhs to rhs with a unique value if lhs is unknown.
-+   * Return the rhs value as the result.
-+   */
-+  hb_codepoint_t add (hb_codepoint_t lhs)
-+  {
-+    hb_codepoint_t  rhs = forw_map[lhs];
-+    if (rhs == HB_MAP_VALUE_INVALID)
-+    {
-+      rhs = get_population ();
-+      set (lhs, rhs);
-+    }
-+    return rhs;
-+  }
-+
-+  /* Create an identity map. */
-+  bool identity (unsigned int size)
-+  {
-+    clear ();
-+    for (hb_codepoint_t i = 0; i < size; i++) set (i, i);
-+    return !in_error ();
-+  }
-+
-+  protected:
-+  static int cmp_id (const void* a, const void* b)
-+  { return (int)*(const hb_codepoint_t *)a - (int)*(const hb_codepoint_t *)b; }
-+
-+  public:
-+  /* Optional: after finished adding all mappings in a random order,
-+   * reassign rhs to lhs so that they are in the same order. */
-+  void sort ()
-+  {
-+    hb_codepoint_t  count = get_population ();
-+    hb_vector_t <hb_codepoint_t> work;
-+    work.resize (count);
-+
-+    for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
-+      work[rhs] = back_map[rhs];
-+  
-+    work.qsort (cmp_id);
-+  
-+    for (hb_codepoint_t rhs = 0; rhs < count; rhs++)
-+      set (work[rhs], rhs);
-+  }
-+};
-+
-+#endif /* HB_BIMAP_HH */
-diff --git a/gfx/harfbuzz/src/hb-blob.cc b/gfx/harfbuzz/src/hb-blob.cc
---- a/gfx/harfbuzz/src/hb-blob.cc
-+++ b/gfx/harfbuzz/src/hb-blob.cc
-@@ -482,16 +482,17 @@ hb_blob_t::try_make_writable ()
- 
-   return true;
- }
- 
- /*
-  * Mmap
-  */
- 
-+#ifndef HB_NO_OPEN
- #ifdef HAVE_MMAP
- # include <sys/types.h>
- # include <sys/stat.h>
- # include <fcntl.h>
- #endif
- 
- #ifdef _WIN32
- # include <windows.h>
-@@ -671,8 +672,9 @@ fail_without_close:
-                          (hb_destroy_func_t) free);
- 
- fread_fail:
-   fclose (fp);
- fread_fail_without_close:
-   free (data);
-   return hb_blob_get_empty ();
- }
-+#endif /* !HB_NO_OPEN */
-diff --git a/gfx/harfbuzz/src/hb-buffer-serialize.cc b/gfx/harfbuzz/src/hb-buffer-serialize.cc
---- a/gfx/harfbuzz/src/hb-buffer-serialize.cc
-+++ b/gfx/harfbuzz/src/hb-buffer-serialize.cc
-@@ -19,24 +19,26 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
-+#include "hb.hh"
-+
-+#ifndef HB_NO_BUFFER_SERIALIZE
-+
- #include "hb-buffer.hh"
- 
- 
- static const char *serialize_formats[] = {
--#ifndef HB_NO_BUFFER_SERIALIZE
-   "text",
-   "json",
--#endif
-   nullptr
- };
- 
- /**
-  * hb_buffer_serialize_list_formats:
-  *
-  * Returns a list of supported buffer serialization formats.
-  *
-@@ -84,20 +86,18 @@ hb_buffer_serialize_format_from_string (
-  *
-  * Since: 0.9.7
-  **/
- const char *
- hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
- {
-   switch ((unsigned) format)
-   {
--#ifndef HB_NO_BUFFER_SERIALIZE
-     case HB_BUFFER_SERIALIZE_FORMAT_TEXT:	return serialize_formats[0];
-     case HB_BUFFER_SERIALIZE_FORMAT_JSON:	return serialize_formats[1];
--#endif
-     default:
-     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:	return nullptr;
-   }
- }
- 
- static unsigned int
- _hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
- 				  unsigned int start,
-@@ -343,20 +343,16 @@ hb_buffer_serialize_glyphs (hb_buffer_t 
- 
-   unsigned int sconsumed;
-   if (!buf_consumed)
-     buf_consumed = &sconsumed;
-   *buf_consumed = 0;
-   if (buf_size)
-     *buf = '\0';
- 
--#ifdef HB_NO_BUFFER_SERIALIZE
--  return 0;
--#endif
--
-   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
- 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
- 
-   if (!buffer->have_positions)
-     flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
- 
-   if (unlikely (start == end))
-     return 0;
-@@ -452,20 +448,16 @@ hb_buffer_deserialize_glyphs (hb_buffer_
- 			      hb_font_t *font, /* May be NULL */
- 			      hb_buffer_serialize_format_t format)
- {
-   const char *end;
-   if (!end_ptr)
-     end_ptr = &end;
-   *end_ptr = buf;
- 
--#ifdef HB_NO_BUFFER_SERIALIZE
--  return false;
--#endif
--
-   assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
- 	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
- 
-   if (buf_len == -1)
-     buf_len = strlen (buf);
- 
-   if (!buf_len)
-   {
-@@ -491,8 +483,11 @@ hb_buffer_deserialize_glyphs (hb_buffer_
- 						 font);
- 
-     default:
-     case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
-       return false;
- 
-   }
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-buffer.cc b/gfx/harfbuzz/src/hb-buffer.cc
---- a/gfx/harfbuzz/src/hb-buffer.cc
-+++ b/gfx/harfbuzz/src/hb-buffer.cc
-@@ -1988,16 +1988,17 @@ hb_buffer_diff (hb_buffer_t *buffer,
-   return result;
- }
- 
- 
- /*
-  * Debugging.
-  */
- 
-+#ifndef HB_NO_BUFFER_MESSAGE
- /**
-  * hb_buffer_set_message_func:
-  * @buffer: an #hb_buffer_t.
-  * @func: (closure user_data) (destroy destroy) (scope notified):
-  * @user_data:
-  * @destroy:
-  *
-  *
-@@ -2017,16 +2018,16 @@ hb_buffer_set_message_func (hb_buffer_t 
-     buffer->message_data = user_data;
-     buffer->message_destroy = destroy;
-   } else {
-     buffer->message_func = nullptr;
-     buffer->message_data = nullptr;
-     buffer->message_destroy = nullptr;
-   }
- }
--
- bool
- hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
- {
-   char buf[100];
--  vsnprintf (buf, sizeof (buf),  fmt, ap);
-+  vsnprintf (buf, sizeof (buf), fmt, ap);
-   return (bool) this->message_func (this, font, buf, this->message_data);
- }
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-buffer.hh b/gfx/harfbuzz/src/hb-buffer.hh
---- a/gfx/harfbuzz/src/hb-buffer.hh
-+++ b/gfx/harfbuzz/src/hb-buffer.hh
-@@ -119,17 +119,19 @@ struct hb_buffer_t
-   /* Text before / after the main buffer contents.
-    * Always in Unicode, and ordered outward.
-    * Index 0 is for "pre-context", 1 for "post-context". */
-   static constexpr unsigned CONTEXT_LENGTH = 5u;
-   hb_codepoint_t context[2][CONTEXT_LENGTH];
-   unsigned int context_len[2];
- 
-   /* Debugging API */
-+#ifndef HB_NO_BUFFER_MESSAGE
-   hb_buffer_message_func_t message_func;
-+#endif
-   void *message_data;
-   hb_destroy_func_t message_destroy;
- 
-   /* Internal debugging. */
-   /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
- #ifndef HB_NDEBUG
-   uint8_t allocated_var_bits;
- #endif
-@@ -342,26 +344,37 @@ struct hb_buffer_t
- 
-   typedef long scratch_buffer_t;
-   HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
- 
-   void clear_context (unsigned int side) { context_len[side] = 0; }
- 
-   HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
- 
--  bool messaging () { return unlikely (message_func); }
-+  bool messaging ()
-+  {
-+#ifdef HB_NO_BUFFER_MESSAGE
-+    return false;
-+#else
-+    return unlikely (message_func);
-+#endif
-+  }
-   bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
-   {
-+#ifdef HB_NO_BUFFER_MESSAGE
-+   return true;
-+#else
-     if (!messaging ())
-       return true;
-     va_list ap;
-     va_start (ap, fmt);
-     bool ret = message_impl (font, fmt, ap);
-     va_end (ap);
-     return ret;
-+#endif
-   }
-   HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
- 
-   static void
-   set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0)
-   {
-     if (inf.cluster != cluster)
-     {
-diff --git a/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh b/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
---- a/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
-+++ b/gfx/harfbuzz/src/hb-cff-interp-cs-common.hh
-@@ -71,18 +71,18 @@ struct biased_subrs_t
-     else if (nSubrs < 33900)
-       bias = 1131;
-     else
-       bias = 32768;
-   }
- 
-   void fini () {}
- 
--  unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; }
--  unsigned int get_bias () const { return bias; }
-+  unsigned int get_count () const { return (subrs == nullptr) ? 0 : subrs->count; }
-+  unsigned int get_bias () const  { return bias; }
- 
-   byte_str_t operator [] (unsigned int index) const
-   {
-     if (unlikely ((subrs == nullptr) || index >= subrs->count))
-       return Null(byte_str_t);
-     else
-       return (*subrs)[index];
-   }
-diff --git a/gfx/harfbuzz/src/hb-cff-interp-dict-common.hh b/gfx/harfbuzz/src/hb-cff-interp-dict-common.hh
---- a/gfx/harfbuzz/src/hb-cff-interp-dict-common.hh
-+++ b/gfx/harfbuzz/src/hb-cff-interp-dict-common.hh
-@@ -129,38 +129,38 @@ struct dict_opset_t : opset_t<number_t>
- 
-       switch (d)
-       {
- 	case RESERVED:
- 	  str_ref.set_error ();
- 	  return value;
- 
- 	case END:
--	  value = (double)(neg? -int_part: int_part);
-+	  value = (double) (neg ? -int_part : int_part);
- 	  if (frac_count > 0)
- 	  {
--	    double frac = (frac_part / pow (10.0, (double)frac_count));
-+	    double frac = (frac_part / pow (10.0, (double) frac_count));
- 	    if (neg) frac = -frac;
- 	    value += frac;
- 	  }
- 	  if (unlikely (exp_overflow))
- 	  {
- 	    if (value == 0.0)
- 	      return value;
- 	    if (exp_neg)
--	      return neg? -DBL_MIN: DBL_MIN;
-+	      return neg ? -DBL_MIN : DBL_MIN;
- 	    else
--	      return neg? -DBL_MAX: DBL_MAX;
-+	      return neg ? -DBL_MAX : DBL_MAX;
- 	  }
- 	  if (exp_part != 0)
- 	  {
- 	    if (exp_neg)
--	      value /= pow (10.0, (double)exp_part);
-+	      value /= pow (10.0, (double) exp_part);
- 	    else
--	      value *= pow (10.0, (double)exp_part);
-+	      value *= pow (10.0, (double) exp_part);
- 	  }
- 	  return value;
- 
- 	case NEG:
- 	  if (i != 0)
- 	  {
- 	    str_ref.set_error ();
- 	    return 0.0;
-diff --git a/gfx/harfbuzz/src/hb-common.cc b/gfx/harfbuzz/src/hb-common.cc
---- a/gfx/harfbuzz/src/hb-common.cc
-+++ b/gfx/harfbuzz/src/hb-common.cc
-@@ -30,16 +30,19 @@
- 
- #include "hb-machinery.hh"
- 
- #include <locale.h>
- #ifdef HAVE_XLOCALE_H
- #include <xlocale.h>
- #endif
- 
-+#ifdef HB_NO_SETLOCALE
-+#define setlocale(Category, Locale) "C"
-+#endif
- 
- /**
-  * SECTION:hb-common
-  * @title: hb-common
-  * @short_description: Common data types
-  * @include: hb.h
-  *
-  * Common data types used across HarfBuzz are defined here.
-@@ -62,17 +65,17 @@ void
-   {
-     while (*c)
-     {
-       const char *p = strchr (c, ':');
-       if (!p)
-         p = c + strlen (c);
- 
- #define OPTION(name, symbol) \
--	if (0 == strncmp (c, name, p - c) && strlen (name) == p - c) do { u.opts.symbol = true; } while (0)
-+	if (0 == strncmp (c, name, p - c) && strlen (name) == static_cast<size_t>(p - c)) do { u.opts.symbol = true; } while (0)
- 
-       OPTION ("uniscribe-bug-compatible", uniscribe_bug_compatible);
-       OPTION ("aat", aat);
- 
- #undef OPTION
- 
-       c = *p ? p + 1 : p;
-     }
-diff --git a/gfx/harfbuzz/src/hb-config.hh b/gfx/harfbuzz/src/hb-config.hh
---- a/gfx/harfbuzz/src/hb-config.hh
-+++ b/gfx/harfbuzz/src/hb-config.hh
-@@ -35,45 +35,60 @@
- #include "config.h"
- #endif
- 
- 
- #ifdef HB_TINY
- #define HB_LEAN
- #define HB_MINI
- #define HB_NO_MT
-+#define HB_NO_UCD_UNASSIGNED
- #ifndef NDEBUG
- #define NDEBUG
- #endif
- #ifndef __OPTIMIZE_SIZE__
- #define __OPTIMIZE_SIZE__
- #endif
- #endif
- 
- #ifdef HB_LEAN
- #define HB_DISABLE_DEPRECATED
- #define HB_NDEBUG
- #define HB_NO_ATEXIT
-+#define HB_NO_BUFFER_MESSAGE
- #define HB_NO_BUFFER_SERIALIZE
- #define HB_NO_BITMAP
- #define HB_NO_CFF
- #define HB_NO_COLOR
-+#define HB_NO_FACE_COLLECT_UNICODES
- #define HB_NO_GETENV
-+#define HB_NO_HINTING
-+#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
-+#define HB_NO_LAYOUT_FEATURE_PARAMS
-+#define HB_NO_LAYOUT_COLLECT_GLYPHS
- #define HB_NO_LAYOUT_UNUSED
- #define HB_NO_MATH
-+#define HB_NO_MMAP
- #define HB_NO_NAME
-+#define HB_NO_OPEN
-+#define HB_NO_SETLOCALE
-+#define HB_NO_OT_FONT_GLYPH_NAMES
-+#define HB_NO_OT_SHAPE_FRACTIONS
-+#define HB_NO_STAT
- #define HB_NO_SUBSET_LAYOUT
-+#define HB_NO_VAR
- #endif
- 
- #ifdef HB_MINI
- #define HB_NO_AAT
- #define HB_NO_LEGACY
- #endif
- 
--/* Closure. */
-+
-+/* Closure of options. */
- 
- #ifdef HB_DISABLE_DEPRECATED
- #define HB_IF_NOT_DEPRECATED(x)
- #else
- #define HB_IF_NOT_DEPRECATED(x) x
- #endif
- 
- #ifdef HB_NO_AAT
-@@ -90,16 +105,19 @@
- #define HB_NO_SUBSET_CFF
- #endif
- 
- #ifdef HB_NO_GETENV
- #define HB_NO_UNISCRIBE_BUG_COMPATIBLE
- #endif
- 
- #ifdef HB_NO_LEGACY
-+#define HB_NO_CMAP_LEGACY_SUBTABLES
-+#define HB_NO_FALLBACK_SHAPE
-+#define HB_NO_OT_KERN
- #define HB_NO_OT_LAYOUT_BLACKLIST
- #define HB_NO_OT_SHAPE_FALLBACK
- #endif
- 
- #ifdef HB_NO_NAME
- #define HB_NO_OT_NAME_LANGUAGE
- #endif
- 
-diff --git a/gfx/harfbuzz/src/hb-coretext.cc b/gfx/harfbuzz/src/hb-coretext.cc
---- a/gfx/harfbuzz/src/hb-coretext.cc
-+++ b/gfx/harfbuzz/src/hb-coretext.cc
-@@ -22,16 +22,19 @@
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Mozilla Author(s): Jonathan Kew
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
-+
-+#ifdef HAVE_CORETEXT
-+
- #include "hb-shaper-impl.hh"
- 
- #include "hb-coretext.h"
- #include "hb-aat-layout.hh"
- #include <math.h>
- 
- 
- /**
-@@ -644,17 +647,17 @@ hb_bool_t
-       log_clusters[chars_len++] = cluster; /* Surrogates. */
-   }
- 
- #define FAIL(...) \
-   HB_STMT_START { \
-     DEBUG_MSG (CORETEXT, nullptr, __VA_ARGS__); \
-     ret = false; \
-     goto fail; \
--  } HB_STMT_END;
-+  } HB_STMT_END
- 
-   bool ret = true;
-   CFStringRef string_ref = nullptr;
-   CTLineRef line = nullptr;
- 
-   if (false)
-   {
- resize_and_retry:
-@@ -972,17 +975,17 @@ resize_and_retry:
- #define USE_PTR true
- 
- #define SCRATCH_SAVE() \
-   unsigned int scratch_size_saved = scratch_size; \
-   hb_buffer_t::scratch_buffer_t *scratch_saved = scratch
- 
- #define SCRATCH_RESTORE() \
-   scratch_size = scratch_size_saved; \
--  scratch = scratch_saved;
-+  scratch = scratch_saved
- 
-       { /* Setup glyphs */
-         SCRATCH_SAVE();
- 	const CGGlyph* glyphs = USE_PTR ? CTRunGetGlyphsPtr (run) : nullptr;
- 	if (!glyphs) {
- 	  ALLOCATE_ARRAY (CGGlyph, glyph_buf, num_glyphs, goto resize_and_retry);
- 	  CTRunGetGlyphs (run, range_all, glyph_buf);
- 	  glyphs = glyph_buf;
-@@ -1143,8 +1146,11 @@ fail:
-     CFRelease (line);
- 
-   for (unsigned int i = 0; i < range_records.length; i++)
-     if (range_records[i].font)
-       CFRelease (range_records[i].font);
- 
-   return ret;
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-deprecated.h b/gfx/harfbuzz/src/hb-deprecated.h
---- a/gfx/harfbuzz/src/hb-deprecated.h
-+++ b/gfx/harfbuzz/src/hb-deprecated.h
-@@ -160,40 +160,19 @@ hb_unicode_funcs_set_decompose_compatibi
- 						   void *user_data, hb_destroy_func_t destroy);
- 
- HB_EXTERN HB_DEPRECATED unsigned int
- hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs,
- 				    hb_codepoint_t      u,
- 				    hb_codepoint_t     *decomposed);
- 
- 
--typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
--							   hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
--							   void *user_data);
--typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
- typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t;
- 
- /**
-- * hb_font_funcs_set_glyph_h_kerning_func:
-- * @ffuncs: font functions.
-- * @func: (closure user_data) (destroy destroy) (scope notified):
-- * @user_data:
-- * @destroy:
-- *
-- * 
-- *
-- * Since: 0.9.2
-- * Deprecated: 2.0.0
-- **/
--HB_EXTERN void
--hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
--					hb_font_get_glyph_h_kerning_func_t func,
--					void *user_data, hb_destroy_func_t destroy);
--
--/**
-  * hb_font_funcs_set_glyph_v_kerning_func:
-  * @ffuncs: font functions.
-  * @func: (closure user_data) (destroy destroy) (scope notified):
-  * @user_data:
-  * @destroy:
-  *
-  * 
-  *
-@@ -201,26 +180,16 @@ hb_font_funcs_set_glyph_h_kerning_func (
-  * Deprecated: 2.0.0
-  **/
- HB_EXTERN void
- hb_font_funcs_set_glyph_v_kerning_func (hb_font_funcs_t *ffuncs,
- 					hb_font_get_glyph_v_kerning_func_t func,
- 					void *user_data, hb_destroy_func_t destroy);
- 
- HB_EXTERN hb_position_t
--hb_font_get_glyph_h_kerning (hb_font_t *font,
--			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
--HB_EXTERN hb_position_t
- hb_font_get_glyph_v_kerning (hb_font_t *font,
- 			     hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph);
- 
--HB_EXTERN void
--hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
--					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
--					 hb_direction_t direction,
--					 hb_position_t *x, hb_position_t *y);
--
--
- #endif
- 
- HB_END_DECLS
- 
- #endif /* HB_DEPRECATED_H */
-diff --git a/gfx/harfbuzz/src/hb-directwrite.cc b/gfx/harfbuzz/src/hb-directwrite.cc
---- a/gfx/harfbuzz/src/hb-directwrite.cc
-+++ b/gfx/harfbuzz/src/hb-directwrite.cc
-@@ -18,16 +18,19 @@
-  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  */
- 
- #include "hb.hh"
-+
-+#ifdef HAVE_DIRECTWRITE
-+
- #include "hb-shaper-impl.hh"
- 
- #include <DWrite_1.h>
- 
- #include "hb-directwrite.h"
- 
- 
- /*
-@@ -168,17 +171,17 @@ hb_directwrite_face_data_t *
-   uint64_t fontFileKey = 0;
-   hr = dwriteFactory->CreateCustomFontFileReference (&fontFileKey, sizeof (fontFileKey),
- 						     fontFileLoader, &fontFile);
- 
- #define FAIL(...) \
-   HB_STMT_START { \
-     DEBUG_MSG (DIRECTWRITE, nullptr, __VA_ARGS__); \
-     return nullptr; \
--  } HB_STMT_END;
-+  } HB_STMT_END
- 
-   if (FAILED (hr))
-     FAIL ("Failed to load font file from data!");
- 
-   BOOL isSupported;
-   DWRITE_FONT_FILE_TYPE fileType;
-   DWRITE_FONT_FACE_TYPE faceType;
-   uint32_t numberOfFaces;
-@@ -946,15 +949,18 @@ hb_directwrite_face_create (IDWriteFontF
- }
- 
- /**
- * hb_directwrite_face_get_font_face:
- * @face: a #hb_face_t object
- *
- * Return value: DirectWrite IDWriteFontFace object corresponding to the given input
- *
--* Since: REPLACEME
-+* Since: 2.5.0
- **/
- IDWriteFontFace *
- hb_directwrite_face_get_font_face (hb_face_t *face)
- {
-   return face->data.directwrite->fontFace;
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-face.cc b/gfx/harfbuzz/src/hb-face.cc
---- a/gfx/harfbuzz/src/hb-face.cc
-+++ b/gfx/harfbuzz/src/hb-face.cc
-@@ -526,63 +526,62 @@ hb_face_get_table_tags (const hb_face_t 
- }
- 
- 
- /*
-  * Character set.
-  */
- 
- 
-+#ifndef HB_NO_FACE_COLLECT_UNICODES
- /**
-  * hb_face_collect_unicodes:
-  * @face: font face.
-  * @out: set to add Unicode characters covered by @face to.
-  *
-  * Since: 1.9.0
-  */
- void
- hb_face_collect_unicodes (hb_face_t *face,
- 			  hb_set_t  *out)
- {
-   face->table.cmap->collect_unicodes (out);
- }
--
- /**
-  * hb_face_collect_variation_selectors:
-  * @face: font face.
-  * @out: set to add Variation Selector characters covered by @face to.
-  *
-  *
-  *
-  * Since: 1.9.0
-  */
- void
- hb_face_collect_variation_selectors (hb_face_t *face,
- 				     hb_set_t  *out)
- {
-   face->table.cmap->collect_variation_selectors (out);
- }
--
- /**
-  * hb_face_collect_variation_unicodes:
-  * @face: font face.
-  * @out: set to add Unicode characters for @variation_selector covered by @face to.
-  *
-  *
-  *
-  * Since: 1.9.0
-  */
- void
- hb_face_collect_variation_unicodes (hb_face_t *face,
- 				    hb_codepoint_t variation_selector,
- 				    hb_set_t  *out)
- {
-   face->table.cmap->collect_variation_unicodes (variation_selector, out);
- }
--
-+#endif
- 
- 
- /*
-  * face-builder: A face that has add_table().
-  */
- 
- struct hb_face_builder_data_t
- {
-diff --git a/gfx/harfbuzz/src/hb-fallback-shape.cc b/gfx/harfbuzz/src/hb-fallback-shape.cc
---- a/gfx/harfbuzz/src/hb-fallback-shape.cc
-+++ b/gfx/harfbuzz/src/hb-fallback-shape.cc
-@@ -21,16 +21,17 @@
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb-shaper-impl.hh"
- 
-+#ifndef HB_NO_FALLBACK_SHAPE
- 
- /*
-  * shaper face data
-  */
- 
- struct hb_fallback_face_data_t {};
- 
- hb_fallback_face_data_t *
-@@ -115,8 +116,10 @@ hb_bool_t
- 
-   if (HB_DIRECTION_IS_BACKWARD (direction))
-     hb_buffer_reverse (buffer);
- 
-   buffer->safe_to_break_all ();
- 
-   return true;
- }
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-font.cc b/gfx/harfbuzz/src/hb-font.cc
---- a/gfx/harfbuzz/src/hb-font.cc
-+++ b/gfx/harfbuzz/src/hb-font.cc
-@@ -331,17 +331,16 @@ hb_font_get_glyph_v_origin_default (hb_f
- 				    void *user_data HB_UNUSED)
- {
-   hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
-   if (ret)
-     font->parent_scale_position (x, y);
-   return ret;
- }
- 
--#ifndef HB_DISABLE_DEPRECATED
- static hb_position_t
- hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
- 				 void *font_data HB_UNUSED,
- 				 hb_codepoint_t left_glyph HB_UNUSED,
- 				 hb_codepoint_t right_glyph HB_UNUSED,
- 				 void *user_data HB_UNUSED)
- {
-   return 0;
-@@ -351,16 +350,17 @@ hb_font_get_glyph_h_kerning_default (hb_
- 				     void *font_data HB_UNUSED,
- 				     hb_codepoint_t left_glyph,
- 				     hb_codepoint_t right_glyph,
- 				     void *user_data HB_UNUSED)
- {
-   return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- static hb_position_t
- hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
- 				 void *font_data HB_UNUSED,
- 				 hb_codepoint_t top_glyph HB_UNUSED,
- 				 hb_codepoint_t bottom_glyph HB_UNUSED,
- 				 void *user_data HB_UNUSED)
- {
-   return 0;
-@@ -922,37 +922,36 @@ hb_font_get_glyph_h_origin (hb_font_t *f
- hb_bool_t
- hb_font_get_glyph_v_origin (hb_font_t *font,
- 			    hb_codepoint_t glyph,
- 			    hb_position_t *x, hb_position_t *y)
- {
-   return font->get_glyph_v_origin (glyph, x, y);
- }
- 
--#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_font_get_glyph_h_kerning:
-  * @font: a font.
-  * @left_glyph: 
-  * @right_glyph: 
-  *
-  * 
-  *
-  * Return value: 
-  *
-  * Since: 0.9.2
-- * Deprecated: 2.0.0
-  **/
- hb_position_t
- hb_font_get_glyph_h_kerning (hb_font_t *font,
- 			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
- {
-   return font->get_glyph_h_kerning (left_glyph, right_glyph);
- }
- 
-+#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_font_get_glyph_v_kerning:
-  * @font: a font.
-  * @top_glyph: 
-  * @bottom_glyph: 
-  *
-  * 
-  *
-@@ -1172,40 +1171,37 @@ void
- hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
- 					     hb_codepoint_t glyph,
- 					     hb_direction_t direction,
- 					     hb_position_t *x, hb_position_t *y)
- {
-   return font->subtract_glyph_origin_for_direction (glyph, direction, x, y);
- }
- 
--#ifndef HB_DISABLE_DEPRECATED
- /**
-  * hb_font_get_glyph_kerning_for_direction:
-  * @font: a font.
-  * @first_glyph: 
-  * @second_glyph: 
-  * @direction: 
-  * @x: (out): 
-  * @y: (out): 
-  *
-  * 
-  *
-  * Since: 0.9.2
-- * Deprecated: 2.0.0
-  **/
- void
- hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
- 					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
- 					 hb_direction_t direction,
- 					 hb_position_t *x, hb_position_t *y)
- {
-   return font->get_glyph_kerning_for_direction (first_glyph, second_glyph, direction, x, y);
- }
--#endif
- 
- /**
-  * hb_font_get_glyph_extents_for_origin:
-  * @font: a font.
-  * @glyph: 
-  * @direction: 
-  * @extents: (out): 
-  *
-@@ -1823,16 +1819,17 @@ static void
- 				      unsigned int coords_length)
- {
-   free (font->coords);
- 
-   font->coords = coords;
-   font->num_coords = coords_length;
- }
- 
-+#ifndef HB_NO_VAR
- /**
-  * hb_font_set_variations:
-  *
-  * Since: 1.4.2
-  */
- void
- hb_font_set_variations (hb_font_t *font,
- 			const hb_variation_t *variations,
-@@ -1853,17 +1850,16 @@ hb_font_set_variations (hb_font_t *font,
-   if (unlikely (coords_length && !normalized))
-     return;
- 
-   hb_ot_var_normalize_variations (font->face,
- 				  variations, variations_length,
- 				  normalized, coords_length);
-   _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
- }
--
- /**
-  * hb_font_set_var_coords_design:
-  *
-  * Since: 1.4.2
-  */
- void
- hb_font_set_var_coords_design (hb_font_t *font,
- 			       const float *coords,
-@@ -1874,16 +1870,17 @@ hb_font_set_var_coords_design (hb_font_t
- 
-   int *normalized = coords_length ? (int *) calloc (coords_length, sizeof (int)) : nullptr;
-   if (unlikely (coords_length && !normalized))
-     return;
- 
-   hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
-   _hb_font_adopt_var_coords_normalized (font, normalized, coords_length);
- }
-+#endif
- 
- /**
-  * hb_font_set_var_coords_normalized:
-  *
-  * Since: 1.4.2
-  */
- void
- hb_font_set_var_coords_normalized (hb_font_t *font,
-diff --git a/gfx/harfbuzz/src/hb-font.h b/gfx/harfbuzz/src/hb-font.h
---- a/gfx/harfbuzz/src/hb-font.h
-+++ b/gfx/harfbuzz/src/hb-font.h
-@@ -152,16 +152,21 @@ typedef hb_font_get_glyph_advances_func_
- 
- typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
- 						      hb_codepoint_t glyph,
- 						      hb_position_t *x, hb_position_t *y,
- 						      void *user_data);
- typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
- typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
- 
-+typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data,
-+							   hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-+							   void *user_data);
-+typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
-+
- 
- typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
- 						       hb_codepoint_t glyph,
- 						       hb_glyph_extents_t *extents,
- 						       void *user_data);
- typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
- 							     hb_codepoint_t glyph, unsigned int point_index,
- 							     hb_position_t *x, hb_position_t *y,
-@@ -352,16 +357,32 @@ hb_font_funcs_set_glyph_h_origin_func (h
-  * Since: 0.9.2
-  **/
- HB_EXTERN void
- hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
- 				       hb_font_get_glyph_v_origin_func_t func,
- 				       void *user_data, hb_destroy_func_t destroy);
- 
- /**
-+ * hb_font_funcs_set_glyph_h_kerning_func:
-+ * @ffuncs: font functions.
-+ * @func: (closure user_data) (destroy destroy) (scope notified):
-+ * @user_data:
-+ * @destroy:
-+ *
-+ * 
-+ *
-+ * Since: 0.9.2
-+ **/
-+HB_EXTERN void
-+hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs,
-+					hb_font_get_glyph_h_kerning_func_t func,
-+					void *user_data, hb_destroy_func_t destroy);
-+
-+/**
-  * hb_font_funcs_set_glyph_extents_func:
-  * @ffuncs: font functions.
-  * @func: (closure user_data) (destroy destroy) (scope notified):
-  * @user_data:
-  * @destroy:
-  *
-  * 
-  *
-@@ -464,16 +485,20 @@ HB_EXTERN hb_bool_t
- hb_font_get_glyph_h_origin (hb_font_t *font,
- 			    hb_codepoint_t glyph,
- 			    hb_position_t *x, hb_position_t *y);
- HB_EXTERN hb_bool_t
- hb_font_get_glyph_v_origin (hb_font_t *font,
- 			    hb_codepoint_t glyph,
- 			    hb_position_t *x, hb_position_t *y);
- 
-+HB_EXTERN hb_position_t
-+hb_font_get_glyph_h_kerning (hb_font_t *font,
-+			     hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
-+
- HB_EXTERN hb_bool_t
- hb_font_get_glyph_extents (hb_font_t *font,
- 			   hb_codepoint_t glyph,
- 			   hb_glyph_extents_t *extents);
- 
- HB_EXTERN hb_bool_t
- hb_font_get_glyph_contour_point (hb_font_t *font,
- 				 hb_codepoint_t glyph, unsigned int point_index,
-@@ -526,16 +551,22 @@ hb_font_add_glyph_origin_for_direction (
- 					hb_direction_t direction,
- 					hb_position_t *x, hb_position_t *y);
- HB_EXTERN void
- hb_font_subtract_glyph_origin_for_direction (hb_font_t *font,
- 					     hb_codepoint_t glyph,
- 					     hb_direction_t direction,
- 					     hb_position_t *x, hb_position_t *y);
- 
-+HB_EXTERN void
-+hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
-+					 hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-+					 hb_direction_t direction,
-+					 hb_position_t *x, hb_position_t *y);
-+
- HB_EXTERN hb_bool_t
- hb_font_get_glyph_extents_for_origin (hb_font_t *font,
- 				      hb_codepoint_t glyph,
- 				      hb_direction_t direction,
- 				      hb_glyph_extents_t *extents);
- 
- HB_EXTERN hb_bool_t
- hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
-diff --git a/gfx/harfbuzz/src/hb-font.hh b/gfx/harfbuzz/src/hb-font.hh
---- a/gfx/harfbuzz/src/hb-font.hh
-+++ b/gfx/harfbuzz/src/hb-font.hh
-@@ -46,17 +46,17 @@
-   HB_FONT_FUNC_IMPLEMENT (nominal_glyphs) \
-   HB_FONT_FUNC_IMPLEMENT (variation_glyph) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_h_advance) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_v_advance) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_h_advances) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_v_advances) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_h_origin) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_v_origin) \
--  HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning)) \
-+  HB_FONT_FUNC_IMPLEMENT (glyph_h_kerning) \
-   HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (glyph_v_kerning)) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_extents) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_name) \
-   HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
-   /* ^--- Add new callbacks here */
- 
- struct hb_font_funcs_t
-diff --git a/gfx/harfbuzz/src/hb-ft.cc b/gfx/harfbuzz/src/hb-ft.cc
---- a/gfx/harfbuzz/src/hb-ft.cc
-+++ b/gfx/harfbuzz/src/hb-ft.cc
-@@ -24,16 +24,18 @@
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Red Hat Author(s): Behdad Esfahbod
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- 
-+#ifdef HAVE_FREETYPE
-+
- #include "hb-ft.h"
- 
- #include "hb-font.hh"
- #include "hb-machinery.hh"
- #include "hb-cache.hh"
- 
- #include FT_ADVANCES_H
- #include FT_MULTIPLE_MASTERS_H
-@@ -341,16 +343,35 @@ hb_ft_get_glyph_v_origin (hb_font_t *fon
-   if (font->x_scale < 0)
-     *x = -*x;
-   if (font->y_scale < 0)
-     *y = -*y;
- 
-   return true;
- }
- 
-+#ifndef HB_NO_OT_SHAPE_FALLBACK
-+static hb_position_t
-+hb_ft_get_glyph_h_kerning (hb_font_t *font,
-+			   void *font_data,
-+			   hb_codepoint_t left_glyph,
-+			   hb_codepoint_t right_glyph,
-+			   void *user_data HB_UNUSED)
-+{
-+  const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-+  FT_Vector kerningv;
-+
-+  FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
-+  if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv))
-+    return 0;
-+
-+  return kerningv.x;
-+}
-+#endif
-+
- static hb_bool_t
- hb_ft_get_glyph_extents (hb_font_t *font,
- 			 void *font_data,
- 			 hb_codepoint_t glyph,
- 			 hb_glyph_extents_t *extents,
- 			 void *user_data HB_UNUSED)
- {
-   const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
-@@ -492,16 +513,20 @@ static struct hb_ft_font_funcs_lazy_load
-     //hb_font_funcs_set_font_v_extents_func (funcs, hb_ft_get_font_v_extents, nullptr, nullptr);
-     hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr);
-     hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ft_get_nominal_glyphs, nullptr, nullptr);
-     hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr);
-     hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr);
-     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr);
-     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr);
-     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr);
-+#ifndef HB_NO_OT_SHAPE_FALLBACK
-+    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, nullptr, nullptr);
-+#endif
-+    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, nullptr, nullptr);
-     hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, nullptr, nullptr);
-     hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, nullptr, nullptr);
-     hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
-     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
- 
-     hb_font_funcs_make_immutable (funcs);
- 
- #if HB_USE_ATEXIT
-@@ -849,8 +874,11 @@ hb_ft_font_set_funcs (hb_font_t *font)
- #endif
- 
-   ft_face->generic.data = blob;
-   ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
- 
-   _hb_ft_font_set_funcs (font, ft_face, true);
-   hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-glib.cc b/gfx/harfbuzz/src/hb-glib.cc
---- a/gfx/harfbuzz/src/hb-glib.cc
-+++ b/gfx/harfbuzz/src/hb-glib.cc
-@@ -23,16 +23,18 @@
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Red Hat Author(s): Behdad Esfahbod
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- 
-+#ifdef HAVE_GLIB
-+
- #include "hb-glib.h"
- 
- #include "hb-machinery.hh"
- 
- 
- /**
-  * SECTION:hb-glib
-  * @title: hb-glib
-@@ -399,8 +401,11 @@ hb_glib_blob_create (GBytes *gbytes)
-   gconstpointer data = g_bytes_get_data (gbytes, &size);
-   return hb_blob_create ((const char *) data,
- 			 size,
- 			 HB_MEMORY_MODE_READONLY,
- 			 g_bytes_ref (gbytes),
- 			 _hb_g_bytes_unref);
- }
- #endif
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-gobject-enums.cc.tmpl b/gfx/harfbuzz/src/hb-gobject-enums.cc.tmpl
---- a/gfx/harfbuzz/src/hb-gobject-enums.cc.tmpl
-+++ b/gfx/harfbuzz/src/hb-gobject-enums.cc.tmpl
-@@ -22,16 +22,18 @@
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- 
-+#ifdef HAVE_GOBJECT
-+
- /* g++ didn't like older gtype.h gcc-only code path. */
- #include <glib.h>
- #if !GLIB_CHECK_VERSION(2,29,16)
- #undef __GNUC__
- #undef __GNUC_MINOR__
- #define __GNUC__ 2
- #define __GNUC_MINOR__ 6
- #endif
-@@ -39,16 +41,21 @@
- #include "hb-gobject.h"
- 
- /*** END file-header ***/
- 
- /*** BEGIN file-production ***/
- /* enumerations from "@filename@" */
- /*** END file-production ***/
- 
-+/*** BEGIN file-tail ***/
-+
-+#endif
-+/*** END file-tail ***/
-+
- /*** BEGIN value-header ***/
- GType
- @enum_name@_get_type ()
- {
-   static gsize type_id = 0;
- 
-   if (g_once_init_enter (&type_id))
-     {
-diff --git a/gfx/harfbuzz/src/hb-gobject-structs.cc b/gfx/harfbuzz/src/hb-gobject-structs.cc
---- a/gfx/harfbuzz/src/hb-gobject-structs.cc
-+++ b/gfx/harfbuzz/src/hb-gobject-structs.cc
-@@ -21,16 +21,18 @@
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- 
-+#ifdef HAVE_GOBJECT
-+
- 
- /**
-  * SECTION:hb-gobject
-  * @title: hb-gobject
-  * @short_description: GObject integration
-  * @include: hb-gobject.h
-  *
-  * Functions for using HarfBuzz with the GObject library to provide
-@@ -89,8 +91,11 @@ HB_DEFINE_OBJECT_TYPE (unicode_funcs)
- HB_DEFINE_VALUE_TYPE (feature)
- HB_DEFINE_VALUE_TYPE (glyph_info)
- HB_DEFINE_VALUE_TYPE (glyph_position)
- HB_DEFINE_VALUE_TYPE (segment_properties)
- HB_DEFINE_VALUE_TYPE (user_data_key)
- 
- HB_DEFINE_VALUE_TYPE (ot_math_glyph_variant)
- HB_DEFINE_VALUE_TYPE (ot_math_glyph_part)
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-graphite2.cc b/gfx/harfbuzz/src/hb-graphite2.cc
---- a/gfx/harfbuzz/src/hb-graphite2.cc
-+++ b/gfx/harfbuzz/src/hb-graphite2.cc
-@@ -21,16 +21,20 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
-+#include "hb.hh"
-+
-+#ifdef HAVE_GRAPHITE2
-+
- #include "hb-shaper-impl.hh"
- 
- #include "hb-graphite2.h"
- 
- #include <graphite2/Segment.h>
- 
- #include "hb-ot-layout.h"
- 
-@@ -442,8 +446,11 @@ hb_bool_t
- 
-   if (feats) gr_featureval_destroy (feats);
-   gr_seg_destroy (seg);
- 
-   buffer->unsafe_to_break_all ();
- 
-   return true;
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-icu.cc b/gfx/harfbuzz/src/hb-icu.cc
---- a/gfx/harfbuzz/src/hb-icu.cc
-+++ b/gfx/harfbuzz/src/hb-icu.cc
-@@ -24,16 +24,18 @@
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Red Hat Author(s): Behdad Esfahbod
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- 
-+#ifdef HAVE_ICU
-+
- #include "hb-icu.h"
- 
- #include "hb-machinery.hh"
- 
- #include <unicode/uchar.h>
- #include <unicode/unorm2.h>
- #include <unicode/ustring.h>
- #include <unicode/utf16.h>
-@@ -346,8 +348,11 @@ void free_static_icu_funcs ()
- }
- #endif
- 
- hb_unicode_funcs_t *
- hb_icu_get_unicode_funcs ()
- {
-   return static_icu_funcs.get_unconst ();
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-mutex.hh b/gfx/harfbuzz/src/hb-mutex.hh
---- a/gfx/harfbuzz/src/hb-mutex.hh
-+++ b/gfx/harfbuzz/src/hb-mutex.hh
-@@ -101,17 +101,17 @@ typedef volatile int hb_mutex_impl_t;
- # define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END
- #endif
- 
- #define HB_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
- typedef volatile int hb_mutex_impl_t;
- #define HB_MUTEX_IMPL_INIT	0
- #define hb_mutex_impl_init(M)	*(M) = 0
- #define hb_mutex_impl_lock(M)	HB_STMT_START { while (*(M)) HB_SCHED_YIELD (); (*(M))++; } HB_STMT_END
--#define hb_mutex_impl_unlock(M)	(*(M))--;
-+#define hb_mutex_impl_unlock(M)	(*(M))--
- #define hb_mutex_impl_finish(M)	HB_STMT_START {} HB_STMT_END
- 
- 
- #else /* HB_NO_MT */
- 
- typedef int hb_mutex_impl_t;
- #define HB_MUTEX_IMPL_INIT	0
- #define hb_mutex_impl_init(M)	HB_STMT_START {} HB_STMT_END
-diff --git a/gfx/harfbuzz/src/hb-null.hh b/gfx/harfbuzz/src/hb-null.hh
---- a/gfx/harfbuzz/src/hb-null.hh
-+++ b/gfx/harfbuzz/src/hb-null.hh
-@@ -69,17 +69,17 @@ using hb_static_size = _hb_static_size<T
- #define hb_static_size(T) hb_static_size<T>::value
- 
- 
- /*
-  * Null()
-  */
- 
- extern HB_INTERNAL
--hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
-+uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)];
- 
- /* Generic nul-content Null objects. */
- template <typename Type>
- struct Null {
-   static Type const & get_null ()
-   {
-     static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-     return *reinterpret_cast<Type const *> (_hb_NullPool);
-@@ -123,17 +123,17 @@ struct NullHelper
- 
- /* Global writable pool.  Enlarge as necessary. */
- 
- /* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
-  * for correct operation. It only exist to catch and divert program logic bugs instead of
-  * causing bad memory access. So, races there are not actually introducing incorrectness
-  * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
- extern HB_INTERNAL
--/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
-+/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)];
- 
- /* CRAP pool: Common Region for Access Protection. */
- template <typename Type>
- static inline Type& Crap () {
-   static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-   Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
-   memcpy (obj, &Null(Type), sizeof (*obj));
-   return *obj;
-diff --git a/gfx/harfbuzz/src/hb-open-type.hh b/gfx/harfbuzz/src/hb-open-type.hh
---- a/gfx/harfbuzz/src/hb-open-type.hh
-+++ b/gfx/harfbuzz/src/hb-open-type.hh
-@@ -54,21 +54,21 @@ namespace OT {
- 
- /* Integer types in big-endian order and no alignment requirement */
- template <typename Type, unsigned int Size>
- struct IntType
- {
-   typedef Type type;
-   typedef hb_conditional<hb_is_signed (Type), signed, unsigned> wide_type;
- 
--  IntType<Type, Size>& operator = (wide_type i) { v = i; return *this; }
-+  IntType& operator = (wide_type i) { v = i; return *this; }
-   operator wide_type () const { return v; }
--  bool operator == (const IntType<Type,Size> &o) const { return (Type) v == (Type) o.v; }
--  bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
--  HB_INTERNAL static int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b)
-+  bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; }
-+  bool operator != (const IntType &o) const { return !(*this == o); }
-+  HB_INTERNAL static int cmp (const IntType *a, const IntType *b)
-   { return b->cmp (*a); }
-   template <typename Type2>
-   int cmp (Type2 a) const
-   {
-     Type b = v;
-     if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int))
-       return (int) a - (int) b;
-     else
-@@ -141,17 +141,17 @@ struct LONGDATETIME
-   public:
-   DEFINE_SIZE_STATIC (8);
- };
- 
- /* Array of four uint8s (length = 32 bits) used to identify a script, language
-  * system, feature, or baseline */
- struct Tag : HBUINT32
- {
--  Tag& operator = (uint32_t i) { HBUINT32::operator= (i); return *this; }
-+  Tag& operator = (hb_tag_t i) { HBUINT32::operator= (i); return *this; }
-   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
-   operator const char* () const { return reinterpret_cast<const char *> (&this->v); }
-   operator char* ()             { return reinterpret_cast<char *> (&this->v); }
-   public:
-   DEFINE_SIZE_STATIC (4);
- };
- 
- /* Glyph index number, same as uint16 (length = 16 bits) */
-diff --git a/gfx/harfbuzz/src/hb-ot-cff-common.hh b/gfx/harfbuzz/src/hb-ot-cff-common.hh
---- a/gfx/harfbuzz/src/hb-ot-cff-common.hh
-+++ b/gfx/harfbuzz/src/hb-ot-cff-common.hh
-@@ -22,16 +22,17 @@
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Adobe Author(s): Michiharu Ariza
-  */
- #ifndef HB_OT_CFF_COMMON_HH
- #define HB_OT_CFF_COMMON_HH
- 
- #include "hb-open-type.hh"
-+#include "hb-bimap.hh"
- #include "hb-ot-layout-common.hh"
- #include "hb-cff-interp-dict-common.hh"
- #include "hb-subset-plan.hh"
- 
- namespace CFF {
- 
- using namespace OT;
- 
-@@ -77,32 +78,24 @@ struct str_buff_vec_t : hb_vector_t<str_
-   private:
-   typedef hb_vector_t<str_buff_t> SUPER;
- };
- 
- /* CFF INDEX */
- template <typename COUNT>
- struct CFFIndex
- {
--  bool sanitize (hb_sanitize_context_t *c) const
--  {
--    TRACE_SANITIZE (this);
--    return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
--			  (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
--			   c->check_array (offsets, offSize, count + 1) &&
--			   c->check_array ((const HBUINT8*)data_base (), 1, max_offset () - 1))));
--  }
--
-   static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
-   { return offSize * (count + 1); }
- 
-   unsigned int offset_array_size () const
-   { return calculate_offset_array_size (offSize, count); }
- 
--  static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count, unsigned int dataSize)
-+  static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count,
-+						 unsigned int dataSize)
-   {
-     if (count == 0)
-       return COUNT::static_size;
-     else
-       return min_size + calculate_offset_array_size (offSize_, count) + dataSize;
-   }
- 
-   bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
-@@ -194,66 +187,75 @@ struct CFFIndex
-     unsigned int offset = 0;
-     for (; size; size--)
-       offset = (offset << 8) + *p++;
-     return offset;
-   }
- 
-   unsigned int length_at (unsigned int index) const
-   {
--	if (likely ((offset_at (index + 1) >= offset_at (index)) &&
--		    (offset_at (index + 1) <= offset_at (count))))
--	  return offset_at (index + 1) - offset_at (index);
--	else
--	  return 0;
-+    if (likely ((offset_at (index + 1) >= offset_at (index)) &&
-+	        (offset_at (index + 1) <= offset_at (count))))
-+      return offset_at (index + 1) - offset_at (index);
-+    else
-+      return 0;
-   }
- 
-   const unsigned char *data_base () const
-   { return (const unsigned char *)this + min_size + offset_array_size (); }
- 
-   unsigned int data_size () const { return HBINT8::static_size; }
- 
-   byte_str_t operator [] (unsigned int index) const
-   {
-     if (likely (index < count))
-       return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
-     else
--      return Null(byte_str_t);
-+      return Null (byte_str_t);
-   }
- 
-   unsigned int get_size () const
-   {
--    if (this != &Null(CFFIndex))
-+    if (this != &Null (CFFIndex))
-     {
-       if (count > 0)
- 	return min_size + offset_array_size () + (offset_at (count) - 1);
-       else
- 	return count.static_size;  /* empty CFFIndex contains count only */
-     }
-     else
-       return 0;
-   }
- 
-+  bool sanitize (hb_sanitize_context_t *c) const
-+  {
-+    TRACE_SANITIZE (this);
-+    return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
-+			  (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
-+			   c->check_array (offsets, offSize, count + 1) &&
-+			   c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1))));
-+  }
-+
-   protected:
-   unsigned int max_offset () const
-   {
-     unsigned int max = 0;
-     for (unsigned int i = 0; i < count + 1u; i++)
-     {
-       unsigned int off = offset_at (i);
-       if (off > max) max = off;
-     }
-     return max;
-   }
- 
-   public:
--  COUNT     count;	/* Number of object data. Note there are (count+1) offsets */
--  HBUINT8   offSize;      /* The byte size of each offset in the offsets array. */
--  HBUINT8   offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
--  /* HBUINT8 data[VAR];      Object data */
-+  COUNT		count;		/* Number of object data. Note there are (count+1) offsets */
-+  HBUINT8	offSize;	/* The byte size of each offset in the offsets array. */
-+  HBUINT8	offsets[VAR];	/* The array of (count + 1) offsets into objects array (1-base). */
-+  /* HBUINT8 data[VAR];	Object data */
-   public:
-   DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
- };
- 
- template <typename COUNT, typename TYPE>
- struct CFFIndexOf : CFFIndex<COUNT>
- {
-   const byte_str_t operator [] (unsigned int index) const
-@@ -288,34 +290,34 @@ struct CFFIndexOf : CFFIndex<COUNT>
-       CFFIndex<COUNT>::set_offset_at (i, offset);
-       offset += dataSizeArray[i];
-     }
-     CFFIndex<COUNT>::set_offset_at (i, offset);
- 
-     /* serialize data */
-     for (unsigned int i = 0; i < dataArrayLen; i++)
-     {
--      TYPE  *dest = c->start_embed<TYPE> ();
-+      TYPE *dest = c->start_embed<TYPE> ();
-       if (unlikely (dest == nullptr ||
- 		    !dest->serialize (c, dataArray[i], param1, param2)))
- 	return_trace (false);
-     }
-     return_trace (true);
-   }
- 
-   /* in parallel to above */
-   template <typename DATA, typename PARAM>
-   static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
- 						 const DATA *dataArray,
- 						 unsigned int dataArrayLen,
- 						 hb_vector_t<unsigned int> &dataSizeArray, /* OUT */
- 						 const PARAM &param)
-   {
-     /* determine offset size */
--    unsigned int  totalDataSize = 0;
-+    unsigned int totalDataSize = 0;
-     for (unsigned int i = 0; i < dataArrayLen; i++)
-     {
-       unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
-       dataSizeArray[i] = dataSize;
-       totalDataSize += dataSize;
-     }
-     offSize_ = calcOffSize (totalDataSize);
- 
-@@ -329,20 +331,19 @@ struct Dict : UnsizedByteStr
-   template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
-   bool serialize (hb_serialize_context_t *c,
- 		  const DICTVAL &dictval,
- 		  OP_SERIALIZER& opszr,
- 		  PARAM& param)
-   {
-     TRACE_SERIALIZE (this);
-     for (unsigned int i = 0; i < dictval.get_count (); i++)
--    {
-       if (unlikely (!opszr.serialize (c, dictval[i], param)))
- 	return_trace (false);
--    }
-+
-     return_trace (true);
-   }
- 
-   /* in parallel to above */
-   template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
-   static unsigned int calculate_serialized_size (const DICTVAL &dictval,
- 						 OP_SERIALIZER& opszr,
- 						 PARAM& param)
-@@ -386,90 +387,35 @@ struct Dict : UnsizedByteStr
- 
-   static bool serialize_uint4_op (hb_serialize_context_t *c, op_code_t op, int value)
-   { return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
- 
-   static bool serialize_uint2_op (hb_serialize_context_t *c, op_code_t op, int value)
-   { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
- 
-   static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
--  {
--    return serialize_uint4_op (c, op, value);
--  }
-+  { return serialize_uint4_op (c, op, value); }
- 
-   static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
--  {
--    return serialize_uint2_op (c, op, value);
--  }
-+  { return serialize_uint2_op (c, op, value); }
- };
- 
- struct TopDict : Dict {};
- struct FontDict : Dict {};
- struct PrivateDict : Dict {};
- 
- struct table_info_t
- {
-   void init () { offSize = offset = size = 0; }
- 
-   unsigned int    offset;
-   unsigned int    size;
-   unsigned int    offSize;
- };
- 
--/* used to remap font index or SID from fullset to subset.
-- * set to CFF_UNDEF_CODE if excluded from subset */
--struct remap_t : hb_vector_t<hb_codepoint_t>
--{
--  void init () { SUPER::init (); }
--
--  void fini () { SUPER::fini (); }
--
--  bool reset (unsigned int size)
--  {
--    if (unlikely (!SUPER::resize (size)))
--      return false;
--    for (unsigned int i = 0; i < length; i++)
--      (*this)[i] = CFF_UNDEF_CODE;
--    count = 0;
--    return true;
--  }
--
--  bool identity (unsigned int size)
--  {
--    if (unlikely (!SUPER::resize (size)))
--      return false;
--    unsigned int i;
--    for (i = 0; i < length; i++)
--      (*this)[i] = i;
--    count = i;
--    return true;
--  }
--
--  bool excludes (hb_codepoint_t id) const
--  { return (id < length) && ((*this)[id] == CFF_UNDEF_CODE); }
--
--  bool includes (hb_codepoint_t id) const
--  { return !excludes (id); }
--
--  unsigned int add (unsigned int i)
--  {
--    if ((*this)[i] == CFF_UNDEF_CODE)
--      (*this)[i] = count++;
--    return (*this)[i];
--  }
--
--  hb_codepoint_t get_count () const { return count; }
--
--  protected:
--  hb_codepoint_t  count;
--
--  private:
--  typedef hb_vector_t<hb_codepoint_t> SUPER;
--};
--
- template <typename COUNT>
- struct FDArray : CFFIndexOf<COUNT, FontDict>
- {
-   /* used by CFF1 */
-   template <typename DICTVAL, typename OP_SERIALIZER>
-   bool serialize (hb_serialize_context_t *c,
- 		  unsigned int offSize_,
- 		  const hb_vector_t<DICTVAL> &fontDicts,
-@@ -478,17 +424,17 @@ struct FDArray : CFFIndexOf<COUNT, FontD
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     this->count = fontDicts.length;
-     this->offSize = offSize_;
-     if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fontDicts.length + 1))))
-       return_trace (false);
- 
-     /* serialize font dict offsets */
--    unsigned int  offset = 1;
-+    unsigned int offset = 1;
-     unsigned int fid = 0;
-     for (; fid < fontDicts.length; fid++)
-     {
-       CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
-       offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
-     }
-     CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
- 
-@@ -503,61 +449,61 @@ struct FDArray : CFFIndexOf<COUNT, FontD
-   }
- 
-   /* used by CFF2 */
-   template <typename DICTVAL, typename OP_SERIALIZER>
-   bool serialize (hb_serialize_context_t *c,
- 		  unsigned int offSize_,
- 		  const hb_vector_t<DICTVAL> &fontDicts,
- 		  unsigned int fdCount,
--		  const remap_t &fdmap,
-+		  const hb_inc_bimap_t &fdmap,
- 		  OP_SERIALIZER& opszr,
- 		  const hb_vector_t<table_info_t> &privateInfos)
-   {
-     TRACE_SERIALIZE (this);
-     if (unlikely (!c->extend_min (*this))) return_trace (false);
-     this->count = fdCount;
-     this->offSize = offSize_;
-     if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (fdCount + 1))))
-       return_trace (false);
- 
-     /* serialize font dict offsets */
-     unsigned int  offset = 1;
-     unsigned int  fid = 0;
-     for (unsigned i = 0; i < fontDicts.length; i++)
--      if (fdmap.includes (i))
-+      if (fdmap.has (i))
-       {
-       	if (unlikely (fid >= fdCount)) return_trace (false);
- 	CFFIndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
- 	offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
-       }
-     CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
- 
-     /* serialize font dicts */
-     for (unsigned int i = 0; i < fontDicts.length; i++)
--      if (fdmap.includes (i))
-+      if (fdmap.has (i))
-       {
- 	FontDict *dict = c->start_embed<FontDict> ();
- 	if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]])))
- 	  return_trace (false);
-       }
-     return_trace (true);
-   }
- 
-   /* in parallel to above */
-   template <typename OP_SERIALIZER, typename DICTVAL>
-   static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
- 						 const hb_vector_t<DICTVAL> &fontDicts,
- 						 unsigned int fdCount,
--						 const remap_t &fdmap,
-+						 const hb_inc_bimap_t &fdmap,
- 						 OP_SERIALIZER& opszr)
-   {
-     unsigned int dictsSize = 0;
-     for (unsigned int i = 0; i < fontDicts.len; i++)
--      if (fdmap.includes (i))
-+      if (fdmap.has (i))
- 	dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
- 
-     offSize_ = calcOffSize (dictsSize);
-     return CFFIndex<COUNT>::calculate_serialized_size (offSize_, fdCount, dictsSize);
-   }
- };
- 
- /* FDSelect */
-@@ -570,59 +516,57 @@ struct FDSelect0 {
-     for (unsigned int i = 0; i < c->get_num_glyphs (); i++)
-       if (unlikely (!fds[i].sanitize (c)))
- 	return_trace (false);
- 
-     return_trace (true);
-   }
- 
-   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
--  {
--    return (hb_codepoint_t)fds[glyph];
--  }
-+  { return (hb_codepoint_t) fds[glyph]; }
- 
-   unsigned int get_size (unsigned int num_glyphs) const
-   { return HBUINT8::static_size * num_glyphs; }
- 
-   HBUINT8     fds[VAR];
- 
-   DEFINE_SIZE_MIN (1);
- };
- 
- template <typename GID_TYPE, typename FD_TYPE>
--struct FDSelect3_4_Range {
-+struct FDSelect3_4_Range
-+{
-   bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (first < c->get_num_glyphs () && (fd < fdcount));
-   }
- 
-   GID_TYPE    first;
-   FD_TYPE     fd;
--
-+  public:
-   DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
- };
- 
- template <typename GID_TYPE, typename FD_TYPE>
--struct FDSelect3_4 {
-+struct FDSelect3_4
-+{
-   unsigned int get_size () const
-   { return GID_TYPE::static_size * 2 + ranges.get_size (); }
- 
-   bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!c->check_struct (this) || !ranges.sanitize (c, nullptr, fdcount) ||
-     		  (nRanges () == 0) || ranges[0].first != 0))
-       return_trace (false);
- 
-     for (unsigned int i = 1; i < nRanges (); i++)
--    {
-       if (unlikely (ranges[i - 1].first >= ranges[i].first))
--	  return_trace (false);
--    }
-+	return_trace (false);
- 
-     if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
-       return_trace (false);
- 
-     return_trace (true);
-   }
- 
-   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
-@@ -644,66 +588,73 @@ struct FDSelect3_4 {
-   /* GID_TYPE sentinel */
- 
-   DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges);
- };
- 
- typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
- typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
- 
--struct FDSelect {
--  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
--  {
--    TRACE_SANITIZE (this);
--
--    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
--			  (format == 0)?
--			  u.format0.sanitize (c, fdcount):
--			  u.format3.sanitize (c, fdcount)));
--  }
--
-+struct FDSelect
-+{
-   bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
-   {
-     TRACE_SERIALIZE (this);
-     unsigned int size = src.get_size (num_glyphs);
-     FDSelect *dest = c->allocate_size<FDSelect> (size);
-     if (unlikely (dest == nullptr)) return_trace (false);
-     memcpy (dest, &src, size);
-     return_trace (true);
-   }
- 
-   unsigned int calculate_serialized_size (unsigned int num_glyphs) const
-   { return get_size (num_glyphs); }
- 
-   unsigned int get_size (unsigned int num_glyphs) const
-   {
--    unsigned int size = format.static_size;
--    if (format == 0)
--      size += u.format0.get_size (num_glyphs);
--    else
--      size += u.format3.get_size ();
--    return size;
-+    switch (format)
-+    {
-+    case 0: return format.static_size + u.format0.get_size (num_glyphs);
-+    case 3: return format.static_size + u.format3.get_size ();
-+    default:return 0;
-+    }
-   }
- 
-   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
-   {
--    if (this == &Null(FDSelect))
-+    if (this == &Null (FDSelect))
-       return 0;
--    if (format == 0)
--      return u.format0.get_fd (glyph);
--    else
--      return u.format3.get_fd (glyph);
-+    switch (format)
-+    {
-+    case 0: return u.format0.get_fd (glyph);
-+    case 3: return u.format3.get_fd (glyph);
-+    default:return 0;
-+    }
-   }
- 
--  HBUINT8       format;
-+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
-+  {
-+    TRACE_SANITIZE (this);
-+    if (unlikely (!c->check_struct (this)))
-+      return_trace (false);
-+
-+    switch (format)
-+    {
-+    case 0: return_trace (u.format0.sanitize (c, fdcount));
-+    case 3: return_trace (u.format3.sanitize (c, fdcount));
-+    default:return_trace (false);
-+    }
-+  }
-+
-+  HBUINT8	format;
-   union {
--    FDSelect0   format0;
--    FDSelect3   format3;
-+  FDSelect0	format0;
-+  FDSelect3	format3;
-   } u;
--
-+  public:
-   DEFINE_SIZE_MIN (1);
- };
- 
- template <typename COUNT>
- struct Subrs : CFFIndex<COUNT>
- {
-   typedef COUNT count_type;
-   typedef CFFIndex<COUNT> SUPER;
-diff --git a/gfx/harfbuzz/src/hb-ot-cff1-table.cc b/gfx/harfbuzz/src/hb-ot-cff1-table.cc
---- a/gfx/harfbuzz/src/hb-ot-cff1-table.cc
-+++ b/gfx/harfbuzz/src/hb-ot-cff1-table.cc
-@@ -19,21 +19,23 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Adobe Author(s): Michiharu Ariza
-  */
- 
-+#include "hb.hh"
-+
-+#ifndef HB_NO_CFF
-+
- #include "hb-ot-cff1-table.hh"
- #include "hb-cff1-interp-cs.hh"
- 
--#ifndef HB_NO_CFF
--
- using namespace CFF;
- 
- /* SID to code */
- static const uint8_t standard_encoding_to_code [] =
- {
-     0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46,
-    47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62,
-    63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78,
-@@ -386,9 +388,10 @@ bool OT::cff1::accelerator_t::get_seac_c
-   {
-     *base = param.base;
-     *accent = param.accent;
-     return true;
-   }
-   return false;
- }
- 
-+
- #endif
-diff --git a/gfx/harfbuzz/src/hb-ot-cff1-table.hh b/gfx/harfbuzz/src/hb-ot-cff1-table.hh
---- a/gfx/harfbuzz/src/hb-ot-cff1-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-cff1-table.hh
-@@ -156,31 +156,18 @@ struct CFF1SuppEncData {
-   HBUINT8 &nSups () { return supps.len; }
-   HBUINT8 nSups () const { return supps.len; }
- 
-   ArrayOf<SuppEncoding, HBUINT8> supps;
- 
-   DEFINE_SIZE_ARRAY_SIZED (1, supps);
- };
- 
--struct Encoding {
--  bool sanitize (hb_sanitize_context_t *c) const
--  {
--    TRACE_SANITIZE (this);
--
--    if (unlikely (!c->check_struct (this)))
--      return_trace (false);
--    unsigned int fmt = format & 0x7F;
--    if (unlikely (fmt > 1))
--      return_trace (false);
--    if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
--      return_trace (false);
--    return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
--  }
--
-+struct Encoding
-+{
-   /* serialize a fullset Encoding */
-   bool serialize (hb_serialize_context_t *c, const Encoding &src)
-   {
-     TRACE_SERIALIZE (this);
-     unsigned int size = src.get_size ();
-     Encoding *dest = c->allocate_size<Encoding> (size);
-     if (unlikely (dest == nullptr)) return_trace (false);
-     memcpy (dest, &src, size);
-@@ -192,119 +179,148 @@ struct Encoding {
- 		  uint8_t format,
- 		  unsigned int enc_count,
- 		  const hb_vector_t<code_pair_t>& code_ranges,
- 		  const hb_vector_t<code_pair_t>& supp_codes)
-   {
-     TRACE_SERIALIZE (this);
-     Encoding *dest = c->extend_min (*this);
-     if (unlikely (dest == nullptr)) return_trace (false);
--    dest->format = format | ((supp_codes.length > 0)? 0x80: 0);
--    if (format == 0)
-+    dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
-+    switch (format) {
-+    case 0:
-     {
-       Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
--    if (unlikely (fmt0 == nullptr)) return_trace (false);
-+      if (unlikely (fmt0 == nullptr)) return_trace (false);
-       fmt0->nCodes () = enc_count;
-       unsigned int glyph = 0;
-       for (unsigned int i = 0; i < code_ranges.length; i++)
-       {
- 	hb_codepoint_t code = code_ranges[i].code;
- 	for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
- 	  fmt0->codes[glyph++] = code++;
- 	if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
- 	  return_trace (false);
-       }
-     }
--    else
-+    break;
-+
-+    case 1:
-     {
-       Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
-       if (unlikely (fmt1 == nullptr)) return_trace (false);
-       fmt1->nRanges () = code_ranges.length;
-       for (unsigned int i = 0; i < code_ranges.length; i++)
-       {
- 	if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
- 	  return_trace (false);
- 	fmt1->ranges[i].first = code_ranges[i].code;
- 	fmt1->ranges[i].nLeft = code_ranges[i].glyph;
-       }
-     }
--    if (supp_codes.length > 0)
-+    break;
-+
-+    }
-+
-+    if (supp_codes.length)
-     {
-       CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
-       if (unlikely (suppData == nullptr)) return_trace (false);
-       suppData->nSups () = supp_codes.length;
-       for (unsigned int i = 0; i < supp_codes.length; i++)
-       {
- 	suppData->supps[i].code = supp_codes[i].code;
- 	suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
-       }
-     }
-+
-     return_trace (true);
-   }
- 
-   /* parallel to above: calculate the size of a subset Encoding */
-   static unsigned int calculate_serialized_size (uint8_t format,
- 						 unsigned int enc_count,
- 						 unsigned int supp_count)
-   {
--    unsigned int  size = min_size;
--    if (format == 0)
--      size += Encoding0::min_size + HBUINT8::static_size * enc_count;
--    else
--      size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
-+    unsigned int size = min_size;
-+    switch (format)
-+    {
-+    case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break;
-+    case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break;
-+    default:return 0;
-+    }
-     if (supp_count > 0)
-       size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
-     return size;
-   }
- 
-   unsigned int get_size () const
-   {
-     unsigned int size = min_size;
--    if (table_format () == 0)
--      size += u.format0.get_size ();
--    else
--      size += u.format1.get_size ();
-+    switch (table_format ())
-+    {
-+    case 0: size += u.format0.get_size (); break;
-+    case 1: size += u.format1.get_size (); break;
-+    }
-     if (has_supplement ())
-       size += suppEncData ().get_size ();
-     return size;
-   }
- 
-   hb_codepoint_t get_code (hb_codepoint_t glyph) const
-   {
--    if (table_format () == 0)
--      return u.format0.get_code (glyph);
--    else
--      return u.format1.get_code (glyph);
-+    switch (table_format ())
-+    {
-+    case 0: return u.format0.get_code (glyph);
-+    case 1: return u.format1.get_code (glyph);
-+    default:return 0;
-+    }
-   }
- 
--  uint8_t table_format () const { return (format & 0x7F); }
--  bool  has_supplement () const { return (format & 0x80) != 0; }
-+  uint8_t table_format () const { return format & 0x7F; }
-+  bool  has_supplement () const { return format & 0x80; }
- 
-   void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
-   {
-     codes.resize (0);
-     if (has_supplement ())
-       suppEncData().get_codes (sid, codes);
-   }
- 
-+  bool sanitize (hb_sanitize_context_t *c) const
-+  {
-+    TRACE_SANITIZE (this);
-+    if (unlikely (!c->check_struct (this)))
-+      return_trace (false);
-+
-+    switch (table_format ())
-+    {
-+    case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
-+    case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
-+    default:return_trace (false);
-+    }
-+    return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
-+  }
-+
-   protected:
-   const CFF1SuppEncData &suppEncData () const
-   {
--    if ((format & 0x7F) == 0)
--      return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
--    else
--      return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
-+    switch (table_format ())
-+    {
-+    case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
-+    case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
-+    default:return Null (CFF1SuppEncData);
-+    }
-   }
- 
-   public:
--  HBUINT8       format;
--
-+  HBUINT8	format;
-   union {
--    Encoding0   format0;
--    Encoding1   format1;
-+  Encoding0	format0;
-+  Encoding1	format1;
-   } u;
-   /* CFF1SuppEncData  suppEncData; */
- 
-   DEFINE_SIZE_MIN (1);
- };
- 
- /* Charset */
- struct Charset0 {
-@@ -428,33 +444,18 @@ struct Charset1_2 {
-   DEFINE_SIZE_ARRAY (0, ranges);
- };
- 
- typedef Charset1_2<HBUINT8>     Charset1;
- typedef Charset1_2<HBUINT16>    Charset2;
- typedef Charset_Range<HBUINT8>  Charset1_Range;
- typedef Charset_Range<HBUINT16> Charset2_Range;
- 
--struct Charset {
--  bool sanitize (hb_sanitize_context_t *c) const
--  {
--    TRACE_SANITIZE (this);
--
--    if (unlikely (!c->check_struct (this)))
--      return_trace (false);
--    if (format == 0)
--      return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
--    else if (format == 1)
--      return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
--    else if (likely (format == 2))
--      return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
--    else
--      return_trace (false);
--  }
--
-+struct Charset
-+{
-   /* serialize a fullset Charset */
-   bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
-   {
-     TRACE_SERIALIZE (this);
-     unsigned int size = src.get_size (num_glyphs);
-     Charset *dest = c->allocate_size<Charset> (size);
-     if (unlikely (dest == nullptr)) return_trace (false);
-     memcpy (dest, &src, size);
-@@ -466,157 +467,179 @@ struct Charset {
- 		  uint8_t format,
- 		  unsigned int num_glyphs,
- 		  const hb_vector_t<code_pair_t>& sid_ranges)
-   {
-     TRACE_SERIALIZE (this);
-     Charset *dest = c->extend_min (*this);
-     if (unlikely (dest == nullptr)) return_trace (false);
-     dest->format = format;
--    if (format == 0)
-+    switch (format)
-+    {
-+    case 0:
-     {
-       Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
--    if (unlikely (fmt0 == nullptr)) return_trace (false);
-+      if (unlikely (fmt0 == nullptr)) return_trace (false);
-       unsigned int glyph = 0;
-       for (unsigned int i = 0; i < sid_ranges.length; i++)
-       {
- 	hb_codepoint_t sid = sid_ranges[i].code;
- 	for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
- 	  fmt0->sids[glyph++] = sid++;
-       }
-     }
--    else if (format == 1)
-+    break;
-+
-+    case 1:
-     {
-       Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
-       if (unlikely (fmt1 == nullptr)) return_trace (false);
-       for (unsigned int i = 0; i < sid_ranges.length; i++)
-       {
-       	if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
- 	  return_trace (false);
- 	fmt1->ranges[i].first = sid_ranges[i].code;
- 	fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
-       }
-     }
--    else /* format 2 */
-+    break;
-+
-+    case 2:
-     {
-       Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
-       if (unlikely (fmt2 == nullptr)) return_trace (false);
-       for (unsigned int i = 0; i < sid_ranges.length; i++)
-       {
-       	if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
- 	  return_trace (false);
- 	fmt2->ranges[i].first = sid_ranges[i].code;
- 	fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
-       }
-     }
-+    break;
-+
-+    }
-     return_trace (true);
-   }
- 
-   /* parallel to above: calculate the size of a subset Charset */
--  static unsigned int calculate_serialized_size (
--			uint8_t format,
--			unsigned int count)
-+  static unsigned int calculate_serialized_size (uint8_t format,
-+						 unsigned int count)
-   {
--    unsigned int  size = min_size;
--    if (format == 0)
--      size += Charset0::min_size + HBUINT16::static_size * (count - 1);
--    else if (format == 1)
--      size += Charset1::min_size + Charset1_Range::static_size * count;
--    else
--      size += Charset2::min_size + Charset2_Range::static_size * count;
--
--    return size;
-+    switch (format)
-+    {
-+    case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1);
-+    case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count;
-+    case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count;
-+    default:return 0;
-+    }
-   }
- 
-   unsigned int get_size (unsigned int num_glyphs) const
-   {
--    unsigned int size = min_size;
--    if (format == 0)
--      size += u.format0.get_size (num_glyphs);
--    else if (format == 1)
--      size += u.format1.get_size (num_glyphs);
--    else
--      size += u.format2.get_size (num_glyphs);
--    return size;
-+    switch (format)
-+    {
-+    case 0: return min_size + u.format0.get_size (num_glyphs);
-+    case 1: return min_size + u.format1.get_size (num_glyphs);
-+    case 2: return min_size + u.format2.get_size (num_glyphs);
-+    default:return 0;
-+    }
-   }
- 
-   hb_codepoint_t get_sid (hb_codepoint_t glyph) const
-   {
--    if (format == 0)
--      return u.format0.get_sid (glyph);
--    else if (format == 1)
--      return u.format1.get_sid (glyph);
--    else
--      return u.format2.get_sid (glyph);
-+    switch (format)
-+    {
-+    case 0: return u.format0.get_sid (glyph);
-+    case 1: return u.format1.get_sid (glyph);
-+    case 2: return u.format2.get_sid (glyph);
-+    default:return 0;
-+    }
-   }
- 
-   hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
-   {
--    if (format == 0)
--      return u.format0.get_glyph (sid, num_glyphs);
--    else if (format == 1)
--      return u.format1.get_glyph (sid, num_glyphs);
--    else
--      return u.format2.get_glyph (sid, num_glyphs);
-+    switch (format)
-+    {
-+    case 0: return u.format0.get_glyph (sid, num_glyphs);
-+    case 1: return u.format1.get_glyph (sid, num_glyphs);
-+    case 2: return u.format2.get_glyph (sid, num_glyphs);
-+    default:return 0;
-+    }
-+  }
-+
-+  bool sanitize (hb_sanitize_context_t *c) const
-+  {
-+    TRACE_SANITIZE (this);
-+    if (unlikely (!c->check_struct (this)))
-+      return_trace (false);
-+
-+    switch (format)
-+    {
-+    case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
-+    case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
-+    case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
-+    default:return_trace (false);
-+    }
-   }
- 
-   HBUINT8       format;
-   union {
-     Charset0    format0;
-     Charset1    format1;
-     Charset2    format2;
-   } u;
- 
-   DEFINE_SIZE_MIN (1);
- };
- 
- struct CFF1StringIndex : CFF1Index
- {
-   bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
--		  unsigned int offSize_, const remap_t &sidmap)
-+		  unsigned int offSize_, const hb_inc_bimap_t &sidmap)
-   {
-     TRACE_SERIALIZE (this);
--    if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
-+    if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
-     {
-       if (unlikely (!c->extend_min (this->count)))
- 	return_trace (false);
-       count = 0;
-       return_trace (true);
-     }
- 
-     byte_str_array_t bytesArray;
-     bytesArray.init ();
--    if (!bytesArray.resize (sidmap.get_count ()))
-+    if (!bytesArray.resize (sidmap.get_population ()))
-       return_trace (false);
-     for (unsigned int i = 0; i < strings.count; i++)
-     {
-       hb_codepoint_t  j = sidmap[i];
-       if (j != CFF_UNDEF_CODE)
- 	bytesArray[j] = strings[i];
-     }
- 
-     bool result = CFF1Index::serialize (c, offSize_, bytesArray);
-     bytesArray.fini ();
-     return_trace (result);
-   }
- 
-   /* in parallel to above */
--  unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const remap_t &sidmap) const
-+  unsigned int calculate_serialized_size (unsigned int &offSize_ /*OUT*/, const hb_inc_bimap_t &sidmap) const
-   {
-     offSize_ = 0;
--    if ((count == 0) || (sidmap.get_count () == 0))
-+    if ((count == 0) || (sidmap.get_population () == 0))
-       return count.static_size;
- 
-     unsigned int dataSize = 0;
-     for (unsigned int i = 0; i < count; i++)
-       if (sidmap[i] != CFF_UNDEF_CODE)
- 	dataSize += length_at (i);
- 
-     offSize_ = calcOffSize(dataSize);
--    return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_count (), dataSize);
-+    return CFF1Index::calculate_serialized_size (offSize_, sidmap.get_population (), dataSize);
-   }
- };
- 
- struct cff1_top_dict_interp_env_t : num_interp_env_t
- {
-   cff1_top_dict_interp_env_t ()
-     : num_interp_env_t(), prev_offset(0), last_offset(0) {}
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-cff2-table.cc b/gfx/harfbuzz/src/hb-ot-cff2-table.cc
---- a/gfx/harfbuzz/src/hb-ot-cff2-table.cc
-+++ b/gfx/harfbuzz/src/hb-ot-cff2-table.cc
-@@ -19,21 +19,23 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Adobe Author(s): Michiharu Ariza
-  */
- 
-+#include "hb.hh"
-+
-+#ifndef HB_NO_OT_FONT_CFF
-+
- #include "hb-ot-cff2-table.hh"
- #include "hb-cff2-interp-cs.hh"
- 
--#ifndef HB_NO_OT_FONT_CFF
--
- using namespace CFF;
- 
- struct extents_param_t
- {
-   void init ()
-   {
-     path_open = false;
-     min_x.set_int (INT_MAX);
-@@ -137,9 +139,10 @@ bool OT::cff2::accelerator_t::get_extent
-   {
-     extents->y_bearing = (int32_t)param.max_y.ceil ();
-     extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
-   }
- 
-   return true;
- }
- 
-+
- #endif
-diff --git a/gfx/harfbuzz/src/hb-ot-cff2-table.hh b/gfx/harfbuzz/src/hb-ot-cff2-table.hh
---- a/gfx/harfbuzz/src/hb-ot-cff2-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-cff2-table.hh
-@@ -46,72 +46,76 @@ typedef CFF2Index         CFF2CharString
- typedef FDArray<HBUINT32> CFF2FDArray;
- typedef Subrs<HBUINT32>   CFF2Subrs;
- 
- typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
- typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
- 
- struct CFF2FDSelect
- {
--  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
--  {
--    TRACE_SANITIZE (this);
--
--    return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) &&
--			  (format == 0)?
--			  u.format0.sanitize (c, fdcount):
--			    ((format == 3)?
--			    u.format3.sanitize (c, fdcount):
--			    u.format4.sanitize (c, fdcount))));
--  }
--
-   bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
-   {
-     TRACE_SERIALIZE (this);
-     unsigned int size = src.get_size (num_glyphs);
-     CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
-     if (unlikely (dest == nullptr)) return_trace (false);
-     memcpy (dest, &src, size);
-     return_trace (true);
-   }
- 
-   unsigned int calculate_serialized_size (unsigned int num_glyphs) const
-   { return get_size (num_glyphs); }
- 
-   unsigned int get_size (unsigned int num_glyphs) const
-   {
--    unsigned int size = format.static_size;
--    if (format == 0)
--      size += u.format0.get_size (num_glyphs);
--    else if (format == 3)
--      size += u.format3.get_size ();
--    else
--      size += u.format4.get_size ();
--    return size;
-+    switch (format)
-+    {
-+    case 0: return format.static_size + u.format0.get_size (num_glyphs);
-+    case 3: return format.static_size + u.format3.get_size ();
-+    case 4: return format.static_size + u.format4.get_size ();
-+    default:return 0;
-+    }
-   }
- 
-   hb_codepoint_t get_fd (hb_codepoint_t glyph) const
-   {
--    if (this == &Null(CFF2FDSelect))
-+    if (this == &Null (CFF2FDSelect))
-       return 0;
--    if (format == 0)
--      return u.format0.get_fd (glyph);
--    else if (format == 3)
--      return u.format3.get_fd (glyph);
--    else
--      return u.format4.get_fd (glyph);
-+
-+    switch (format)
-+    {
-+    case 0: return u.format0.get_fd (glyph);
-+    case 3: return u.format3.get_fd (glyph);
-+    case 4: return u.format4.get_fd (glyph);
-+    default:return 0;
-+    }
-   }
- 
--  HBUINT8       format;
-+  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
-+  {
-+    TRACE_SANITIZE (this);
-+    if (unlikely (!c->check_struct (this)))
-+      return_trace (false);
-+
-+    switch (format)
-+    {
-+    case 0: return_trace (u.format0.sanitize (c, fdcount));
-+    case 3: return_trace (u.format3.sanitize (c, fdcount));
-+    case 4: return_trace (u.format4.sanitize (c, fdcount));
-+    default:return_trace (false);
-+    }
-+  }
-+
-+  HBUINT8	format;
-   union {
--    FDSelect0   format0;
--    FDSelect3   format3;
--    FDSelect4   format4;
-+  FDSelect0	format0;
-+  FDSelect3	format3;
-+  FDSelect4	format4;
-   } u;
--
-+  public:
-   DEFINE_SIZE_MIN (2);
- };
- 
- struct CFF2VariationStore
- {
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-diff --git a/gfx/harfbuzz/src/hb-ot-cmap-table.hh b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
---- a/gfx/harfbuzz/src/hb-ot-cmap-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-cmap-table.hh
-@@ -751,63 +751,71 @@ struct CmapSubtableFormat14
- struct CmapSubtable
- {
-   /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
- 
-   bool get_glyph (hb_codepoint_t codepoint,
- 		  hb_codepoint_t *glyph) const
-   {
-     switch (u.format) {
-+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
-     case  0: return u.format0 .get_glyph (codepoint, glyph);
--    case  4: return u.format4 .get_glyph (codepoint, glyph);
-     case  6: return u.format6 .get_glyph (codepoint, glyph);
-     case 10: return u.format10.get_glyph (codepoint, glyph);
-+#endif
-+    case  4: return u.format4 .get_glyph (codepoint, glyph);
-     case 12: return u.format12.get_glyph (codepoint, glyph);
-     case 13: return u.format13.get_glyph (codepoint, glyph);
-     case 14:
-     default: return false;
-     }
-   }
-   void collect_unicodes (hb_set_t *out) const
-   {
-     switch (u.format) {
-+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
-     case  0: u.format0 .collect_unicodes (out); return;
--    case  4: u.format4 .collect_unicodes (out); return;
-     case  6: u.format6 .collect_unicodes (out); return;
-     case 10: u.format10.collect_unicodes (out); return;
-+#endif
-+    case  4: u.format4 .collect_unicodes (out); return;
-     case 12: u.format12.collect_unicodes (out); return;
-     case 13: u.format13.collect_unicodes (out); return;
-     case 14:
-     default: return;
-     }
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!u.format.sanitize (c)) return_trace (false);
-     switch (u.format) {
-+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
-     case  0: return_trace (u.format0 .sanitize (c));
--    case  4: return_trace (u.format4 .sanitize (c));
-     case  6: return_trace (u.format6 .sanitize (c));
-     case 10: return_trace (u.format10.sanitize (c));
-+#endif
-+    case  4: return_trace (u.format4 .sanitize (c));
-     case 12: return_trace (u.format12.sanitize (c));
-     case 13: return_trace (u.format13.sanitize (c));
-     case 14: return_trace (u.format14.sanitize (c));
-     default:return_trace (true);
-     }
-   }
- 
-   public:
-   union {
-   HBUINT16		format;		/* Format identifier */
-+#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
-   CmapSubtableFormat0	format0;
--  CmapSubtableFormat4	format4;
-   CmapSubtableFormat6	format6;
-   CmapSubtableFormat10	format10;
-+#endif
-+  CmapSubtableFormat4	format4;
-   CmapSubtableFormat12	format12;
-   CmapSubtableFormat13	format13;
-   CmapSubtableFormat14	format14;
-   } u;
-   public:
-   DEFINE_SIZE_UNION (2, format);
- };
- 
-@@ -843,28 +851,39 @@ struct cmap
- {
-   static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
- 
-   struct subset_plan
-   {
-     size_t final_size () const
-     {
-       return 4 // header
--	  +  8 * 3 // 3 EncodingRecord
-+	  +  8 * num_enc_records
- 	  +  CmapSubtableFormat4::get_sub_table_size (this->format4_segments)
- 	  +  CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
-     }
- 
-+    unsigned int num_enc_records;
-+    bool has_unicode_bmp;
-+    bool has_unicode_ucs4;
-+    bool has_ms_bmp;
-+    bool has_ms_ucs4;
-     hb_sorted_vector_t<CmapSubtableFormat4::segment_plan> format4_segments;
-     hb_sorted_vector_t<CmapSubtableLongGroup> format12_groups;
-   };
- 
-   bool _create_plan (const hb_subset_plan_t *plan,
- 		     subset_plan *cmap_plan) const
-   {
-+    cmap_plan->has_unicode_bmp = find_subtable (0, 3);
-+    cmap_plan->has_unicode_ucs4 = find_subtable (0, 4);
-+    cmap_plan->has_ms_bmp = find_subtable (3, 1);
-+    cmap_plan->has_ms_ucs4 = find_subtable (3, 10);
-+    cmap_plan->num_enc_records = cmap_plan->has_unicode_bmp + cmap_plan->has_unicode_ucs4 + cmap_plan->has_ms_bmp + cmap_plan->has_ms_ucs4;
-+  
-     if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments)))
-       return false;
- 
-     if (!find_subtable (12)) return true;
-     return CmapSubtableFormat12::create_sub_table_plan (plan, &cmap_plan->format12_groups);
-   }
- 
-   bool _subset (const hb_subset_plan_t *plan,
-@@ -877,54 +896,88 @@ struct cmap
-     cmap *table = c.start_serialize<cmap> ();
-     if (unlikely (!c.extend_min (*table)))
-     {
-       return false;
-     }
- 
-     table->version = 0;
- 
--    if (unlikely (!table->encodingRecord.serialize (&c, /* numTables */ cmap_subset_plan.format12_groups ? 3 : 2))) return false;
-+    if (unlikely (!table->encodingRecord.serialize (&c, cmap_subset_plan.num_enc_records))) return false;
- 
-     // TODO(grieger): Convert the below to a for loop
-+    int enc_index = 0;
-+    int unicode_bmp_index = 0;
-+    int unicode_ucs4_index = 0;
-+    int ms_bmp_index = 0;
-+    int ms_ucs4_index = 0;
- 
-     // Format 4, Plat 0 Encoding Record
--    EncodingRecord &format4_plat0_rec = table->encodingRecord[0];
--    format4_plat0_rec.platformID = 0; // Unicode
--    format4_plat0_rec.encodingID = 3;
-+    if (cmap_subset_plan.has_unicode_bmp)
-+    {
-+      unicode_bmp_index = enc_index;
-+      EncodingRecord &format4_plat0_rec = table->encodingRecord[enc_index++];
-+      format4_plat0_rec.platformID = 0; // Unicode
-+      format4_plat0_rec.encodingID = 3;
-+    }
-+
-+    // Format 12, Plat 0 Encoding Record
-+    if (cmap_subset_plan.has_unicode_ucs4)
-+    {
-+      unicode_ucs4_index = enc_index;
-+      EncodingRecord &format12_rec = table->encodingRecord[enc_index++];
-+      format12_rec.platformID = 0; // Unicode
-+      format12_rec.encodingID = 4; // Unicode UCS-4
-+    }
- 
-     // Format 4, Plat 3 Encoding Record
--    EncodingRecord &format4_plat3_rec = table->encodingRecord[1];
--    format4_plat3_rec.platformID = 3; // Windows
--    format4_plat3_rec.encodingID = 1; // Unicode BMP
-+    if (cmap_subset_plan.has_ms_bmp)
-+    {
-+      ms_bmp_index = enc_index;
-+      EncodingRecord &format4_plat3_rec = table->encodingRecord[enc_index++];
-+      format4_plat3_rec.platformID = 3; // Windows
-+      format4_plat3_rec.encodingID = 1; // Unicode BMP
-+    }
- 
--    // Format 12 Encoding Record
--    if (cmap_subset_plan.format12_groups)
-+    // Format 12, Plat 3 Encoding Record
-+    if (cmap_subset_plan.has_ms_ucs4)
-     {
--      EncodingRecord &format12_rec = table->encodingRecord[2];
-+      ms_ucs4_index = enc_index;
-+      EncodingRecord &format12_rec = table->encodingRecord[enc_index++];
-       format12_rec.platformID = 3; // Windows
-       format12_rec.encodingID = 10; // Unicode UCS-4
-     }
- 
-     // Write out format 4 sub table
-     {
--      CmapSubtable &subtable = format4_plat0_rec.subtable.serialize (&c, table);
--      format4_plat3_rec.subtable = (unsigned int) format4_plat0_rec.subtable;
-+      if (unlikely (!cmap_subset_plan.has_unicode_bmp && !cmap_subset_plan.has_ms_bmp)) return false;
-+      EncodingRecord &format4_rec = cmap_subset_plan.has_unicode_bmp?
-+				     table->encodingRecord[unicode_bmp_index]:
-+				     table->encodingRecord[ms_bmp_index];
-+      CmapSubtable &subtable = format4_rec.subtable.serialize (&c, table);
-+      if (cmap_subset_plan.has_unicode_bmp && cmap_subset_plan.has_ms_bmp)
-+      	table->encodingRecord[ms_bmp_index].subtable = (unsigned int) format4_rec.subtable;
-       subtable.u.format = 4;
- 
-       CmapSubtableFormat4 &format4 = subtable.u.format4;
-       if (unlikely (!format4.serialize (&c, plan, cmap_subset_plan.format4_segments)))
- 	return false;
-     }
- 
-     // Write out format 12 sub table.
-     if (cmap_subset_plan.format12_groups)
-     {
--      EncodingRecord &format12_rec = table->encodingRecord[2];
-+      if (unlikely (!cmap_subset_plan.has_unicode_ucs4 && !cmap_subset_plan.has_ms_ucs4)) return false;
-+      EncodingRecord &format12_rec = cmap_subset_plan.has_unicode_ucs4?
-+				     table->encodingRecord[unicode_ucs4_index]:
-+				     table->encodingRecord[ms_ucs4_index];
-+
-       CmapSubtable &subtable = format12_rec.subtable.serialize (&c, table);
-+      if (cmap_subset_plan.has_unicode_ucs4 && cmap_subset_plan.has_ms_ucs4)
-+      	table->encodingRecord[ms_ucs4_index].subtable = (unsigned int) format12_rec.subtable;
-       subtable.u.format = 12;
- 
-       CmapSubtableFormat12 &format12 = subtable.u.format12;
-       if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups)))
- 	return false;
-     }
- 
-     c.end_serialize ();
-diff --git a/gfx/harfbuzz/src/hb-ot-color.cc b/gfx/harfbuzz/src/hb-ot-color.cc
---- a/gfx/harfbuzz/src/hb-ot-color.cc
-+++ b/gfx/harfbuzz/src/hb-ot-color.cc
-@@ -20,30 +20,31 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Sascha Brawer, Behdad Esfahbod
-  */
- 
--#include "hb-open-type.hh"
-+#include "hb.hh"
-+
-+#ifndef HB_NO_COLOR
-+
-+#include "hb-ot.h"
-+
- #include "hb-ot-color-cbdt-table.hh"
- #include "hb-ot-color-colr-table.hh"
- #include "hb-ot-color-cpal-table.hh"
- #include "hb-ot-color-sbix-table.hh"
- #include "hb-ot-color-svg-table.hh"
--#include "hb-ot-face.hh"
--#include "hb-ot.h"
- 
- #include <stdlib.h>
- #include <string.h>
- 
--#include "hb-ot-layout.hh"
--
- 
- /**
-  * SECTION:hb-ot-color
-  * @title: hb-ot-color
-  * @short_description: OpenType Color Fonts
-  * @include: hb-ot.h
-  *
-  * Functions for fetching color-font information from OpenType font faces.
-@@ -65,38 +66,32 @@
-  *
-  * Return value: true if data found, false otherwise
-  *
-  * Since: 2.1.0
-  */
- hb_bool_t
- hb_ot_color_has_palettes (hb_face_t *face)
- {
--#ifdef HB_NO_COLOR
--  return false;
--#endif
-   return face->table.CPAL->has_data ();
- }
- 
- /**
-  * hb_ot_color_palette_get_count:
-  * @face: #hb_face_t to work upon
-  *
-  * Fetches the number of color palettes in a face.
-  *
-  * Return value: the number of palettes found
-  *
-  * Since: 2.1.0
-  */
- unsigned int
- hb_ot_color_palette_get_count (hb_face_t *face)
- {
--#ifdef HB_NO_COLOR
--  return 0;
--#endif
-   return face->table.CPAL->get_palette_count ();
- }
- 
- /**
-  * hb_ot_color_palette_get_name_id:
-  * @face: #hb_face_t to work upon
-  * @palette_index: The index of the color palette 
-  *
-@@ -110,19 +105,16 @@ hb_ot_color_palette_get_count (hb_face_t
-  * If the requested palette has no name the result is #HB_OT_NAME_ID_INVALID.
-  *
-  * Since: 2.1.0
-  */
- hb_ot_name_id_t
- hb_ot_color_palette_get_name_id (hb_face_t *face,
- 				 unsigned int palette_index)
- {
--#ifdef HB_NO_COLOR
--  return HB_OT_NAME_ID_INVALID;
--#endif
-   return face->table.CPAL->get_palette_name_id (palette_index);
- }
- 
- /**
-  * hb_ot_color_palette_color_get_name_id:
-  * @face: #hb_face_t to work upon
-  * @color_index: The index of the color
-  *
-@@ -135,19 +127,16 @@ hb_ot_color_palette_get_name_id (hb_face
-  * Return value: the Name ID found for the color.
-  *
-  * Since: 2.1.0
-  */
- hb_ot_name_id_t
- hb_ot_color_palette_color_get_name_id (hb_face_t *face,
- 				       unsigned int color_index)
- {
--#ifdef HB_NO_COLOR
--  return HB_OT_NAME_ID_INVALID;
--#endif
-   return face->table.CPAL->get_color_name_id (color_index);
- }
- 
- /**
-  * hb_ot_color_palette_get_flags:
-  * @face: #hb_face_t to work upon
-  * @palette_index: The index of the color palette
-  *
-@@ -156,19 +145,16 @@ hb_ot_color_palette_color_get_name_id (h
-  * Return value: the #hb_ot_color_palette_flags_t of the requested color palette
-  *
-  * Since: 2.1.0
-  */
- hb_ot_color_palette_flags_t
- hb_ot_color_palette_get_flags (hb_face_t *face,
- 			       unsigned int palette_index)
- {
--#ifdef HB_NO_COLOR
--  return HB_OT_COLOR_PALETTE_FLAG_DEFAULT;
--#endif
-   return face->table.CPAL->get_palette_flags (palette_index);
- }
- 
- /**
-  * hb_ot_color_palette_get_colors:
-  * @face: #hb_face_t to work upon
-  * @palette_index: the index of the color palette to query
-  * @start_offset: offset of the first color to retrieve
-@@ -190,21 +176,16 @@ hb_ot_color_palette_get_flags (hb_face_t
-  */
- unsigned int
- hb_ot_color_palette_get_colors (hb_face_t     *face,
- 				unsigned int   palette_index,
- 				unsigned int   start_offset,
- 				unsigned int  *colors_count  /* IN/OUT.  May be NULL. */,
- 				hb_color_t    *colors        /* OUT.     May be NULL. */)
- {
--#ifdef HB_NO_COLOR
--  if (colors_count)
--    *colors_count = 0;
--  return 0;
--#endif
-   return face->table.CPAL->get_palette_colors (palette_index, start_offset, colors_count, colors);
- }
- 
- 
- /*
-  * COLR
-  */
- 
-@@ -216,19 +197,16 @@ hb_ot_color_palette_get_colors (hb_face_
-  *
-  * Return value: true if data found, false otherwise
-  *
-  * Since: 2.1.0
-  */
- hb_bool_t
- hb_ot_color_has_layers (hb_face_t *face)
- {
--#ifdef HB_NO_COLOR
--  return false;
--#endif
-   return face->table.COLR->has_data ();
- }
- 
- /**
-  * hb_ot_color_glyph_get_layers:
-  * @face: #hb_face_t to work upon
-  * @glyph: The glyph index to query
-  * @start_offset: offset of the first layer to retrieve
-@@ -245,21 +223,16 @@ hb_ot_color_has_layers (hb_face_t *face)
-  */
- unsigned int
- hb_ot_color_glyph_get_layers (hb_face_t           *face,
- 			      hb_codepoint_t       glyph,
- 			      unsigned int         start_offset,
- 			      unsigned int        *layer_count, /* IN/OUT.  May be NULL. */
- 			      hb_ot_color_layer_t *layers /* OUT.     May be NULL. */)
- {
--#ifdef HB_NO_COLOR
--  if (layer_count)
--    *layer_count = 0;
--  return 0;
--#endif
-   return face->table.COLR->get_glyph_layers (glyph, start_offset, layer_count, layers);
- }
- 
- 
- /*
-  * SVG
-  */
- 
-@@ -271,19 +244,16 @@ hb_ot_color_glyph_get_layers (hb_face_t 
-  *
-  * Return value: true if data found, false otherwise.
-  *
-  * Since: 2.1.0
-  */
- hb_bool_t
- hb_ot_color_has_svg (hb_face_t *face)
- {
--#ifdef HB_NO_COLOR
--  return false;
--#endif
-   return face->table.SVG->has_data ();
- }
- 
- /**
-  * hb_ot_color_glyph_reference_svg:
-  * @face: #hb_face_t to work upon
-  * @glyph: a svg glyph index
-  *
-@@ -291,19 +261,16 @@ hb_ot_color_has_svg (hb_face_t *face)
-  *
-  * Return value: (transfer full): An #hb_blob_t containing the SVG document of the glyph, if available
-  *
-  * Since: 2.1.0
-  */
- hb_blob_t *
- hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
- {
--#ifdef HB_NO_COLOR
--  return hb_blob_get_empty ();
--#endif
-   return face->table.SVG->reference_blob_for_glyph (glyph);
- }
- 
- 
- /*
-  * PNG: CBDT or sbix
-  */
- 
-@@ -315,19 +282,16 @@ hb_ot_color_glyph_reference_svg (hb_face
-  *
-  * Return value: true if data found, false otherwise
-  *
-  * Since: 2.1.0
-  */
- hb_bool_t
- hb_ot_color_has_png (hb_face_t *face)
- {
--#ifdef HB_NO_COLOR
--  return false;
--#endif
-   return face->table.CBDT->has_data () || face->table.sbix->has_data ();
- }
- 
- /**
-  * hb_ot_color_glyph_reference_png:
-  * @font: #hb_font_t to work upon
-  * @glyph: a glyph index
-  *
-@@ -337,22 +301,21 @@ hb_ot_color_has_png (hb_face_t *face)
-  *
-  * Return value: (transfer full): An #hb_blob_t containing the PNG image for the glyph, if available
-  *
-  * Since: 2.1.0
-  */
- hb_blob_t *
- hb_ot_color_glyph_reference_png (hb_font_t *font, hb_codepoint_t  glyph)
- {
--#ifdef HB_NO_COLOR
--  return hb_blob_get_empty ();
--#endif
--
-   hb_blob_t *blob = hb_blob_get_empty ();
- 
-   if (font->face->table.sbix->has_data ())
-     blob = font->face->table.sbix->reference_png (font, glyph, nullptr, nullptr, nullptr);
- 
-   if (!blob->length && font->face->table.CBDT->has_data ())
-     blob = font->face->table.CBDT->reference_png (font, glyph);
- 
-   return blob;
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-ot-face-table-list.hh b/gfx/harfbuzz/src/hb-ot-face-table-list.hh
-new file mode 100644
---- /dev/null
-+++ b/gfx/harfbuzz/src/hb-ot-face-table-list.hh
-@@ -0,0 +1,126 @@
-+/*
-+ * Copyright © 2007,2008,2009  Red Hat, Inc.
-+ * Copyright © 2012,2013  Google, Inc.
-+ * Copyright © 2019, Facebook Inc.
-+ *
-+ *  This is part of HarfBuzz, a text shaping library.
-+ *
-+ * Permission is hereby granted, without written agreement and without
-+ * license or royalty fees, to use, copy, modify, and distribute this
-+ * software and its documentation for any purpose, provided that the
-+ * above copyright notice and the following two paragraphs appear in
-+ * all copies of this software.
-+ *
-+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
-+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
-+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
-+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
-+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-+ *
-+ * Red Hat Author(s): Behdad Esfahbod
-+ * Google Author(s): Behdad Esfahbod
-+ * Facebook Author(s): Behdad Esfahbod
-+ */
-+
-+#ifndef HB_OT_FACE_TABLE_LIST_HH
-+#define HB_OT_FACE_TABLE_LIST_HH
-+#endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */
-+
-+#ifndef HB_OT_ACCELERATOR
-+#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
-+#define _HB_OT_ACCELERATOR_UNDEF
-+#endif
-+
-+
-+/* This lists font tables that the hb_face_t will contain and lazily
-+ * load.  Don't add a table unless it's used though.  This is not
-+ * exactly free. */
-+
-+/* v--- Add new tables in the right place here. */
-+
-+
-+/* OpenType fundamentals. */
-+HB_OT_TABLE (OT, head)
-+#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
-+HB_OT_ACCELERATOR (OT, cmap)
-+#endif
-+HB_OT_ACCELERATOR (OT, hmtx)
-+HB_OT_TABLE (OT, OS2)
-+#ifndef HB_NO_OT_FONT_GLYPH_NAMES
-+HB_OT_ACCELERATOR (OT, post)
-+#endif
-+#ifndef HB_NO_NAME
-+HB_OT_ACCELERATOR (OT, name)
-+#endif
-+#ifndef HB_NO_STAT
-+HB_OT_TABLE (OT, STAT)
-+#endif
-+
-+/* Vertical layout. */
-+HB_OT_ACCELERATOR (OT, vmtx)
-+
-+/* TrueType outlines. */
-+HB_OT_ACCELERATOR (OT, glyf)
-+
-+/* CFF outlines. */
-+#ifndef HB_NO_CFF
-+HB_OT_ACCELERATOR (OT, cff1)
-+HB_OT_ACCELERATOR (OT, cff2)
-+HB_OT_TABLE (OT, VORG)
-+#endif
-+
-+/* OpenType variations. */
-+#ifndef HB_NO_VAR
-+HB_OT_TABLE (OT, fvar)
-+HB_OT_TABLE (OT, avar)
-+HB_OT_TABLE (OT, MVAR)
-+#endif
-+
-+/* Legacy kern. */
-+#ifndef HB_NO_OT_KERN
-+HB_OT_TABLE (OT, kern)
-+#endif
-+
-+/* OpenType shaping. */
-+HB_OT_ACCELERATOR (OT, GDEF)
-+HB_OT_ACCELERATOR (OT, GSUB)
-+HB_OT_ACCELERATOR (OT, GPOS)
-+//HB_OT_TABLE (OT, BASE)
-+//HB_OT_TABLE (OT, JSTF)
-+
-+/* AAT shaping. */
-+#ifndef HB_NO_AAT
-+HB_OT_TABLE (AAT, morx)
-+HB_OT_TABLE (AAT, mort)
-+HB_OT_TABLE (AAT, kerx)
-+HB_OT_TABLE (AAT, ankr)
-+HB_OT_TABLE (AAT, trak)
-+HB_OT_TABLE (AAT, lcar)
-+HB_OT_TABLE (AAT, ltag)
-+HB_OT_TABLE (AAT, feat)
-+#endif
-+
-+/* OpenType color fonts. */
-+#ifndef HB_NO_COLOR
-+HB_OT_TABLE (OT, COLR)
-+HB_OT_TABLE (OT, CPAL)
-+HB_OT_ACCELERATOR (OT, CBDT)
-+HB_OT_ACCELERATOR (OT, sbix)
-+HB_OT_ACCELERATOR (OT, SVG)
-+#endif
-+
-+/* OpenType math. */
-+#ifndef HB_NO_MATH
-+HB_OT_TABLE (OT, MATH)
-+#endif
-+
-+
-+#ifdef _HB_OT_ACCELERATOR_UNDEF
-+#undef HB_OT_ACCELERATOR
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-ot-face.cc b/gfx/harfbuzz/src/hb-ot-face.cc
---- a/gfx/harfbuzz/src/hb-ot-face.cc
-+++ b/gfx/harfbuzz/src/hb-ot-face.cc
-@@ -41,21 +41,17 @@
- #include "hb-ot-layout-gsub-table.hh"
- #include "hb-ot-layout-gpos-table.hh"
- 
- 
- void hb_ot_face_t::init0 (hb_face_t *face)
- {
-   this->face = face;
- #define HB_OT_TABLE(Namespace, Type) Type.init0 ();
--#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
--  HB_OT_TABLES
--#undef HB_OT_ACCELERATOR
-+#include "hb-ot-face-table-list.hh"
- #undef HB_OT_TABLE
- }
- void hb_ot_face_t::fini ()
- {
- #define HB_OT_TABLE(Namespace, Type) Type.fini ();
--#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
--  HB_OT_TABLES
--#undef HB_OT_ACCELERATOR
-+#include "hb-ot-face-table-list.hh"
- #undef HB_OT_TABLE
- }
-diff --git a/gfx/harfbuzz/src/hb-ot-face.hh b/gfx/harfbuzz/src/hb-ot-face.hh
---- a/gfx/harfbuzz/src/hb-ot-face.hh
-+++ b/gfx/harfbuzz/src/hb-ot-face.hh
-@@ -33,88 +33,42 @@
- 
- #include "hb-machinery.hh"
- 
- 
- /*
-  * hb_ot_face_t
-  */
- 
--#define HB_OT_TABLES \
--    /* OpenType fundamentals. */ \
--    HB_OT_TABLE(OT, head) \
--    HB_OT_ACCELERATOR(OT, cmap) \
--    HB_OT_ACCELERATOR(OT, hmtx) \
--    HB_OT_ACCELERATOR(OT, vmtx) \
--    HB_OT_ACCELERATOR(OT, post) \
--    HB_OT_TABLE(OT, kern) \
--    HB_OT_ACCELERATOR(OT, glyf) \
--    HB_OT_ACCELERATOR(OT, cff1) \
--    HB_OT_ACCELERATOR(OT, cff2) \
--    HB_OT_TABLE(OT, VORG) \
--    HB_OT_ACCELERATOR(OT, name) \
--    HB_OT_TABLE(OT, OS2) \
--    HB_OT_TABLE(OT, STAT) \
--    /* OpenType shaping. */ \
--    HB_OT_ACCELERATOR(OT, GDEF) \
--    HB_OT_ACCELERATOR(OT, GSUB) \
--    HB_OT_ACCELERATOR(OT, GPOS) \
--    HB_OT_TABLE(OT, BASE) \
--    HB_OT_TABLE(OT, JSTF) \
--    /* AAT shaping. */ \
--    HB_OT_TABLE(AAT, mort) \
--    HB_OT_TABLE(AAT, morx) \
--    HB_OT_TABLE(AAT, kerx) \
--    HB_OT_TABLE(AAT, ankr) \
--    HB_OT_TABLE(AAT, trak) \
--    HB_OT_TABLE(AAT, lcar) \
--    HB_OT_TABLE(AAT, ltag) \
--    HB_OT_TABLE(AAT, feat) \
--    /* OpenType variations. */ \
--    HB_OT_TABLE(OT, fvar) \
--    HB_OT_TABLE(OT, avar) \
--    HB_OT_TABLE(OT, MVAR) \
--    /* OpenType math. */ \
--    HB_OT_TABLE(OT, MATH) \
--    /* OpenType color fonts. */ \
--    HB_OT_TABLE(OT, COLR) \
--    HB_OT_TABLE(OT, CPAL) \
--    HB_OT_ACCELERATOR(OT, CBDT) \
--    HB_OT_ACCELERATOR(OT, sbix) \
--    HB_OT_ACCELERATOR(OT, SVG) \
--    /* */
--
- /* Declare tables. */
- #define HB_OT_TABLE(Namespace, Type) namespace Namespace { struct Type; }
- #define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type##_accelerator_t)
--HB_OT_TABLES
-+#include "hb-ot-face-table-list.hh"
- #undef HB_OT_ACCELERATOR
- #undef HB_OT_TABLE
- 
- struct hb_ot_face_t
- {
-   HB_INTERNAL void init0 (hb_face_t *face);
-   HB_INTERNAL void fini ();
- 
- #define HB_OT_TABLE_ORDER(Namespace, Type) \
-     HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
-   enum order_t
-   {
-     ORDER_ZERO,
- #define HB_OT_TABLE(Namespace, Type) HB_OT_TABLE_ORDER (Namespace, Type),
--#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
--    HB_OT_TABLES
--#undef HB_OT_ACCELERATOR
-+#include "hb-ot-face-table-list.hh"
- #undef HB_OT_TABLE
-   };
- 
-   hb_face_t *face; /* MUST be JUST before the lazy loaders. */
- #define HB_OT_TABLE(Namespace, Type) \
-   hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
- #define HB_OT_ACCELERATOR(Namespace, Type) \
-   hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
--  HB_OT_TABLES
-+#include "hb-ot-face-table-list.hh"
- #undef HB_OT_ACCELERATOR
- #undef HB_OT_TABLE
- };
- 
- 
- #endif /* HB_OT_FACE_HH */
-diff --git a/gfx/harfbuzz/src/hb-ot-font.cc b/gfx/harfbuzz/src/hb-ot-font.cc
---- a/gfx/harfbuzz/src/hb-ot-font.cc
-+++ b/gfx/harfbuzz/src/hb-ot-font.cc
-@@ -21,28 +21,29 @@
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod, Roozbeh Pournader
-  */
- 
- #include "hb.hh"
- 
-+#ifndef HB_NO_OT_FONT
-+
- #include "hb-ot.h"
- 
- #include "hb-font.hh"
- #include "hb-machinery.hh"
- #include "hb-ot-face.hh"
- 
- #include "hb-ot-cmap-table.hh"
- #include "hb-ot-glyf-table.hh"
- #include "hb-ot-cff1-table.hh"
- #include "hb-ot-cff2-table.hh"
- #include "hb-ot-hmtx-table.hh"
--#include "hb-ot-kern-table.hh"
- #include "hb-ot-os2-table.hh"
- #include "hb-ot-post-table.hh"
- #include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
- #include "hb-ot-vorg-table.hh"
- #include "hb-ot-color-cbdt-table.hh"
- #include "hb-ot-color-sbix-table.hh"
- 
- 
-@@ -144,22 +145,24 @@ hb_ot_get_glyph_v_origin (hb_font_t *fon
- 			  hb_position_t *x,
- 			  hb_position_t *y,
- 			  void *user_data HB_UNUSED)
- {
-   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
- 
-   *x = font->get_glyph_h_advance (glyph) / 2;
- 
-+#ifndef HB_NO_OT_FONT_CFF
-   const OT::VORG &VORG = *ot_face->VORG;
-   if (VORG.has_data ())
-   {
-     *y = font->em_scale_y (VORG.get_y_origin (glyph));
-     return true;
-   }
-+#endif
- 
-   hb_glyph_extents_t extents = {0};
-   if (ot_face->glyf->get_extents (glyph, &extents))
-   {
-     const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
-     hb_position_t tsb = vmtx.get_side_bearing (glyph);
-     *y = font->em_scale_y (extents.y_bearing + tsb);
-     return true;
-@@ -197,37 +200,38 @@ hb_ot_get_glyph_extents (hb_font_t *font
-   // TODO Hook up side-bearings variations.
-   extents->x_bearing = font->em_scale_x (extents->x_bearing);
-   extents->y_bearing = font->em_scale_y (extents->y_bearing);
-   extents->width     = font->em_scale_x (extents->width);
-   extents->height    = font->em_scale_y (extents->height);
-   return ret;
- }
- 
-+#ifndef HB_NO_OT_FONT_GLYPH_NAMES
- static hb_bool_t
- hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
-                       void *font_data,
-                       hb_codepoint_t glyph,
-                       char *name, unsigned int size,
-                       void *user_data HB_UNUSED)
- {
-   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
-   return ot_face->post->get_glyph_name (glyph, name, size);
- }
--
- static hb_bool_t
- hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
-                            void *font_data,
-                            const char *name, int len,
-                            hb_codepoint_t *glyph,
-                            void *user_data HB_UNUSED)
- {
-   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
-   return ot_face->post->get_glyph_from_name (name, len, glyph);
- }
-+#endif
- 
- static hb_bool_t
- hb_ot_get_font_h_extents (hb_font_t *font,
- 			  void *font_data,
- 			  hb_font_extents_t *metrics,
- 			  void *user_data HB_UNUSED)
- {
-   const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
-@@ -270,18 +274,20 @@ static struct hb_ot_font_funcs_lazy_load
-     hb_font_funcs_set_nominal_glyphs_func (funcs, hb_ot_get_nominal_glyphs, nullptr, nullptr);
-     hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr);
-     hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
-     hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
-     //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
-     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
-     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
-     //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
-+#ifndef HB_NO_OT_FONT_GLYPH_NAMES
-     hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, nullptr, nullptr);
-     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, nullptr, nullptr);
-+#endif
- 
-     hb_font_funcs_make_immutable (funcs);
- 
- #if HB_USE_ATEXIT
-     atexit (free_static_ot_funcs);
- #endif
- 
-     return funcs;
-@@ -311,8 +317,11 @@ static hb_font_funcs_t *
- void
- hb_ot_font_set_funcs (hb_font_t *font)
- {
-   hb_font_set_funcs (font,
- 		     _hb_ot_get_font_funcs (),
- 		     &font->face->table,
- 		     nullptr);
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-ot-glyf-table.hh b/gfx/harfbuzz/src/hb-ot-glyf-table.hh
---- a/gfx/harfbuzz/src/hb-ot-glyf-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-glyf-table.hh
-@@ -175,17 +175,17 @@ struct glyf
-   _populate_subset_glyphs (const hb_subset_plan_t * plan,
- 			   hb_vector_t<SubsetGlyph> * glyphs /* OUT */) const
-   {
-     OT::glyf::accelerator_t glyf;
-     glyf.init (plan->source);
- 
-     + hb_range (plan->num_output_glyphs ())
-     | hb_map ([&] (hb_codepoint_t new_gid) {
--      SubsetGlyph subset_glyph;
-+      SubsetGlyph subset_glyph = {0};
-       subset_glyph.new_gid = new_gid;
- 
-       // should never fail: all old gids should be mapped
-       if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid)) return subset_glyph;
- 
-       subset_glyph.source_glyph = glyf.bytes_for_glyph ((const char *) this, subset_glyph.old_gid);
-       if (plan->drop_hints) subset_glyph.drop_hints (glyf);
-       else subset_glyph.dest_start = subset_glyph.source_glyph;
-diff --git a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
---- a/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-hmtx-table.hh
-@@ -81,84 +81,81 @@ struct hmtxvmtx
-     table->numberOfLongMetrics = num_hmetrics;
- 
-     bool result = plan->add_table (H::tableTag, dest_blob);
-     hb_blob_destroy (dest_blob);
- 
-     return result;
-   }
- 
--  bool subset (hb_subset_plan_t *plan) const
-+  template<typename Iterator,
-+           hb_requires (hb_is_iterator (Iterator))>
-+  void serialize (hb_serialize_context_t *c, 
-+                  Iterator it, 
-+                  unsigned num_advances)
-   {
--    typename T::accelerator_t _mtx;
--    _mtx.init (plan->source);
--
--    /* All the trailing glyphs with the same advance can use one LongMetric
--     * and just keep LSB */
--    unsigned int num_output_glyphs = plan->num_output_glyphs ();
--    unsigned int num_advances = _mtx.num_advances_for_subset (plan);
--
--    /* alloc the new table */
--    size_t dest_sz = num_advances * 4
--		  + (num_output_glyphs - num_advances) * 2;
--    void *dest = (void *) malloc (dest_sz);
--    if (unlikely (!dest))
--    {
--      return false;
--    }
--    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
--    DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes",
--              HB_UNTAG(T::tableTag), num_advances, num_output_glyphs - num_advances, (unsigned int) dest_sz);
--
--    // Copy everything over
--    char * dest_pos = (char *) dest;
-+    unsigned idx = 0;
-+    + it
-+    | hb_apply ([c, &idx, num_advances] (const hb_item_type<Iterator>& _)
-+                {
-+                  if (idx < num_advances) 
-+                  {
-+                    LongMetric lm;
-+                    lm.advance = _.first;
-+                    lm.sb = _.second;
-+                    if (unlikely (!c->embed<LongMetric> (&lm))) return;
-+                  } 
-+                  else 
-+                  {
-+                    FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
-+                    if (unlikely (!sb)) return;
-+                    *sb = _.second;
-+                  }
-+                  idx++;
-+                })
-+    ;
-+  }
- 
--    bool failed = false;
--    for (unsigned int i = 0; i < num_output_glyphs; i++)
--    {
--      unsigned int side_bearing = 0;
--      unsigned int advance = 0;
--      hb_codepoint_t old_gid;
--      if (plan->old_gid_for_new_gid (i, &old_gid))
--      {
--        // Glyph is not an empty glyph so copy advance and side bearing
--        // from the input font.
--        side_bearing = _mtx.get_side_bearing (old_gid);
--        advance = _mtx.get_advance (old_gid);
--      }
-+  bool subset (hb_subset_context_t *c) const
-+  {
-+    TRACE_SUBSET (this);
- 
--      bool has_advance = i < num_advances;
--      if (has_advance)
--      {
--        ((LongMetric *) dest_pos)->advance = advance;
--        ((LongMetric *) dest_pos)->sb = side_bearing;
--      }
--      else
--      {
--        *((FWORD *) dest_pos) = side_bearing;
--      }
--      dest_pos += (has_advance ? 4 : 2);
--    }
-+    T *table_prime = c->serializer->start_embed <T> ();
-+    if (unlikely (!table_prime)) return_trace (false);
-+    
-+    accelerator_t _mtx;
-+    _mtx.init (c->plan->source);
-+    unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
-+    
-+    auto it = 
-+    + hb_range (c->plan->num_output_glyphs ())
-+    | hb_map ([c, &_mtx] (unsigned _)
-+	{
-+	  hb_codepoint_t old_gid;
-+	  if (c->plan->old_gid_for_new_gid (_, &old_gid))
-+            return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
-+          else
-+	    return hb_pair (0u, 0u);
-+	})
-+    ;
-+
-+    table_prime->serialize (c->serializer, it, num_advances);
-+
-     _mtx.fini ();
- 
-+    if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ()))
-+      return_trace (false);
-+
-     // Amend header num hmetrics
--    if (failed || unlikely (!subset_update_header (plan, num_advances)))
-+    if (unlikely (!subset_update_header (c->plan, num_advances)))
-     {
--      free (dest);
--      return false;
-+      return_trace (false);
-     }
- 
--    hb_blob_t *result = hb_blob_create ((const char *)dest,
--                                        dest_sz,
--                                        HB_MEMORY_MODE_READONLY,
--                                        dest,
--                                        free);
--    bool success = plan->add_table (T::tableTag, result);
--    hb_blob_destroy (result);
--    return success;
-+    return_trace (true);
-   }
- 
-   struct accelerator_t
-   {
-     friend struct hmtxvmtx;
- 
-     void init (hb_face_t *face,
-                unsigned int default_advance_ = 0)
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-common.hh b/gfx/harfbuzz/src/hb-ot-layout-common.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-common.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-common.hh
-@@ -494,46 +494,49 @@ struct FeatureParamsCharacterVariants
-   public:
-   DEFINE_SIZE_ARRAY (14, characters);
- };
- 
- struct FeatureParams
- {
-   bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
-   {
-+#ifdef HB_NO_LAYOUT_FEATURE_PARAMS
-+    return true;
-+#endif
-     TRACE_SANITIZE (this);
-     if (tag == HB_TAG ('s','i','z','e'))
-       return_trace (u.size.sanitize (c));
-     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
-       return_trace (u.stylisticSet.sanitize (c));
-     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
-       return_trace (u.characterVariants.sanitize (c));
-     return_trace (true);
-   }
- 
-+#ifndef HB_NO_LAYOUT_FEATURE_PARAMS
-   const FeatureParamsSize& get_size_params (hb_tag_t tag) const
-   {
-     if (tag == HB_TAG ('s','i','z','e'))
-       return u.size;
-     return Null (FeatureParamsSize);
-   }
--
-   const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
-   {
-     if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
-       return u.stylisticSet;
-     return Null (FeatureParamsStylisticSet);
-   }
--
-   const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
-   {
-     if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
-       return u.characterVariants;
-     return Null (FeatureParamsCharacterVariants);
-   }
-+#endif
- 
-   private:
-   union {
-   FeatureParamsSize			size;
-   FeatureParamsStylisticSet		stylisticSet;
-   FeatureParamsCharacterVariants	characterVariants;
-   } u;
-   public:
-@@ -1742,21 +1745,21 @@ struct VarData
-    return delta;
-   }
- 
-   void get_scalars (int *coords, unsigned int coord_count,
-                     const VarRegionList &regions,
-                     float *scalars /*OUT */,
-                     unsigned int num_scalars) const
-   {
--    assert (num_scalars == regionIndices.len);
--   for (unsigned int i = 0; i < num_scalars; i++)
--   {
--     scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
--   }
-+    unsigned count = hb_min (num_scalars, regionIndices.len);
-+    for (unsigned int i = 0; i < count; i++)
-+      scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
-+    for (unsigned int i = count; i < num_scalars; i++)
-+      scalars[i] = 0.f;
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  regionIndices.sanitize (c) &&
- 		  shortCount <= regionIndices.len &&
-@@ -1774,49 +1777,63 @@ struct VarData
-   DEFINE_SIZE_ARRAY (6, regionIndices);
- };
- 
- struct VariationStore
- {
-   float get_delta (unsigned int outer, unsigned int inner,
- 		   const int *coords, unsigned int coord_count) const
-   {
-+#ifdef HB_NO_VAR
-+    return 0.f;
-+#endif
-+
-     if (unlikely (outer >= dataSets.len))
--      return 0.;
-+      return 0.f;
- 
-     return (this+dataSets[outer]).get_delta (inner,
- 					     coords, coord_count,
- 					     this+regions);
-   }
- 
-   float get_delta (unsigned int index,
- 		   const int *coords, unsigned int coord_count) const
-   {
-     unsigned int outer = index >> 16;
-     unsigned int inner = index & 0xFFFF;
-     return get_delta (outer, inner, coords, coord_count);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-+#ifdef HB_NO_VAR
-+    return true;
-+#endif
-+
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
- 		  format == 1 &&
- 		  regions.sanitize (c, this) &&
- 		  dataSets.sanitize (c, this));
-   }
- 
-   unsigned int get_region_index_count (unsigned int ivs) const
-   { return (this+dataSets[ivs]).get_region_index_count (); }
- 
-   void get_scalars (unsigned int ivs,
- 		    int *coords, unsigned int coord_count,
- 		    float *scalars /*OUT*/,
- 		    unsigned int num_scalars) const
-   {
-+#ifdef HB_NO_VAR
-+    for (unsigned i = 0; i < num_scalars; i++)
-+      scalars[i] = 0.f;
-+    return;
-+#endif
-+
-     (this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
-                                       &scalars[0], num_scalars);
-   }
- 
-   protected:
-   HBUINT16				format;
-   LOffsetTo<VarRegionList>		regions;
-   LOffsetArrayOf<VarData>		dataSets;
-@@ -2147,56 +2164,70 @@ struct DeviceHeader
- };
- 
- struct Device
- {
-   hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
-   {
-     switch (u.b.format)
-     {
-+#ifndef HB_NO_HINTING
-     case 1: case 2: case 3:
-       return u.hinting.get_x_delta (font);
-+#endif
-+#ifndef HB_NO_VAR
-     case 0x8000:
-       return u.variation.get_x_delta (font, store);
-+#endif
-     default:
-       return 0;
-     }
-   }
-   hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
-   {
-     switch (u.b.format)
-     {
-     case 1: case 2: case 3:
-+#ifndef HB_NO_HINTING
-       return u.hinting.get_y_delta (font);
-+#endif
-+#ifndef HB_NO_VAR
-     case 0x8000:
-       return u.variation.get_y_delta (font, store);
-+#endif
-     default:
-       return 0;
-     }
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (!u.b.format.sanitize (c)) return_trace (false);
-     switch (u.b.format) {
-+#ifndef HB_NO_HINTING
-     case 1: case 2: case 3:
-       return_trace (u.hinting.sanitize (c));
-+#endif
-+#ifndef HB_NO_VAR
-     case 0x8000:
-       return_trace (u.variation.sanitize (c));
-+#endif
-     default:
-       return_trace (true);
-     }
-   }
- 
-   protected:
-   union {
-   DeviceHeader		b;
-   HintingDevice		hinting;
-+#ifndef HB_NO_VAR
-   VariationDevice	variation;
-+#endif
-   } u;
-   public:
-   DEFINE_SIZE_UNION (6, b);
- };
- 
- 
- } /* namespace OT */
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-gpos-table.hh
-@@ -262,16 +262,23 @@ struct AnchorFormat1
- };
- 
- struct AnchorFormat2
- {
-   void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
- 		   float *x, float *y) const
-   {
-     hb_font_t *font = c->font;
-+
-+#ifdef HB_NO_HINTING
-+    *x = font->em_fscale_x (xCoordinate);
-+    *y = font->em_fscale_y (yCoordinate);
-+    return;
-+#endif
-+
-     unsigned int x_ppem = font->x_ppem;
-     unsigned int y_ppem = font->y_ppem;
-     hb_position_t cx = 0, cy = 0;
-     bool ret;
- 
-     ret = (x_ppem || y_ppem) &&
- 	  font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
-     *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
-diff --git a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
---- a/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
-+++ b/gfx/harfbuzz/src/hb-ot-layout-gsubgpos.hh
-@@ -2656,29 +2656,36 @@ struct GSUBGPOS
- 
-   unsigned int get_lookup_count () const
-   { return (this+lookupList).len; }
-   const Lookup& get_lookup (unsigned int i) const
-   { return (this+lookupList)[i]; }
- 
-   bool find_variations_index (const int *coords, unsigned int num_coords,
- 			      unsigned int *index) const
--  { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
--	   .find_index (coords, num_coords, index); }
-+  {
-+#ifdef HB_NOVAR
-+    return false;
-+#endif
-+    return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
-+	    .find_index (coords, num_coords, index);
-+  }
-   const Feature& get_feature_variation (unsigned int feature_index,
- 					unsigned int variations_index) const
-   {
-+#ifndef HB_NO_VAR
-     if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
- 	version.to_int () >= 0x00010001u)
-     {
-       const Feature *feature = (this+featureVars).find_substitute (variations_index,
- 								   feature_index);
-       if (feature)
- 	return *feature;
-     }
-+#endif
-     return get_feature (feature_index);
-   }
- 
-   template <typename TLookup>
-   bool subset (hb_subset_context_t *c) const
-   {
-     TRACE_SUBSET (this);
-     auto *out = c->serializer->embed (*this);
-@@ -2690,39 +2697,48 @@ struct GSUBGPOS
-     typedef OffsetListOf<TLookup> TLookupList;
-     /* TODO Use intersects() to count how many subtables survive? */
-     CastR<OffsetTo<TLookupList>> (out->lookupList)
-       .serialize_subset (c,
- 			 CastR<OffsetTo<TLookupList>> (lookupList),
- 			 this,
- 			 out);
- 
-+#ifndef HB_NO_VAR
-     if (version.to_int () >= 0x00010001u)
-      out->featureVars.serialize_copy (c->serializer, featureVars, this, out);
-+#endif
- 
-     return_trace (true);
-   }
- 
-   unsigned int get_size () const
-   {
-     return min_size +
- 	   (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
-   }
- 
-   template <typename TLookup>
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     typedef OffsetListOf<TLookup> TLookupList;
--    return_trace (version.sanitize (c) &&
--		  likely (version.major == 1) &&
--		  scriptList.sanitize (c, this) &&
--		  featureList.sanitize (c, this) &&
--		  CastR<OffsetTo<TLookupList>> (lookupList).sanitize (c, this) &&
--		  (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
-+    if (unlikely (!(version.sanitize (c) &&
-+		    likely (version.major == 1) &&
-+		    scriptList.sanitize (c, this) &&
-+		    featureList.sanitize (c, this) &&
-+		    CastR<OffsetTo<TLookupList>> (lookupList).sanitize (c, this))))
-+      return_trace (false);
-+
-+#ifndef HB_NO_VAR
-+    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
-+      return_trace (false);
-+#endif
-+
-+    return_trace (true);
-   }
- 
-   template <typename T>
-   struct accelerator_t
-   {
-     void init (hb_face_t *face)
-     {
-       this->table = hb_sanitize_context_t().reference_table<T> (face);
-diff --git a/gfx/harfbuzz/src/hb-ot-layout.cc b/gfx/harfbuzz/src/hb-ot-layout.cc
---- a/gfx/harfbuzz/src/hb-ot-layout.cc
-+++ b/gfx/harfbuzz/src/hb-ot-layout.cc
-@@ -57,50 +57,49 @@
-  * Functions for querying OpenType Layout features in the font face.
-  **/
- 
- 
- /*
-  * kern
-  */
- 
-+#ifndef HB_NO_OT_KERN
- /**
-  * hb_ot_layout_has_kerning:
-  * @face: The #hb_face_t to work on
-  *
-  * Tests whether a face includes any kerning data in the 'kern' table.
-  * Does NOT test for kerning lookups in the GPOS table.
-  *
-  * Return value: true if data found, false otherwise
-  *
-  **/
- bool
- hb_ot_layout_has_kerning (hb_face_t *face)
- {
-   return face->table.kern->has_data ();
- }
- 
--
- /**
-  * hb_ot_layout_has_machine_kerning:
-  * @face: The #hb_face_t to work on
-  *
-  * Tests whether a face includes any state-machine kerning in the 'kern' table.
-  * Does NOT examine the GPOS table.
-  *
-  * Return value: true if data found, false otherwise
-  *
-  **/
- bool
- hb_ot_layout_has_machine_kerning (hb_face_t *face)
- {
-   return face->table.kern->has_state_machine ();
- }
- 
--
- /**
-  * hb_ot_layout_has_cross_kerning:
-  * @face: The #hb_face_t to work on
-  *
-  * Tests whether a face has any cross-stream kerning (i.e., kerns
-  * that make adjustments perpendicular to the direction of the text
-  * flow: Y adjustments in horizontal text or X adjustments in 
-  * vertical text) in the 'kern' table.
-@@ -123,16 +122,17 @@ hb_ot_layout_kern (const hb_ot_shape_pla
- {
-   hb_blob_t *blob = font->face->table.kern.get_blob ();
-   const AAT::kern& kern = *blob->as<AAT::kern> ();
- 
-   AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
- 
-   kern.apply (&c);
- }
-+#endif
- 
- 
- /*
-  * GDEF
-  */
- 
- bool
- OT::GDEF::is_blacklisted (hb_blob_t *blob,
-@@ -306,16 +306,17 @@ void
- hb_ot_layout_get_glyphs_in_class (hb_face_t                  *face,
- 				  hb_ot_layout_glyph_class_t  klass,
- 				  hb_set_t                   *glyphs /* OUT */)
- {
-   return face->table.GDEF->table->get_glyphs_in_class (klass, glyphs);
- }
- 
- 
-+#ifndef HB_NO_LAYOUT_UNUSED
- /**
-  * hb_ot_layout_get_attach_points:
-  * @face: The #hb_face_t to work on
-  * @glyph: The #hb_codepoint_t code point to query
-  * @start_offset: offset of the first attachment point to retrieve
-  * @point_count: (inout) (allow-none): Input = the maximum number of attachment points to return;
-  *               Output = the actual number of attachment points returned (may be zero)
-  * @point_array: (out) (array length=point_count): The array of attachment points found for the query
-@@ -328,29 +329,21 @@ hb_ot_layout_get_glyphs_in_class (hb_fac
-  **/
- unsigned int
- hb_ot_layout_get_attach_points (hb_face_t      *face,
- 				hb_codepoint_t  glyph,
- 				unsigned int    start_offset,
- 				unsigned int   *point_count /* IN/OUT */,
- 				unsigned int   *point_array /* OUT */)
- {
--#ifdef HB_NO_LAYOUT_UNUSED
--  if (point_count)
--    *point_count = 0;
--  return 0;
--#endif
--
-   return face->table.GDEF->table->get_attach_points (glyph,
- 						     start_offset,
- 						     point_count,
- 						     point_array);
- }
--
--
- /**
-  * hb_ot_layout_get_ligature_carets:
-  * @font: The #hb_font_t to work on
-  * @direction: The #hb_direction_t text direction to use
-  * @glyph: The #hb_codepoint_t code point to query
-  * @start_offset: offset of the first caret position to retrieve
-  * @caret_count: (inout) (allow-none): Input = the maximum number of caret positions to return;
-  *               Output = the actual number of caret positions returned (may be zero)
-@@ -363,45 +356,44 @@ hb_ot_layout_get_attach_points (hb_face_
- unsigned int
- hb_ot_layout_get_ligature_carets (hb_font_t      *font,
- 				  hb_direction_t  direction,
- 				  hb_codepoint_t  glyph,
- 				  unsigned int    start_offset,
- 				  unsigned int   *caret_count /* IN/OUT */,
- 				  hb_position_t  *caret_array /* OUT */)
- {
--#ifdef HB_NO_LAYOUT_UNUSED
--  if (caret_count)
--    *caret_count = 0;
--  return 0;
--#endif
--
-   unsigned int result_caret_count = 0;
-   unsigned int result = font->face->table.GDEF->table->get_lig_carets (font, direction, glyph, start_offset, &result_caret_count, caret_array);
-   if (result)
-   {
-     if (caret_count) *caret_count = result_caret_count;
-   }
-+#ifndef HB_NO_AAT
-   else
-     result = font->face->table.lcar->get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
-+#endif
-   return result;
- }
-+#endif
- 
- 
- /*
-  * GSUB/GPOS
-  */
- 
- bool
- OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED,
- 			  hb_face_t *face) const
- {
- #ifdef HB_NO_OT_LAYOUT_BLACKLIST
-   return false;
- #endif
-+
-+#ifndef HB_NO_SHAPE_AAT
-   /* Mac OS X prefers morx over GSUB.  It also ships with various Indic fonts,
-    * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken
-    * GSUB/GPOS tables.  Some have GSUB with zero scripts, those are ignored by
-    * our morx/GSUB preference code.  But if GSUB has non-zero scripts, we tend
-    * to prefer it over morx because we want to be consistent with other OpenType
-    * shapers.
-    *
-    * To work around broken Indic Mac system fonts, we ignore GSUB table if
-@@ -409,16 +401,17 @@ OT::GSUB::is_blacklisted (hb_blob_t *blo
-    *
-    * https://github.com/harfbuzz/harfbuzz/issues/1410
-    * https://github.com/harfbuzz/harfbuzz/issues/1348
-    * https://github.com/harfbuzz/harfbuzz/issues/1391
-    */
-   if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') &&
- 		face->table.morx->has_data ()))
-     return true;
-+#endif
- 
-   return false;
- }
- 
- bool
- OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED,
- 			  hb_face_t *face HB_UNUSED) const
- {
-@@ -1205,16 +1198,17 @@ hb_ot_layout_collect_lookups (hb_face_t 
-   hb_ot_layout_collect_features (face, table_tag, scripts, languages, features, &feature_indexes);
- 
-   for (hb_codepoint_t feature_index = HB_SET_VALUE_INVALID;
-        hb_set_next (&feature_indexes, &feature_index);)
-     g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
- }
- 
- 
-+#ifndef HB_NO_LAYOUT_COLLECT_GLYPHS
- /**
-  * hb_ot_layout_lookup_collect_glyphs:
-  * @face: #hb_face_t to work upon
-  * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS
-  * @lookup_index: The index of the feature lookup to query
-  * @glyphs_before: (out): Array of glyphs preceding the substitution range
-  * @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup
-  * @glyphs_after: (out): Array of glyphs following the substition range
-@@ -1251,16 +1245,17 @@ hb_ot_layout_lookup_collect_glyphs (hb_f
-     case HB_OT_TAG_GPOS:
-     {
-       const OT::PosLookup& l = face->table.GPOS->table->get_lookup (lookup_index);
-       l.collect_glyphs (&c);
-       return;
-     }
-   }
- }
-+#endif
- 
- 
- /* Variations support */
- 
- 
- /**
-  * hb_ot_layout_table_find_feature_variations:
-  * @face: #hb_face_t to work upon
-@@ -1559,16 +1554,17 @@ hb_ot_layout_position_finish_advances (h
-  **/
- void
- hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
- {
-   OT::GPOS::position_finish_offsets (font, buffer);
- }
- 
- 
-+#ifndef HB_NO_LAYOUT_FEATURE_PARAMS
- /**
-  * hb_ot_layout_get_size_params:
-  * @face: #hb_face_t to work upon
-  * @design_size: (out): The design size of the face
-  * @subfamily_id: (out): The identifier of the face within the font subfamily
-  * @subfamily_name_id: (out): The ‘name’ table name ID of the face within the font subfamily
-  * @range_start: (out): The minimum size of the recommended size range for the face
-  * @range_end: (out): The maximum size of the recommended size range for the face
-@@ -1621,18 +1617,16 @@ hb_ot_layout_get_size_params (hb_face_t 
-   if (design_size) *design_size = 0;
-   if (subfamily_id) *subfamily_id = 0;
-   if (subfamily_name_id) *subfamily_name_id = HB_OT_NAME_ID_INVALID;
-   if (range_start) *range_start = 0;
-   if (range_end) *range_end = 0;
- 
-   return false;
- }
--
--
- /**
-  * hb_ot_layout_feature_get_name_ids:
-  * @face: #hb_face_t to work upon
-  * @table_tag: table tag to query, "GSUB" or "GPOS".
-  * @feature_index: index of feature to query.
-  * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
-  *            for a user-interface label for this feature. (May be NULL.)
-  * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string
-@@ -1697,18 +1691,16 @@ hb_ot_layout_feature_get_name_ids (hb_fa
- 
-   if (label_id) *label_id = HB_OT_NAME_ID_INVALID;
-   if (tooltip_id) *tooltip_id = HB_OT_NAME_ID_INVALID;
-   if (sample_id) *sample_id = HB_OT_NAME_ID_INVALID;
-   if (num_named_parameters) *num_named_parameters = 0;
-   if (first_param_id) *first_param_id = HB_OT_NAME_ID_INVALID;
-   return false;
- }
--
--
- /**
-  * hb_ot_layout_feature_get_characters:
-  * @face: #hb_face_t to work upon
-  * @table_tag: table tag to query, "GSUB" or "GPOS".
-  * @feature_index: index of feature to query.
-  * @start_offset: offset of the first character to retrieve
-  * @char_count: (inout) (allow-none): Input = the maximum number of characters to return;
-  *              Output = the actual number of characters returned (may be zero)
-@@ -1752,16 +1744,17 @@ hb_ot_layout_feature_get_characters (hb_
-   {
-     len = hb_min (cv_params.characters.len - start_offset, *char_count);
-     for (unsigned int i = 0; i < len; ++i)
-       characters[i] = cv_params.characters[start_offset + i];
-   }
-   if (char_count) *char_count = len;
-   return cv_params.characters.len;
- }
-+#endif
- 
- 
- /*
-  * Parts of different types are implemented here such that they have direct
-  * access to GSUB/GPOS lookups.
-  */
- 
- 
-@@ -1936,32 +1929,26 @@ void
- hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
- 				const OT::SubstLookup &lookup,
- 				const OT::hb_ot_layout_lookup_accelerator_t &accel)
- {
-   apply_string<GSUBProxy> (c, lookup, accel);
- }
- 
- #if 0
--static const OT::BASE& _get_base (hb_face_t *face)
--{
--  return *face->table.BASE;
--}
--
- hb_bool_t
- hb_ot_layout_get_baseline (hb_font_t               *font,
- 			   hb_ot_layout_baseline_t  baseline,
- 			   hb_direction_t           direction,
- 			   hb_tag_t                 script_tag,
- 			   hb_tag_t                 language_tag,
- 			   hb_position_t           *coord        /* OUT.  May be NULL. */)
- {
--  const OT::BASE &base = _get_base (font->face);
--  bool result = base.get_baseline (font, baseline, direction, script_tag,
--				   language_tag, coord);
-+  bool result = font->face->table.BASE->get_baseline (font, baseline, direction, script_tag,
-+						      language_tag, coord);
- 
-   /* TODO: Simulate https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags#ideographic-em-box */
-   if (!result && coord) *coord = 0;
- 
-   if (coord) *coord = font->em_scale_dir (*coord, direction);
- 
-   return result;
- }
-diff --git a/gfx/harfbuzz/src/hb-ot-math.cc b/gfx/harfbuzz/src/hb-ot-math.cc
---- a/gfx/harfbuzz/src/hb-ot-math.cc
-+++ b/gfx/harfbuzz/src/hb-ot-math.cc
-@@ -19,19 +19,20 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Igalia Author(s): Frédéric Wang
-  */
- 
--#include "hb-open-type.hh"
-+#include "hb.hh"
- 
--#include "hb-ot-face.hh"
-+#ifndef HB_NO_MATH
-+
- #include "hb-ot-math-table.hh"
- 
- 
- /**
-  * SECTION:hb-ot-math
-  * @title: hb-ot-math
-  * @short_description: OpenType Math information
-  * @include: hb-ot.h
-@@ -57,20 +58,16 @@
-  *
-  * Return value: true if the table is found, false otherwise
-  *
-  * Since: 1.3.3
-  **/
- hb_bool_t
- hb_ot_math_has_data (hb_face_t *face)
- {
--#ifdef HB_NO_MATH
--  return false;
--#endif
--
-   return face->table.MATH->has_data ();
- }
- 
- /**
-  * hb_ot_math_get_constant:
-  * @font: #hb_font_t to work upon
-  * @constant: #hb_ot_math_constant_t the constant to retrieve
-  *
-@@ -85,20 +82,16 @@ hb_ot_math_has_data (hb_face_t *face)
-  * Return value: the requested constant or zero
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_constant (hb_font_t *font,
- 			 hb_ot_math_constant_t constant)
- {
--#ifdef HB_NO_MATH
--  return 0;
--#endif
--
-   return font->face->table.MATH->get_constant(constant, font);
- }
- 
- /**
-  * hb_ot_math_get_glyph_italics_correction:
-  * @font: #hb_font_t to work upon
-  * @glyph: The glyph index from which to retrieve the value
-  *
-@@ -108,20 +101,16 @@ hb_ot_math_get_constant (hb_font_t *font
-   * Return value: the italics correction of the glyph or zero
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_glyph_italics_correction (hb_font_t *font,
- 					 hb_codepoint_t glyph)
- {
--#ifdef HB_NO_MATH
--  return 0;
--#endif
--
-   return font->face->table.MATH->get_glyph_info().get_italics_correction (glyph, font);
- }
- 
- /**
-  * hb_ot_math_get_glyph_top_accent_attachment:
-  * @font: #hb_font_t to work upon
-  * @glyph: The glyph index from which to retrieve the value
-  *
-@@ -138,20 +127,16 @@ hb_ot_math_get_glyph_italics_correction 
-  *               width of @glyph
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
- 					    hb_codepoint_t glyph)
- {
--#ifdef HB_NO_MATH
--  return 0;
--#endif
--
-   return font->face->table.MATH->get_glyph_info().get_top_accent_attachment (glyph, font);
- }
- 
- /**
-  * hb_ot_math_is_glyph_extended_shape:
-  * @face: #hb_face_t to work upon
-  * @glyph: The glyph index to test
-  *
-@@ -160,20 +145,16 @@ hb_ot_math_get_glyph_top_accent_attachme
-  * Return value: true if the glyph is an extended shape, false otherwise
-  *
-  * Since: 1.3.3
-  **/
- hb_bool_t
- hb_ot_math_is_glyph_extended_shape (hb_face_t *face,
- 				    hb_codepoint_t glyph)
- {
--#ifdef HB_NO_MATH
--  return false;
--#endif
--
-   return face->table.MATH->get_glyph_info().is_extended_shape (glyph);
- }
- 
- /**
-  * hb_ot_math_get_glyph_kerning:
-  * @font: #hb_font_t to work upon
-  * @glyph: The glyph index from which to retrieve the value
-  * @kern: The #hb_ot_math_kern_t from which to retrieve the value
-@@ -192,20 +173,16 @@ hb_ot_math_is_glyph_extended_shape (hb_f
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_glyph_kerning (hb_font_t *font,
- 			      hb_codepoint_t glyph,
- 			      hb_ot_math_kern_t kern,
- 			      hb_position_t correction_height)
- {
--#ifdef HB_NO_MATH
--  return 0;
--#endif
--
-   return font->face->table.MATH->get_glyph_info().get_kerning (glyph,
- 							       kern,
- 							       correction_height,
- 							       font);
- }
- 
- /**
-  * hb_ot_math_get_glyph_variants:
-@@ -233,22 +210,16 @@ hb_ot_math_get_glyph_kerning (hb_font_t 
- unsigned int
- hb_ot_math_get_glyph_variants (hb_font_t *font,
- 			       hb_codepoint_t glyph,
- 			       hb_direction_t direction,
- 			       unsigned int start_offset,
- 			       unsigned int *variants_count, /* IN/OUT */
- 			       hb_ot_math_glyph_variant_t *variants /* OUT */)
- {
--#ifdef HB_NO_MATH
--  if (variants_count)
--    *variants_count = 0;
--  return 0;
--#endif
--
-   return font->face->table.MATH->get_variants().get_glyph_variants (glyph, direction, font,
- 								    start_offset,
- 								    variants_count,
- 								    variants);
- }
- 
- /**
-  * hb_ot_math_get_min_connector_overlap:
-@@ -267,20 +238,16 @@ hb_ot_math_get_glyph_variants (hb_font_t
-  * Return value: requested minimum connector overlap or zero
-  *
-  * Since: 1.3.3
-  **/
- hb_position_t
- hb_ot_math_get_min_connector_overlap (hb_font_t *font,
- 				      hb_direction_t direction)
- {
--#ifdef HB_NO_MATH
--  return 0;
--#endif
--
-   return font->face->table.MATH->get_variants().get_min_connector_overlap (direction, font);
- }
- 
- /**
-  * hb_ot_math_get_glyph_assembly:
-  * @font: #hb_font_t to work upon
-  * @glyph: The index of the glyph to stretch
-  * @direction: direction of the stretching (horizontal or vertical)
-@@ -308,22 +275,19 @@ unsigned int
- hb_ot_math_get_glyph_assembly (hb_font_t *font,
- 			       hb_codepoint_t glyph,
- 			       hb_direction_t direction,
- 			       unsigned int start_offset,
- 			       unsigned int *parts_count, /* IN/OUT */
- 			       hb_ot_math_glyph_part_t *parts, /* OUT */
- 			       hb_position_t *italics_correction /* OUT */)
- {
--#ifdef HB_NO_MATH
--  if (parts_count)
--    *parts_count = 0;
--  return 0;
--#endif
--
-   return font->face->table.MATH->get_variants().get_glyph_parts (glyph,
- 								 direction,
- 								 font,
- 								 start_offset,
- 								 parts_count,
- 								 parts,
- 								 italics_correction);
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-ot-maxp-table.hh b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
---- a/gfx/harfbuzz/src/hb-ot-maxp-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-maxp-table.hh
-@@ -89,49 +89,45 @@ struct maxp
-     if (version.major == 1)
-     {
-       const maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*this);
-       return_trace (v1.sanitize (c));
-     }
-     return_trace (likely (version.major == 0 && version.minor == 0x5000u));
-   }
- 
--  bool subset (hb_subset_plan_t *plan) const
-+  bool subset (hb_subset_context_t *c) const
-   {
--    hb_blob_t *maxp_blob = hb_sanitize_context_t().reference_table<maxp> (plan->source);
--    hb_blob_t *maxp_prime_blob = hb_blob_copy_writable_or_fail (maxp_blob);
--    hb_blob_destroy (maxp_blob);
-+    TRACE_SUBSET (this);
-+    maxp *maxp_prime = c->serializer->embed (this);
-+    if (unlikely (!maxp_prime)) return_trace (false);
- 
--    if (unlikely (!maxp_prime_blob)) {
--      return false;
-+    maxp_prime->numGlyphs = c->plan->num_output_glyphs ();
-+    if (maxp_prime->version.major == 1)
-+    {
-+      const maxpV1Tail *src_v1 = &StructAfter<maxpV1Tail> (*this);
-+      maxpV1Tail *dest_v1 = c->serializer->embed<maxpV1Tail> (src_v1);
-+      if (unlikely (!dest_v1)) return_trace (false);
-+
-+      if (c->plan->drop_hints)
-+        drop_hint_fields (dest_v1);
-     }
--    maxp *maxp_prime = (maxp *) hb_blob_get_data (maxp_prime_blob, nullptr);
- 
--    maxp_prime->set_num_glyphs (plan->num_output_glyphs ());
--    if (plan->drop_hints)
--      drop_hint_fields (plan, maxp_prime);
--
--    bool result = plan->add_table (HB_OT_TAG_maxp, maxp_prime_blob);
--    hb_blob_destroy (maxp_prime_blob);
--    return result;
-+    return_trace (true);
-   }
- 
--  static void drop_hint_fields (hb_subset_plan_t *plan HB_UNUSED, maxp *maxp_prime)
-+  static void drop_hint_fields (maxpV1Tail* dest_v1)
-   {
--    if (maxp_prime->version.major == 1)
--    {
--      maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*maxp_prime);
--      v1.maxZones = 1;
--      v1.maxTwilightPoints = 0;
--      v1.maxStorage = 0;
--      v1.maxFunctionDefs = 0;
--      v1.maxInstructionDefs = 0;
--      v1.maxStackElements = 0;
--      v1.maxSizeOfInstructions = 0;
--    }
-+    dest_v1->maxZones = 1;
-+    dest_v1->maxTwilightPoints = 0;
-+    dest_v1->maxStorage = 0;
-+    dest_v1->maxFunctionDefs = 0;
-+    dest_v1->maxInstructionDefs = 0;
-+    dest_v1->maxStackElements = 0;
-+    dest_v1->maxSizeOfInstructions = 0;
-   }
- 
-   protected:
-   FixedVersion<>version;		/* Version of the maxp table (0.5 or 1.0),
- 					 * 0x00005000u or 0x00010000u. */
-   HBUINT16	numGlyphs;		/* The number of glyphs in the font. */
- /*maxpV1Tail	v1Tail[VAR]; */
-   public:
-diff --git a/gfx/harfbuzz/src/hb-ot-name-table.hh b/gfx/harfbuzz/src/hb-ot-name-table.hh
---- a/gfx/harfbuzz/src/hb-ot-name-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-name-table.hh
-@@ -58,17 +58,17 @@ struct NameRecord
-     if (p == 3)
-       return _hb_ot_name_language_for_ms_code (l);
- 
-     if (p == 1)
-       return _hb_ot_name_language_for_mac_code (l);
- 
- #ifndef HB_NO_OT_NAME_LANGUAGE_AAT
-     if (p == 0)
--      return _hb_aat_language_get (face, l);
-+      return face->table.ltag->get_language (l);
- #endif
- 
- #endif
-     return HB_LANGUAGE_INVALID;
-   }
- 
-   uint16_t score () const
-   {
-diff --git a/gfx/harfbuzz/src/hb-ot-name.cc b/gfx/harfbuzz/src/hb-ot-name.cc
---- a/gfx/harfbuzz/src/hb-ot-name.cc
-+++ b/gfx/harfbuzz/src/hb-ot-name.cc
-@@ -21,19 +21,20 @@
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
- 
-+#ifndef HB_NO_NAME
-+
- #include "hb-ot-name-table.hh"
- 
--#include "hb-ot-face.hh"
- #include "hb-utf.hh"
- 
- 
- /**
-  * SECTION:hb-ot-name
-  * @title: hb-ot-name
-  * @short_description: OpenType font name information
-  * @include: hb-ot.h
-@@ -53,21 +54,16 @@
-  *
-  * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
-  * Since: 2.1.0
-  **/
- const hb_ot_name_entry_t *
- hb_ot_name_list_names (hb_face_t    *face,
- 		       unsigned int *num_entries /* OUT */)
- {
--#ifdef HB_NO_NAME
--  if (num_entries)
--    *num_entries = 0;
--  return 0;
--#endif
-   const OT::name_accelerator_t &name = *face->table.name;
-   if (num_entries) *num_entries = name.names.length;
-   return (const hb_ot_name_entry_t *) name.names;
- }
- 
- 
- template <typename in_utf_t, typename out_utf_t>
- static inline unsigned int
-@@ -167,21 +163,16 @@ hb_ot_name_get_utf (hb_face_t       *fac
-  **/
- unsigned int
- hb_ot_name_get_utf8 (hb_face_t       *face,
- 		     hb_ot_name_id_t  name_id,
- 		     hb_language_t    language,
- 		     unsigned int    *text_size /* IN/OUT */,
- 		     char            *text      /* OUT */)
- {
--#ifdef HB_NO_NAME
--  if (text_size)
--    *text_size = 0;
--  return 0;
--#endif
-   return hb_ot_name_get_utf<hb_utf8_t> (face, name_id, language, text_size,
- 					(hb_utf8_t::codepoint_t *) text);
- }
- 
- /**
-  * hb_ot_name_get_utf16:
-  * @face: font face.
-  * @name_id: OpenType name identifier to fetch.
-@@ -199,21 +190,16 @@ hb_ot_name_get_utf8 (hb_face_t       *fa
-  **/
- unsigned int
- hb_ot_name_get_utf16 (hb_face_t       *face,
- 		      hb_ot_name_id_t  name_id,
- 		      hb_language_t    language,
- 		      unsigned int    *text_size /* IN/OUT */,
- 		      uint16_t        *text      /* OUT */)
- {
--#ifdef HB_NO_NAME
--  if (text_size)
--    *text_size = 0;
--  return 0;
--#endif
-   return hb_ot_name_get_utf<hb_utf16_t> (face, name_id, language, text_size, text);
- }
- 
- /**
-  * hb_ot_name_get_utf32:
-  * @face: font face.
-  * @name_id: OpenType name identifier to fetch.
-  * @language: language to fetch the name for.
-@@ -230,15 +216,13 @@ hb_ot_name_get_utf16 (hb_face_t       *f
-  **/
- unsigned int
- hb_ot_name_get_utf32 (hb_face_t       *face,
- 		      hb_ot_name_id_t  name_id,
- 		      hb_language_t    language,
- 		      unsigned int    *text_size /* IN/OUT */,
- 		      uint32_t        *text      /* OUT */)
- {
--#ifdef HB_NO_NAME
--  if (text_size)
--    *text_size = 0;
--  return 0;
--#endif
-   return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-ot-os2-table.hh b/gfx/harfbuzz/src/hb-ot-os2-table.hh
---- a/gfx/harfbuzz/src/hb-ot-os2-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-os2-table.hh
-@@ -140,65 +140,60 @@ struct OS2
-     case FWIDTH_NORMAL:		return 100.f;
-     case FWIDTH_SEMI_EXPANDED:	return 112.5f;
-     case FWIDTH_EXPANDED:	return 125.f;
-     case FWIDTH_EXTRA_EXPANDED:	return 150.f;
-     case FWIDTH_ULTRA_EXPANDED:	return 200.f;
-     }
-   }
- 
--  bool subset (hb_subset_plan_t *plan) const
-+  bool subset (hb_subset_context_t *c) const
-   {
--    hb_blob_t *os2_blob = hb_sanitize_context_t ().reference_table<OS2> (plan->source);
--    hb_blob_t *os2_prime_blob = hb_blob_create_sub_blob (os2_blob, 0, -1);
--    // TODO(grieger): move to hb_blob_copy_writable_or_fail
--    hb_blob_destroy (os2_blob);
--
--    OS2 *os2_prime = (OS2 *) hb_blob_get_data_writable (os2_prime_blob, nullptr);
--    if (unlikely (!os2_prime)) {
--      hb_blob_destroy (os2_prime_blob);
--      return false;
--    }
-+    TRACE_SUBSET (this);
-+    OS2 *os2_prime = c->serializer->embed (this);
-+    if (unlikely (!os2_prime)) return_trace (false);
- 
-     uint16_t min_cp, max_cp;
--    find_min_and_max_codepoint (plan->unicodes, &min_cp, &max_cp);
-+    find_min_and_max_codepoint (c->plan->unicodes, &min_cp, &max_cp);
-     os2_prime->usFirstCharIndex = min_cp;
-     os2_prime->usLastCharIndex = max_cp;
- 
--    _update_unicode_ranges (plan->unicodes, os2_prime->ulUnicodeRange);
--    bool result = plan->add_table (HB_OT_TAG_OS2, os2_prime_blob);
-+    _update_unicode_ranges (c->plan->unicodes, os2_prime->ulUnicodeRange);
- 
--    hb_blob_destroy (os2_prime_blob);
--    return result;
-+    return_trace (true);
-   }
- 
-   void _update_unicode_ranges (const hb_set_t *codepoints,
- 			       HBUINT32 ulUnicodeRange[4]) const
-   {
-+    HBUINT32	newBits[4];
-     for (unsigned int i = 0; i < 4; i++)
--      ulUnicodeRange[i] = 0;
-+      newBits[i] = 0;
- 
-     hb_codepoint_t cp = HB_SET_VALUE_INVALID;
-     while (codepoints->next (&cp)) {
-       unsigned int bit = _hb_ot_os2_get_unicode_range_bit (cp);
-       if (bit < 128)
-       {
- 	unsigned int block = bit / 32;
- 	unsigned int bit_in_block = bit % 32;
- 	unsigned int mask = 1 << bit_in_block;
--	ulUnicodeRange[block] = ulUnicodeRange[block] | mask;
-+	newBits[block] = newBits[block] | mask;
-       }
-       if (cp >= 0x10000 && cp <= 0x110000)
-       {
- 	/* the spec says that bit 57 ("Non Plane 0") implies that there's
- 	   at least one codepoint beyond the BMP; so I also include all
- 	   the non-BMP codepoints here */
--	ulUnicodeRange[1] = ulUnicodeRange[1] | (1 << 25);
-+	newBits[1] = newBits[1] | (1 << 25);
-       }
-     }
-+
-+    for (unsigned int i = 0; i < 4; i++)
-+      ulUnicodeRange[i] = ulUnicodeRange[i] & newBits[i]; // set bits only if set in the original
-   }
- 
-   static void find_min_and_max_codepoint (const hb_set_t *codepoints,
- 						 uint16_t *min_cp, /* OUT */
- 						 uint16_t *max_cp  /* OUT */)
-   {
-     *min_cp = codepoints->get_min ();
-     *max_cp = codepoints->get_max ();
-@@ -213,16 +208,25 @@ struct OS2
-     TRAD_FARSI_FONT_PAGE	= 0xBB00, // Traditional Farsi Windows 3.1 font page
-     THAI_FONT_PAGE		= 0xDE00  // Thai Windows 3.1 font page
-   };
- 
-   // https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
-   font_page_t get_font_page () const
-   { return (font_page_t) (version == 0 ? fsSelection & 0xFF00 : 0); }
- 
-+  unsigned get_size () const
-+  {
-+    unsigned result = min_size;
-+    if (version >= 1) result += v1X.get_size ();
-+    if (version >= 2) result += v2X.get_size ();
-+    if (version >= 5) result += v5X.get_size ();
-+    return result;
-+  }
-+
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!c->check_struct (this))) return_trace (false);
-     if (unlikely (version >= 1 && !v1X.sanitize (c))) return_trace (false);
-     if (unlikely (version >= 2 && !v2X.sanitize (c))) return_trace (false);
-     if (unlikely (version >= 5 && !v5X.sanitize (c))) return_trace (false);
-     return_trace (true);
-diff --git a/gfx/harfbuzz/src/hb-ot-post-table.hh b/gfx/harfbuzz/src/hb-ot-post-table.hh
---- a/gfx/harfbuzz/src/hb-ot-post-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-post-table.hh
-@@ -68,36 +68,35 @@ struct postV2Tail
-   public:
-   DEFINE_SIZE_ARRAY (2, glyphNameIndex);
- };
- 
- struct post
- {
-   static constexpr hb_tag_t tableTag = HB_OT_TAG_post;
- 
--  bool subset (hb_subset_plan_t *plan) const
-+  void serialize (hb_serialize_context_t *c) const
-   {
--    unsigned int post_prime_length;
--    hb_blob_t *post_blob = hb_sanitize_context_t ().reference_table<post>(plan->source);
--    hb_blob_t *post_prime_blob = hb_blob_create_sub_blob (post_blob, 0, post::min_size);
--    post *post_prime = (post *) hb_blob_get_data_writable (post_prime_blob, &post_prime_length);
--    hb_blob_destroy (post_blob);
-+    post *post_prime = c->allocate_min<post> ();
-+    if (unlikely (!post_prime))  return;
-+
-+    memcpy (post_prime, this, post::min_size);
-+    post_prime->version.major = 3; // Version 3 does not have any glyph names.
-+  }
- 
--    if (unlikely (!post_prime || post_prime_length != post::min_size))
--    {
--      hb_blob_destroy (post_prime_blob);
--      DEBUG_MSG(SUBSET, nullptr, "Invalid source post table with length %d.", post_prime_length);
--      return false;
--    }
-+  bool subset (hb_subset_context_t *c) const
-+  {
-+    TRACE_SUBSET (this);
-+    post *post_prime = c->serializer->start_embed<post> ();
-+    if (unlikely (!post_prime)) return_trace (false);
- 
--    post_prime->version.major = 3; // Version 3 does not have any glyph names.
--    bool result = plan->add_table (HB_OT_TAG_post, post_prime_blob);
--    hb_blob_destroy (post_prime_blob);
-+    serialize (c->serializer);
-+    if (c->serializer->in_error () || c->serializer->ran_out_of_room) return_trace (false);
- 
--    return result;
-+    return_trace (true);
-   }
- 
-   struct accelerator_t
-   {
-     void init (hb_face_t *face)
-     {
-       index_to_offset.init ();
- 
-@@ -153,28 +152,28 @@ struct post
-       if (unlikely (!gids))
-       {
- 	gids = (uint16_t *) malloc (count * sizeof (gids[0]));
- 	if (unlikely (!gids))
- 	  return false; /* Anything better?! */
- 
- 	for (unsigned int i = 0; i < count; i++)
- 	  gids[i] = i;
--	hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
-+	hb_qsort (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
- 
- 	if (unlikely (!gids_sorted_by_name.cmpexch (nullptr, gids)))
- 	{
- 	  free (gids);
- 	  goto retry;
- 	}
-       }
- 
-       hb_bytes_t st (name, len);
--      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (hb_addressof (st), gids, count,
--							     sizeof (gids[0]), cmp_key, (void *) this);
-+      const uint16_t *gid = (const uint16_t *) hb_bsearch (hb_addressof (st), gids, count,
-+							   sizeof (gids[0]), cmp_key, (void *) this);
-       if (gid)
-       {
- 	*glyph = *gid;
- 	return true;
-       }
- 
-       return false;
-     }
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-indic.hh
-@@ -354,17 +354,17 @@ set_indic_properties (hb_glyph_info_t &i
-     /* https://github.com/harfbuzz/harfbuzz/issues/524 */
-     cat = OT_M;
-     pos = POS_BELOW_C;
-   }
- 
-   /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
-    * so the Indic shaper needs to know their categories. */
-   else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
--  else if (unlikely (u == 0x1133cu)) cat = OT_N;
-+  else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N;
- 
-   else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
- 
-   else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
-   else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */
-   else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
-   else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
- 				    cat = OT_PLACEHOLDER;
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
-@@ -31,41 +31,41 @@
- 
- #include "hb.hh"
- 
- 
- #line 36 "hb-ot-shape-complex-myanmar-machine.hh"
- static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
- 	1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 
- 	3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, 
--	3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 5u, 29u, 
--	5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 
--	3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
--	3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 1u, 32u, 
--	1u, 32u, 8u, 8u, 0
-+	3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
-+	5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 
-+	3u, 29u, 3u, 29u, 1u, 16u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 
-+	3u, 29u, 3u, 30u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 
-+	3u, 29u, 1u, 32u, 1u, 32u, 8u, 8u, 0
- };
- 
- static const char _myanmar_syllable_machine_key_spans[] = {
- 	32, 28, 25, 4, 25, 23, 21, 21, 
- 	27, 27, 27, 27, 16, 27, 27, 27, 
--	27, 27, 28, 27, 27, 27, 27, 25, 
--	4, 25, 23, 21, 21, 27, 27, 27, 
--	27, 16, 28, 27, 27, 27, 27, 27, 
--	28, 27, 27, 27, 27, 28, 27, 32, 
--	32, 1
-+	27, 27, 28, 27, 27, 27, 27, 27, 
-+	25, 4, 25, 23, 21, 21, 27, 27, 
-+	27, 27, 16, 28, 27, 27, 27, 27, 
-+	27, 28, 27, 27, 27, 27, 27, 28, 
-+	27, 32, 32, 1
- };
- 
- static const short _myanmar_syllable_machine_index_offsets[] = {
- 	0, 33, 62, 88, 93, 119, 143, 165, 
- 	187, 215, 243, 271, 299, 316, 344, 372, 
- 	400, 428, 456, 485, 513, 541, 569, 597, 
--	623, 628, 654, 678, 700, 722, 750, 778, 
--	806, 834, 851, 880, 908, 936, 964, 992, 
--	1020, 1049, 1077, 1105, 1133, 1161, 1190, 1218, 
--	1251, 1284
-+	625, 651, 656, 682, 706, 728, 750, 778, 
-+	806, 834, 862, 879, 908, 936, 964, 992, 
-+	1020, 1048, 1077, 1105, 1133, 1161, 1189, 1217, 
-+	1246, 1274, 1307, 1340
- };
- 
- static const char _myanmar_syllable_machine_indicies[] = {
- 	1, 1, 2, 3, 4, 4, 0, 5, 
- 	0, 6, 1, 0, 0, 0, 0, 7, 
- 	0, 8, 9, 0, 10, 11, 12, 13, 
- 	14, 15, 16, 17, 18, 19, 20, 1, 
- 	0, 22, 23, 24, 24, 21, 25, 21, 
-@@ -121,167 +121,174 @@ static const char _myanmar_syllable_mach
- 	21, 25, 21, 26, 21, 21, 21, 21, 
- 	21, 21, 21, 21, 21, 21, 21, 21, 
- 	21, 21, 32, 21, 34, 21, 36, 21, 
- 	22, 21, 24, 24, 21, 25, 21, 26, 
- 	21, 21, 21, 21, 21, 21, 21, 21, 
- 	21, 21, 21, 21, 21, 21, 32, 33, 
- 	34, 35, 36, 43, 21, 22, 21, 24, 
- 	24, 21, 25, 21, 26, 21, 21, 21, 
--	21, 21, 21, 21, 43, 21, 21, 28, 
-+	21, 21, 21, 21, 21, 21, 21, 28, 
- 	21, 30, 21, 32, 33, 34, 35, 36, 
- 	21, 22, 21, 24, 24, 21, 25, 21, 
- 	26, 21, 21, 21, 21, 21, 21, 21, 
- 	43, 21, 21, 28, 21, 21, 21, 32, 
- 	33, 34, 35, 36, 21, 22, 21, 24, 
- 	24, 21, 25, 21, 26, 21, 21, 21, 
--	21, 21, 21, 21, 43, 21, 21, 28, 
-+	21, 21, 21, 21, 44, 21, 21, 28, 
- 	29, 30, 21, 32, 33, 34, 35, 36, 
--	21, 22, 23, 24, 24, 21, 25, 21, 
-+	21, 22, 21, 24, 24, 21, 25, 21, 
- 	26, 21, 21, 21, 21, 21, 21, 21, 
--	27, 21, 21, 28, 29, 30, 31, 32, 
--	33, 34, 35, 36, 21, 45, 45, 44, 
--	5, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 46, 44, 44, 44, 44, 44, 
--	44, 14, 44, 44, 44, 18, 44, 45, 
--	45, 44, 5, 44, 45, 45, 44, 5, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	14, 44, 44, 44, 18, 44, 47, 44, 
--	45, 45, 44, 5, 44, 14, 44, 44, 
--	44, 44, 44, 44, 44, 48, 44, 44, 
--	44, 44, 44, 44, 14, 44, 45, 45, 
--	44, 5, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 48, 44, 44, 44, 44, 
--	44, 44, 14, 44, 45, 45, 44, 5, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	14, 44, 2, 44, 45, 45, 44, 5, 
--	44, 6, 44, 44, 44, 44, 44, 44, 
--	44, 49, 44, 44, 49, 44, 44, 44, 
--	14, 50, 44, 44, 18, 44, 2, 44, 
--	45, 45, 44, 5, 44, 6, 44, 44, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 14, 44, 44, 44, 
--	18, 44, 2, 44, 45, 45, 44, 5, 
--	44, 6, 44, 44, 44, 44, 44, 44, 
--	44, 49, 44, 44, 44, 44, 44, 44, 
--	14, 50, 44, 44, 18, 44, 2, 44, 
--	45, 45, 44, 5, 44, 6, 44, 44, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 14, 50, 44, 44, 
--	18, 44, 51, 51, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 51, 44, 2, 3, 45, 45, 44, 
--	5, 44, 6, 44, 44, 44, 44, 44, 
--	44, 44, 8, 44, 44, 10, 11, 12, 
--	13, 14, 15, 16, 17, 18, 19, 44, 
--	2, 44, 45, 45, 44, 5, 44, 6, 
--	44, 44, 44, 44, 44, 44, 44, 8, 
--	44, 44, 10, 11, 12, 13, 14, 15, 
--	16, 17, 18, 44, 2, 44, 45, 45, 
--	44, 5, 44, 6, 44, 44, 44, 44, 
--	44, 44, 44, 52, 44, 44, 44, 44, 
--	44, 44, 14, 15, 16, 17, 18, 44, 
--	2, 44, 45, 45, 44, 5, 44, 6, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 14, 15, 
--	16, 17, 18, 44, 2, 44, 45, 45, 
--	44, 5, 44, 6, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 14, 15, 16, 44, 18, 44, 
--	2, 44, 45, 45, 44, 5, 44, 6, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 14, 44, 
--	16, 44, 18, 44, 2, 44, 45, 45, 
--	44, 5, 44, 6, 44, 44, 44, 44, 
--	44, 44, 44, 44, 44, 44, 44, 44, 
--	44, 44, 14, 15, 16, 17, 18, 52, 
--	44, 2, 44, 45, 45, 44, 5, 44, 
--	6, 44, 44, 44, 44, 44, 44, 44, 
--	52, 44, 44, 10, 44, 12, 44, 14, 
--	15, 16, 17, 18, 44, 2, 44, 45, 
--	45, 44, 5, 44, 6, 44, 44, 44, 
--	44, 44, 44, 44, 52, 44, 44, 10, 
--	44, 44, 44, 14, 15, 16, 17, 18, 
--	44, 2, 44, 45, 45, 44, 5, 44, 
--	6, 44, 44, 44, 44, 44, 44, 44, 
--	52, 44, 44, 10, 11, 12, 44, 14, 
--	15, 16, 17, 18, 44, 2, 3, 45, 
--	45, 44, 5, 44, 6, 44, 44, 44, 
--	44, 44, 44, 44, 8, 44, 44, 10, 
-+	21, 21, 21, 28, 29, 30, 21, 32, 
-+	33, 34, 35, 36, 21, 22, 23, 24, 
-+	24, 21, 25, 21, 26, 21, 21, 21, 
-+	21, 21, 21, 21, 27, 21, 21, 28, 
-+	29, 30, 31, 32, 33, 34, 35, 36, 
-+	21, 46, 46, 45, 5, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 47, 45, 
-+	45, 45, 45, 45, 45, 14, 45, 45, 
-+	45, 18, 45, 46, 46, 45, 5, 45, 
-+	46, 46, 45, 5, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 14, 45, 45, 45, 
-+	18, 45, 48, 45, 46, 46, 45, 5, 
-+	45, 14, 45, 45, 45, 45, 45, 45, 
-+	45, 49, 45, 45, 45, 45, 45, 45, 
-+	14, 45, 46, 46, 45, 5, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 45, 49, 
-+	45, 45, 45, 45, 45, 45, 14, 45, 
-+	46, 46, 45, 5, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 14, 45, 2, 45, 
-+	46, 46, 45, 5, 45, 6, 45, 45, 
-+	45, 45, 45, 45, 45, 50, 45, 45, 
-+	50, 45, 45, 45, 14, 51, 45, 45, 
-+	18, 45, 2, 45, 46, 46, 45, 5, 
-+	45, 6, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	14, 45, 45, 45, 18, 45, 2, 45, 
-+	46, 46, 45, 5, 45, 6, 45, 45, 
-+	45, 45, 45, 45, 45, 50, 45, 45, 
-+	45, 45, 45, 45, 14, 51, 45, 45, 
-+	18, 45, 2, 45, 46, 46, 45, 5, 
-+	45, 6, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	14, 51, 45, 45, 18, 45, 52, 52, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 52, 45, 2, 
-+	3, 46, 46, 45, 5, 45, 6, 45, 
-+	45, 45, 45, 45, 45, 45, 8, 45, 
-+	45, 10, 11, 12, 13, 14, 15, 16, 
-+	17, 18, 19, 45, 2, 45, 46, 46, 
-+	45, 5, 45, 6, 45, 45, 45, 45, 
-+	45, 45, 45, 8, 45, 45, 10, 11, 
-+	12, 13, 14, 15, 16, 17, 18, 45, 
-+	2, 45, 46, 46, 45, 5, 45, 6, 
-+	45, 45, 45, 45, 45, 45, 45, 53, 
-+	45, 45, 45, 45, 45, 45, 14, 15, 
-+	16, 17, 18, 45, 2, 45, 46, 46, 
-+	45, 5, 45, 6, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 14, 15, 16, 17, 18, 45, 
-+	2, 45, 46, 46, 45, 5, 45, 6, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 14, 15, 
-+	16, 45, 18, 45, 2, 45, 46, 46, 
-+	45, 5, 45, 6, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 14, 45, 16, 45, 18, 45, 
-+	2, 45, 46, 46, 45, 5, 45, 6, 
-+	45, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 14, 15, 
-+	16, 17, 18, 53, 45, 2, 45, 46, 
-+	46, 45, 5, 45, 6, 45, 45, 45, 
-+	45, 45, 45, 45, 45, 45, 45, 10, 
-+	45, 12, 45, 14, 15, 16, 17, 18, 
-+	45, 2, 45, 46, 46, 45, 5, 45, 
-+	6, 45, 45, 45, 45, 45, 45, 45, 
-+	53, 45, 45, 10, 45, 45, 45, 14, 
-+	15, 16, 17, 18, 45, 2, 45, 46, 
-+	46, 45, 5, 45, 6, 45, 45, 45, 
-+	45, 45, 45, 45, 54, 45, 45, 10, 
-+	11, 12, 45, 14, 15, 16, 17, 18, 
-+	45, 2, 45, 46, 46, 45, 5, 45, 
-+	6, 45, 45, 45, 45, 45, 45, 45, 
-+	45, 45, 45, 10, 11, 12, 45, 14, 
-+	15, 16, 17, 18, 45, 2, 3, 46, 
-+	46, 45, 5, 45, 6, 45, 45, 45, 
-+	45, 45, 45, 45, 8, 45, 45, 10, 
- 	11, 12, 13, 14, 15, 16, 17, 18, 
--	44, 22, 23, 24, 24, 21, 25, 21, 
-+	45, 22, 23, 24, 24, 21, 25, 21, 
- 	26, 21, 21, 21, 21, 21, 21, 21, 
--	53, 21, 21, 28, 29, 30, 31, 32, 
--	33, 34, 35, 36, 37, 21, 22, 54, 
-+	55, 21, 21, 28, 29, 30, 31, 32, 
-+	33, 34, 35, 36, 37, 21, 22, 56, 
- 	24, 24, 21, 25, 21, 26, 21, 21, 
- 	21, 21, 21, 21, 21, 27, 21, 21, 
- 	28, 29, 30, 31, 32, 33, 34, 35, 
--	36, 21, 1, 1, 2, 3, 45, 45, 
--	44, 5, 44, 6, 1, 44, 44, 44, 
--	44, 1, 44, 8, 44, 44, 10, 11, 
-+	36, 21, 1, 1, 2, 3, 46, 46, 
-+	45, 5, 45, 6, 1, 45, 45, 45, 
-+	45, 1, 45, 8, 45, 45, 10, 11, 
- 	12, 13, 14, 15, 16, 17, 18, 19, 
--	44, 1, 44, 1, 1, 55, 55, 55, 
--	55, 55, 55, 55, 55, 1, 55, 55, 
--	55, 55, 1, 55, 55, 55, 55, 55, 
--	55, 55, 55, 55, 55, 55, 55, 55, 
--	55, 55, 1, 55, 56, 55, 0
-+	45, 1, 45, 1, 1, 57, 57, 57, 
-+	57, 57, 57, 57, 57, 1, 57, 57, 
-+	57, 57, 1, 57, 57, 57, 57, 57, 
-+	57, 57, 57, 57, 57, 57, 57, 57, 
-+	57, 57, 1, 57, 58, 57, 0
- };
- 
- static const char _myanmar_syllable_machine_trans_targs[] = {
--	0, 1, 23, 33, 0, 24, 30, 45, 
--	35, 48, 36, 41, 42, 43, 26, 38, 
--	39, 40, 29, 44, 49, 0, 2, 12, 
-+	0, 1, 24, 34, 0, 25, 31, 47, 
-+	36, 50, 37, 42, 43, 44, 27, 39, 
-+	40, 41, 30, 46, 51, 0, 2, 12, 
- 	0, 3, 9, 13, 14, 19, 20, 21, 
--	5, 16, 17, 18, 8, 22, 4, 6, 
--	7, 10, 11, 15, 0, 0, 25, 27, 
--	28, 31, 32, 34, 37, 46, 47, 0, 
--	0
-+	5, 16, 17, 18, 8, 23, 4, 6, 
-+	7, 10, 11, 15, 22, 0, 0, 26, 
-+	28, 29, 32, 33, 35, 38, 45, 48, 
-+	49, 0, 0
- };
- 
- static const char _myanmar_syllable_machine_trans_actions[] = {
- 	3, 0, 0, 0, 4, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 5, 0, 0, 
- 	6, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0, 0, 0, 7, 8, 0, 0, 
--	0, 0, 0, 0, 0, 0, 0, 9, 
--	10
-+	0, 0, 0, 0, 0, 7, 8, 0, 
-+	0, 0, 0, 0, 0, 0, 0, 0, 
-+	0, 9, 10
- };
- 
- static const char _myanmar_syllable_machine_to_state_actions[] = {
- 	1, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0
-+	0, 0, 0, 0
- };
- 
- static const char _myanmar_syllable_machine_from_state_actions[] = {
- 	2, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
- 	0, 0, 0, 0, 0, 0, 0, 0, 
--	0, 0
-+	0, 0, 0, 0
- };
- 
- static const short _myanmar_syllable_machine_eof_trans[] = {
- 	0, 22, 22, 22, 22, 22, 22, 22, 
- 	22, 22, 22, 22, 22, 22, 22, 22, 
--	22, 22, 22, 22, 22, 22, 22, 45, 
--	45, 45, 45, 45, 45, 45, 45, 45, 
--	45, 45, 45, 45, 45, 45, 45, 45, 
--	45, 45, 45, 45, 45, 22, 22, 45, 
--	56, 56
-+	22, 22, 22, 22, 22, 22, 22, 22, 
-+	46, 46, 46, 46, 46, 46, 46, 46, 
-+	46, 46, 46, 46, 46, 46, 46, 46, 
-+	46, 46, 46, 46, 46, 46, 46, 22, 
-+	22, 46, 58, 58
- };
- 
- static const int myanmar_syllable_machine_start = 0;
- static const int myanmar_syllable_machine_first_final = 0;
- static const int myanmar_syllable_machine_error = -1;
- 
- static const int myanmar_syllable_machine_en_main = 0;
- 
-@@ -304,47 +311,47 @@ static const int myanmar_syllable_machin
- 
- static void
- find_syllables (hb_buffer_t *buffer)
- {
-   unsigned int p, pe, eof, ts, te, act HB_UNUSED;
-   int cs;
-   hb_glyph_info_t *info = buffer->info;
-   
--#line 313 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 320 "hb-ot-shape-complex-myanmar-machine.hh"
- 	{
- 	cs = myanmar_syllable_machine_start;
- 	ts = 0;
- 	te = 0;
- 	act = 0;
- 	}
- 
- #line 114 "hb-ot-shape-complex-myanmar-machine.rl"
- 
- 
-   p = 0;
-   pe = eof = buffer->len;
- 
-   unsigned int syllable_serial = 1;
-   
--#line 329 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 336 "hb-ot-shape-complex-myanmar-machine.hh"
- 	{
- 	int _slen;
- 	int _trans;
- 	const unsigned char *_keys;
- 	const char *_inds;
- 	if ( p == pe )
- 		goto _test_eof;
- _resume:
- 	switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
- 	case 2:
- #line 1 "NONE"
- 	{ts = p;}
- 	break;
--#line 343 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 350 "hb-ot-shape-complex-myanmar-machine.hh"
- 	}
- 
- 	_keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
- 	_inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
- 
- 	_slen = _myanmar_syllable_machine_key_spans[cs];
- 	_trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
- 		( info[p].myanmar_category()) <= _keys[1] ?
-@@ -384,26 +391,26 @@ find_syllables (hb_buffer_t *buffer)
- 	case 7:
- #line 89 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p;p--;{ found_syllable (broken_cluster); }}
- 	break;
- 	case 9:
- #line 90 "hb-ot-shape-complex-myanmar-machine.rl"
- 	{te = p;p--;{ found_syllable (non_myanmar_cluster); }}
- 	break;
--#line 393 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 400 "hb-ot-shape-complex-myanmar-machine.hh"
- 	}
- 
- _again:
- 	switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
- 	case 1:
- #line 1 "NONE"
- 	{ts = 0;}
- 	break;
--#line 402 "hb-ot-shape-complex-myanmar-machine.hh"
-+#line 409 "hb-ot-shape-complex-myanmar-machine.hh"
- 	}
- 
- 	if ( ++p != pe )
- 		goto _resume;
- 	_test_eof: {}
- 	if ( p == eof )
- 	{
- 	if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
-diff --git a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
---- a/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
-+++ b/gfx/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.rl
-@@ -64,17 +64,17 @@ Ra   = 16;
- P    = 31;
- CS   = 19;
- 
- j = ZWJ|ZWNJ;			# Joiners
- k = (Ra As H);			# Kinzi
- 
- c = C|Ra;			# is_consonant
- 
--medial_group = MY? MR? MW? MH? As?;
-+medial_group = MY? As? MR? ((MW MH? | MH) As?)?;
- main_vowel_group = (VPre.VS?)* VAbv* VBlw* A* (DB As?)?;
- post_vowel_group = VPst MH? As* VAbv* A* (DB As?)?;
- pwo_tone_group = PT A* DB? As?;
- 
- complex_syllable_tail = As* medial_group main_vowel_group post_vowel_group* pwo_tone_group* V* j?;
- syllable_tail = (H (c|IV).VS?)* (H | complex_syllable_tail);
- 
- consonant_syllable =	(k|CS)? (c|IV|D|GB).VS? syllable_tail;
-diff --git a/gfx/harfbuzz/src/hb-ot-shape.cc b/gfx/harfbuzz/src/hb-ot-shape.cc
---- a/gfx/harfbuzz/src/hb-ot-shape.cc
-+++ b/gfx/harfbuzz/src/hb-ot-shape.cc
-@@ -93,31 +93,40 @@ hb_ot_shape_planner_t::hb_ot_shape_plann
- 
- void
- hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t           &plan,
- 				const hb_ot_shape_plan_key_t &key)
- {
-   plan.props = props;
-   plan.shaper = shaper;
-   map.compile (plan.map, key);
-+#ifndef HB_NO_SHAPE_AAT
-   if (apply_morx)
-     aat_map.compile (plan.aat_map);
-+#endif
- 
-+#ifndef HB_NO_OT_SHAPE_FRACTIONS
-   plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
-   plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
-   plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
-   plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
-+#endif
-+
-   plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
-   hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
- 		      HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
-+#ifndef HB_NO_OT_KERN
-   plan.kern_mask = plan.map.get_mask (kern_tag);
-+  plan.requested_kerning = !!plan.kern_mask;
-+#endif
-+#ifndef HB_NO_SHAPE_AAT
-   plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
-+  plan.requested_tracking = !!plan.trak_mask;
-+#endif
- 
--  plan.requested_kerning = !!plan.kern_mask;
--  plan.requested_tracking = !!plan.trak_mask;
-   bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
-   bool disable_gpos = plan.shaper->gpos_tag &&
- 		      plan.shaper->gpos_tag != plan.map.chosen_script[1];
- 
-   /*
-    * Decide who provides glyph classes. GDEF or Unicode.
-    */
- 
-@@ -147,50 +156,61 @@ hb_ot_shape_planner_t::compile (hb_ot_sh
- #ifndef HB_NO_SHAPE_AAT
-   else if (hb_aat_layout_has_positioning (face))
-     plan.apply_kerx = true;
- #endif
- 
-   if (!plan.apply_kerx && !has_gpos_kern)
-   {
-     /* Apparently Apple applies kerx if GPOS kern was not applied. */
--    if (0)
--      ;
- #ifndef HB_NO_SHAPE_AAT
--    else if (hb_aat_layout_has_positioning (face))
-+    if (hb_aat_layout_has_positioning (face))
-       plan.apply_kerx = true;
-+    else
- #endif
--    else if (hb_ot_layout_has_kerning (face))
-+#ifndef HB_NO_OT_KERN
-+    if (hb_ot_layout_has_kerning (face))
-       plan.apply_kern = true;
-+#endif
-   }
- 
-   plan.zero_marks = script_zero_marks &&
- 		    !plan.apply_kerx &&
--		    (!plan.apply_kern || !hb_ot_layout_has_machine_kerning (face));
-+		    (!plan.apply_kern
-+#ifndef HB_NO_OT_KERN
-+		     || !hb_ot_layout_has_machine_kerning (face)
-+#endif
-+		    );
-   plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
- 
-   plan.adjust_mark_positioning_when_zeroing = !plan.apply_gpos &&
- 					      !plan.apply_kerx &&
--					      (!plan.apply_kern || !hb_ot_layout_has_cross_kerning (face));
-+					      (!plan.apply_kern
-+#ifndef HB_NO_OT_KERN
-+					       || !hb_ot_layout_has_cross_kerning (face)
-+#endif
-+					      );
- 
-   plan.fallback_mark_positioning = plan.adjust_mark_positioning_when_zeroing &&
- 				   script_fallback_mark_positioning;
- 
- #ifndef HB_NO_SHAPE_AAT
-   /* Currently we always apply trak. */
-   plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face);
- #endif
- }
- 
- bool
- hb_ot_shape_plan_t::init0 (hb_face_t                     *face,
- 			   const hb_shape_plan_key_t     *key)
- {
-   map.init ();
-+#ifndef HB_NO_SHAPE_AAT
-   aat_map.init ();
-+#endif
- 
-   hb_ot_shape_planner_t planner (face,
- 				 &key->props);
- 
-   hb_ot_shape_collect_features (&planner,
- 				key->user_features,
- 				key->num_user_features);
- 
-@@ -208,44 +228,54 @@ hb_ot_shape_plan_t::init0 (hb_face_t    
- 
- void
- hb_ot_shape_plan_t::fini ()
- {
-   if (shaper->data_destroy)
-     shaper->data_destroy (const_cast<void *> (data));
- 
-   map.fini ();
-+#ifndef HB_NO_SHAPE_AAT
-   aat_map.fini ();
-+#endif
- }
- 
- void
- hb_ot_shape_plan_t::substitute (hb_font_t   *font,
- 				hb_buffer_t *buffer) const
- {
-+#ifndef HB_NO_SHAPE_AAT
-   if (unlikely (apply_morx))
-     hb_aat_layout_substitute (this, font, buffer);
-   else
-+#endif
-     map.substitute (this, font, buffer);
- }
- 
- void
- hb_ot_shape_plan_t::position (hb_font_t   *font,
- 			      hb_buffer_t *buffer) const
- {
-   if (this->apply_gpos)
-     map.position (this, font, buffer);
-+#ifndef HB_NO_SHAPE_AAT
-   else if (this->apply_kerx)
-     hb_aat_layout_position (this, font, buffer);
-+#endif
-+#ifndef HB_NO_OT_KERN
-   else if (this->apply_kern)
-     hb_ot_layout_kern (this, font, buffer);
-+#endif
-   else
-     _hb_ot_shape_fallback_kern (this, font, buffer);
- 
-+#ifndef HB_NO_SHAPE_AAT
-   if (this->apply_trak)
-     hb_aat_layout_track (this, font, buffer);
-+#endif
- }
- 
- 
- static const hb_ot_map_feature_t
- common_features[] =
- {
-   {HB_TAG('c','c','m','p'), F_GLOBAL},
-   {HB_TAG('l','o','c','l'), F_GLOBAL},
-@@ -287,28 +317,32 @@ hb_ot_shape_collect_features (hb_ot_shap
-       break;
-     case HB_DIRECTION_TTB:
-     case HB_DIRECTION_BTT:
-     case HB_DIRECTION_INVALID:
-     default:
-       break;
-   }
- 
-+#ifndef HB_NO_OT_SHAPE_FRACTIONS
-   /* Automatic fractions. */
-   map->add_feature (HB_TAG ('f','r','a','c'));
-   map->add_feature (HB_TAG ('n','u','m','r'));
-   map->add_feature (HB_TAG ('d','n','o','m'));
-+#endif
- 
-   /* Random! */
-   map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
- 
-+#ifndef HB_NO_SHAPE_AAT
-   /* Tracking.  We enable dummy feature here just to allow disabling
-    * AAT 'trak' table using features.
-    * https://github.com/harfbuzz/harfbuzz/issues/1303 */
-   map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
-+#endif
- 
-   map->enable_feature (HB_TAG ('H','A','R','F'));
- 
-   if (planner->shaper->collect_features)
-     planner->shaper->collect_features (planner);
- 
-   map->enable_feature (HB_TAG ('B','U','Z','Z'));
- 
-@@ -331,25 +365,27 @@ hb_ot_shape_collect_features (hb_ot_shap
-   {
-     const hb_feature_t *feature = &user_features[i];
-     map->add_feature (feature->tag,
- 		      (feature->start == HB_FEATURE_GLOBAL_START &&
- 		       feature->end == HB_FEATURE_GLOBAL_END) ?  F_GLOBAL : F_NONE,
- 		      feature->value);
-   }
- 
-+#ifndef HB_NO_SHAPE_AAT
-   if (planner->apply_morx)
-   {
-     hb_aat_map_builder_t *aat_map = &planner->aat_map;
-     for (unsigned int i = 0; i < num_user_features; i++)
-     {
-       const hb_feature_t *feature = &user_features[i];
-       aat_map->add_feature (feature->tag, feature->value);
-     }
-   }
-+#endif
- 
-   if (planner->shaper->override_features)
-     planner->shaper->override_features (planner);
- }
- 
- 
- /*
-  * shaper face data
-@@ -564,16 +600,20 @@ hb_ot_mirror_chars (const hb_ot_shape_co
-     else
-       info[i].codepoint = codepoint;
-   }
- }
- 
- static inline void
- hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c)
- {
-+#ifdef HB_NO_OT_SHAPE_FRACTIONS
-+  return;
-+#endif
-+
-   if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
-       !c->plan->has_frac)
-     return;
- 
-   hb_buffer_t *buffer = c->buffer;
- 
-   hb_mask_t pre_mask, post_mask;
-   if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
-@@ -774,18 +814,20 @@ hb_ot_substitute_pre (const hb_ot_shape_
- 
-   hb_ot_substitute_complex (c);
- }
- 
- static inline void
- hb_ot_substitute_post (const hb_ot_shape_context_t *c)
- {
-   hb_ot_hide_default_ignorables (c->buffer, c->font);
-+#ifndef HB_NO_SHAPE_AAT
-   if (c->plan->apply_morx)
-     hb_aat_layout_remove_deleted_glyphs (c->buffer);
-+#endif
- 
-   if (c->plan->shaper->postprocess_glyphs)
-     c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
- }
- 
- 
- /*
-  * Position
-@@ -909,18 +951,20 @@ hb_ot_position_complex (const hb_ot_shap
-       case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
-       case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
- 	break;
-     }
- 
-   /* Finish off.  Has to follow a certain order. */
-   hb_ot_layout_position_finish_advances (c->font, c->buffer);
-   hb_ot_zero_width_default_ignorables (c->buffer);
-+#ifndef HB_NO_SHAPE_AAT
-   if (c->plan->apply_morx)
-     hb_aat_layout_zero_width_deleted_glyphs (c->buffer);
-+#endif
-   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
- 
-   /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
-   if (c->font->has_glyph_h_origin_func ())
-     for (unsigned int i = 0; i < count; i++)
-       c->font->subtract_glyph_h_origin (info[i].codepoint,
- 					&pos[i].x_offset,
- 					&pos[i].y_offset);
-diff --git a/gfx/harfbuzz/src/hb-ot-shape.hh b/gfx/harfbuzz/src/hb-ot-shape.hh
---- a/gfx/harfbuzz/src/hb-ot-shape.hh
-+++ b/gfx/harfbuzz/src/hb-ot-shape.hh
-@@ -60,32 +60,62 @@ struct hb_shape_plan_key_t;
- 
- struct hb_ot_shape_plan_t
- {
-   hb_segment_properties_t props;
-   const struct hb_ot_complex_shaper_t *shaper;
-   hb_ot_map_t map;
-   hb_aat_map_t aat_map;
-   const void *data;
-+#ifndef HB_NO_OT_SHAPE_FRACTIONS
-   hb_mask_t frac_mask, numr_mask, dnom_mask;
-+#else
-+  static constexpr hb_mask_t frac_mask = 0;
-+  static constexpr hb_mask_t numr_mask = 0;
-+  static constexpr hb_mask_t dnom_mask = 0;
-+#endif
-   hb_mask_t rtlm_mask;
-+#ifndef HB_NO_OT_KERN
-   hb_mask_t kern_mask;
-+#else
-+  static constexpr hb_mask_t kern_mask = 0;
-+#endif
-+#ifndef HB_NO_SHAPE_AAT
-   hb_mask_t trak_mask;
-+#else
-+  static constexpr hb_mask_t trak_mask = 0;
-+#endif
- 
-+#ifndef HB_NO_OT_KERN
-   bool requested_kerning : 1;
-+#else
-+  static constexpr bool requested_kerning = false;
-+#endif
-+#ifndef HB_NO_SHAPE_AAT
-   bool requested_tracking : 1;
-+#else
-+  static constexpr bool requested_tracking = false;
-+#endif
-+#ifndef HB_NO_OT_SHAPE_FRACTIONS
-   bool has_frac : 1;
-+#else
-+  static constexpr bool has_frac = false;
-+#endif
-   bool has_gpos_mark : 1;
-   bool zero_marks : 1;
-   bool fallback_glyph_classes : 1;
-   bool fallback_mark_positioning : 1;
-   bool adjust_mark_positioning_when_zeroing : 1;
- 
-   bool apply_gpos : 1;
-+#ifndef HB_NO_OT_KERN
-   bool apply_kern : 1;
-+#else
-+  static constexpr bool apply_kern = false;
-+#endif
- #ifndef HB_NO_SHAPE_AAT
-   bool apply_kerx : 1;
-   bool apply_morx : 1;
-   bool apply_trak : 1;
- #else
-   static constexpr bool apply_kerx = false;
-   static constexpr bool apply_morx = false;
-   static constexpr bool apply_trak = false;
-diff --git a/gfx/harfbuzz/src/hb-ot-stat-table.hh b/gfx/harfbuzz/src/hb-ot-stat-table.hh
---- a/gfx/harfbuzz/src/hb-ot-stat-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-stat-table.hh
-@@ -54,24 +54,24 @@ enum
- 						 * value represents the “normal” value
- 						 * for the axis and may be omitted when
- 						 * composing name strings. */
-   // Reserved = 0xFFFC				/* Reserved for future use — set to zero. */
- };
- 
- struct AxisValueFormat1
- {
-+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-+
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
--  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
--
-   protected:
-   HBUINT16	format;		/* Format identifier — set to 1. */
-   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
- 				 * identifying the axis of design variation
- 				 * to which the axis value record applies.
- 				 * Must be less than designAxisCount. */
-   HBUINT16	flags;		/* Flags — see below for details. */
-   NameID	valueNameID;	/* The name ID for entries in the 'name' table
-@@ -79,24 +79,24 @@ struct AxisValueFormat1
- 				 * attribute value. */
-   Fixed		value;		/* A numeric value for this attribute value. */
-   public:
-   DEFINE_SIZE_STATIC (12);
- };
- 
- struct AxisValueFormat2
- {
-+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-+
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
--  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
--
-   protected:
-   HBUINT16	format;		/* Format identifier — set to 2. */
-   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
- 				 * identifying the axis of design variation
- 				 * to which the axis value record applies.
- 				 * Must be less than designAxisCount. */
-   HBUINT16	flags;		/* Flags — see below for details. */
-   NameID	valueNameID;	/* The name ID for entries in the 'name' table
-@@ -108,24 +108,24 @@ struct AxisValueFormat2
-   Fixed		rangeMaxValue;	/* The maximum value for a range associated
- 				 * with the specified name ID. */
-   public:
-   DEFINE_SIZE_STATIC (20);
- };
- 
- struct AxisValueFormat3
- {
-+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-+
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
--  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
--
-   protected:
-   HBUINT16	format;		/* Format identifier — set to 3. */
-   HBUINT16	axisIndex;	/* Zero-base index into the axis record array
- 				 * identifying the axis of design variation
- 				 * to which the axis value record applies.
- 				 * Must be less than designAxisCount. */
-   HBUINT16	flags;		/* Flags — see below for details. */
-   NameID	valueNameID;	/* The name ID for entries in the 'name' table
-@@ -152,24 +152,24 @@ struct AxisValueRecord
- 				 * applies. Must be less than designAxisCount. */
-   Fixed		value;		/* A numeric value for this attribute value. */
-   public:
-   DEFINE_SIZE_STATIC (6);
- };
- 
- struct AxisValueFormat4
- {
-+  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
-+
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
--  hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
--
-   protected:
-   HBUINT16	format;		/* Format identifier — set to 4. */
-   HBUINT16	axisCount;	/* The total number of axes contributing to
- 				 * this axis-values combination. */
-   HBUINT16	flags;		/* Flags — see below for details. */
-   NameID	valueNameID;	/* The name ID for entries in the 'name' table
- 				 * that provide a display string for this
- 				 * attribute value. */
-@@ -178,41 +178,41 @@ struct AxisValueFormat4
- 				 * combination of axis values, one for each
- 				 * contributing axis. */
-   public:
-   DEFINE_SIZE_ARRAY (8, axisValues);
- };
- 
- struct AxisValue
- {
-+  hb_ot_name_id_t get_value_name_id () const
-+  {
-+    switch (u.format)
-+    {
-+    case 1: return u.format1.get_value_name_id ();
-+    case 2: return u.format2.get_value_name_id ();
-+    case 3: return u.format3.get_value_name_id ();
-+    case 4: return u.format4.get_value_name_id ();
-+    default:return HB_OT_NAME_ID_INVALID;
-+    }
-+  }
-+
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     if (unlikely (!c->check_struct (this)))
-       return_trace (false);
- 
-     switch (u.format)
-     {
--    case 1:  return_trace (likely (u.format1.sanitize (c)));
--    case 2:  return_trace (likely (u.format2.sanitize (c)));
--    case 3:  return_trace (likely (u.format3.sanitize (c)));
--    case 4:  return_trace (likely (u.format4.sanitize (c)));
--    default: return_trace (true);
--    }
--  }
--
--  hb_ot_name_id_t get_value_name_id () const
--  {
--    switch (u.format)
--    {
--      case 1: return u.format1.get_value_name_id ();
--      case 2: return u.format2.get_value_name_id ();
--      case 3: return u.format3.get_value_name_id ();
--      case 4: return u.format4.get_value_name_id ();
--      default: return HB_OT_NAME_ID_INVALID;
-+    case 1: return_trace (u.format1.sanitize (c));
-+    case 2: return_trace (u.format2.sanitize (c));
-+    case 3: return_trace (u.format3.sanitize (c));
-+    case 4: return_trace (u.format4.sanitize (c));
-+    default:return_trace (true);
-     }
-   }
- 
-   protected:
-   union
-   {
-   HBUINT16		format;
-   AxisValueFormat1	format1;
-@@ -221,49 +221,39 @@ struct AxisValue
-   AxisValueFormat4	format4;
-   } u;
-   public:
-   DEFINE_SIZE_UNION (2, format);
- };
- 
- struct StatAxisRecord
- {
-+  hb_ot_name_id_t get_name_id () const { return nameID; }
-+
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (likely (c->check_struct (this)));
-   }
- 
--  hb_ot_name_id_t get_name_id () const { return nameID; }
--
-   protected:
-   Tag		tag;		/* A tag identifying the axis of design variation. */
-   NameID	nameID;		/* The name ID for entries in the 'name' table that
- 				 * provide a display string for this axis. */
-   HBUINT16	ordering;	/* A value that applications can use to determine
- 				 * primary sorting of face names, or for ordering
- 				 * of descriptors when composing family or face names. */
-   public:
-   DEFINE_SIZE_STATIC (8);
- };
- 
- struct STAT
- {
-   static constexpr hb_tag_t tableTag = HB_OT_TAG_STAT;
- 
--  bool sanitize (hb_sanitize_context_t *c) const
--  {
--    TRACE_SANITIZE (this);
--    return_trace (likely (c->check_struct (this) &&
--			  version.major == 1 &&
--                          version.minor > 0 &&
--			  designAxesOffset.sanitize (c, this, designAxisCount) &&
--			  offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
--  }
--
-   bool has_data () const { return version.to_int (); }
- 
-   unsigned get_design_axis_count () const { return designAxisCount; }
- 
-   hb_ot_name_id_t get_axis_record_name_id (unsigned axis_record_index) const
-   {
-     if (unlikely (axis_record_index >= designAxisCount)) return HB_OT_NAME_ID_INVALID;
-     const StatAxisRecord &axis_record = get_design_axes ()[axis_record_index];
-@@ -290,16 +280,26 @@ struct STAT
- 
-     + get_axis_value_offsets ()
-     | hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
-     | hb_map (&AxisValue::get_value_name_id)
-     | hb_sink (nameids_to_retain)
-     ;
-   }
- 
-+  bool sanitize (hb_sanitize_context_t *c) const
-+  {
-+    TRACE_SANITIZE (this);
-+    return_trace (likely (c->check_struct (this) &&
-+			  version.major == 1 &&
-+			  version.minor > 0 &&
-+			  designAxesOffset.sanitize (c, this, designAxisCount) &&
-+			  offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets))));
-+  }
-+
-   protected:
-   hb_array_t<const StatAxisRecord> const get_design_axes () const
-   { return (this+designAxesOffset).as_array (designAxisCount); }
- 
-   hb_array_t<const OffsetTo<AxisValue>> const get_axis_value_offsets () const
-   { return (this+offsetToAxisValueOffsets).as_array (axisValueCount); }
- 
- 
-diff --git a/gfx/harfbuzz/src/hb-ot-tag.cc b/gfx/harfbuzz/src/hb-ot-tag.cc
---- a/gfx/harfbuzz/src/hb-ot-tag.cc
-+++ b/gfx/harfbuzz/src/hb-ot-tag.cc
-@@ -140,17 +140,19 @@ hb_ot_all_tags_from_script (hb_script_t 
- 			    unsigned int *count /* IN/OUT */,
- 			    hb_tag_t     *tags /* OUT */)
- {
-   unsigned int i = 0;
- 
-   hb_tag_t new_tag = hb_ot_new_tag_from_script (script);
-   if (unlikely (new_tag != HB_OT_TAG_DEFAULT_SCRIPT))
-   {
--    tags[i++] = new_tag | '3';
-+    /* HB_SCRIPT_MYANMAR maps to 'mym2', but there is no 'mym3'. */
-+    if (new_tag != HB_TAG('m','y','m','2'))
-+      tags[i++] = new_tag | '3';
-     if (*count > i)
-       tags[i++] = new_tag;
-   }
- 
-   if (*count > i)
-   {
-     hb_tag_t old_tag = hb_ot_old_tag_from_script (script);
-     if (old_tag != HB_OT_TAG_DEFAULT_SCRIPT)
-@@ -298,38 +300,38 @@ hb_ot_tags_from_language (const char   *
- 
- static bool
- parse_private_use_subtag (const char     *private_use_subtag,
- 			  unsigned int   *count,
- 			  hb_tag_t       *tags,
- 			  const char     *prefix,
- 			  unsigned char (*normalize) (unsigned char))
- {
--  if (private_use_subtag && count && tags && *count)
--  {
--    const char *s = strstr (private_use_subtag, prefix);
--    if (s)
--    {
--      char tag[4];
--      int i;
--      s += strlen (prefix);
--      for (i = 0; i < 4 && ISALNUM (s[i]); i++)
--	tag[i] = normalize (s[i]);
--      if (i)
--      {
--	for (; i < 4; i++)
--	  tag[i] = ' ';
--	tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
--	if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
--	  tags[0] ^= ~0xDFDFDFDF;
--	*count = 1;
--	return false;
--      }
--    }
--  }
-+#ifdef HB_NO_LANGUAGE_PRIVATE_SUBTAG
-+  return false;
-+#endif
-+
-+  if (!(private_use_subtag && count && tags && *count)) return false;
-+
-+  const char *s = strstr (private_use_subtag, prefix);
-+  if (!s) return false;
-+
-+  char tag[4];
-+  int i;
-+  s += strlen (prefix);
-+  for (i = 0; i < 4 && ISALNUM (s[i]); i++)
-+    tag[i] = normalize (s[i]);
-+  if (!i) return false;
-+
-+  for (; i < 4; i++)
-+    tag[i] = ' ';
-+  tags[0] = HB_TAG (tag[0], tag[1], tag[2], tag[3]);
-+  if ((tags[0] & 0xDFDFDFDF) == HB_OT_TAG_DEFAULT_SCRIPT)
-+    tags[0] ^= ~0xDFDFDFDF;
-+  *count = 1;
-   return true;
- }
- 
- /**
-  * hb_ot_tags_from_script_and_language:
-  * @script: an #hb_script_t to convert.
-  * @language: an #hb_language_t to convert.
-  * @script_count: (allow-none): maximum number of script tags to retrieve (IN)
-@@ -387,18 +389,18 @@ hb_ot_tags_from_script_and_language (hb_
- 	    limit = s - 1;
- 	  }
- 	}
-       }
-       if (!limit)
- 	limit = s;
-     }
- 
--    needs_script = parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER);
--    needs_language = parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER);
-+    needs_script = !parse_private_use_subtag (private_use_subtag, script_count, script_tags, "-hbsc", TOLOWER);
-+    needs_language = !parse_private_use_subtag (private_use_subtag, language_count, language_tags, "-hbot", TOUPPER);
- 
-     if (needs_language && language_count && language_tags && *language_count)
-       hb_ot_tags_from_language (lang_str, limit, language_count, language_tags);
-   }
- 
-   if (needs_script && script_count && script_tags && *script_count)
-     hb_ot_all_tags_from_script (script, script_count, script_tags);
- }
-diff --git a/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
---- a/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-var-mvar-table.hh
-@@ -72,19 +72,19 @@ struct MVAR
- 				  valueRecordCount,
- 				  valueRecordSize));
-   }
- 
-   float get_var (hb_tag_t tag,
- 		 const int *coords, unsigned int coord_count) const
-   {
-     const VariationValueRecord *record;
--    record = (VariationValueRecord *) bsearch (&tag, valuesZ.arrayZ,
--					       valueRecordCount, valueRecordSize,
--					       tag_compare);
-+    record = (VariationValueRecord *) hb_bsearch (&tag, valuesZ.arrayZ,
-+						  valueRecordCount, valueRecordSize,
-+						  tag_compare);
-     if (!record)
-       return 0.;
- 
-     return (this+varStore).get_delta (record->varIdx, coords, coord_count);
-   }
- 
- protected:
-   static int tag_compare (const void *pa, const void *pb)
-diff --git a/gfx/harfbuzz/src/hb-ot-var.cc b/gfx/harfbuzz/src/hb-ot-var.cc
---- a/gfx/harfbuzz/src/hb-ot-var.cc
-+++ b/gfx/harfbuzz/src/hb-ot-var.cc
-@@ -19,23 +19,25 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
--#include "hb-open-type.hh"
-+#include "hb.hh"
- 
--#include "hb-ot-face.hh"
-+#ifndef HB_NO_VAR
-+
-+#include "hb-ot-var.h"
-+
- #include "hb-ot-var-avar-table.hh"
- #include "hb-ot-var-fvar-table.hh"
- #include "hb-ot-var-mvar-table.hh"
--#include "hb-ot-var.h"
- 
- 
- /**
-  * SECTION:hb-ot-var
-  * @title: hb-ot-var
-  * @short_description: OpenType Font Variations
-  * @include: hb-ot.h
-  *
-@@ -208,8 +210,11 @@ hb_ot_var_normalize_coords (hb_face_t   
- 			    int *normalized_coords /* OUT */)
- {
-   const OT::fvar &fvar = *face->table.fvar;
-   for (unsigned int i = 0; i < coords_length; i++)
-     normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
- 
-   face->table.avar->map_coords (normalized_coords, coords_length);
- }
-+
-+
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-ot-vorg-table.hh b/gfx/harfbuzz/src/hb-ot-vorg-table.hh
---- a/gfx/harfbuzz/src/hb-ot-vorg-table.hh
-+++ b/gfx/harfbuzz/src/hb-ot-vorg-table.hh
-@@ -64,112 +64,60 @@ struct VORG
-   int get_y_origin (hb_codepoint_t glyph) const
-   {
-     unsigned int i;
-     if (!vertYOrigins.bfind (glyph, &i))
-       return defaultVertOriginY;
-     return vertYOrigins[i].vertOriginY;
-   }
- 
--  bool _subset (const hb_subset_plan_t *plan HB_UNUSED,
--		const VORG *vorg_table,
--		const hb_vector_t<VertOriginMetric> &subset_metrics,
--		unsigned int dest_sz,
--		void *dest) const
-+  template <typename Iterator,
-+            hb_requires (hb_is_iterator (Iterator))>
-+  void serialize (hb_serialize_context_t *c,
-+                  Iterator it,
-+                  FWORD defaultVertOriginY)
-   {
--    hb_serialize_context_t c (dest, dest_sz);
- 
--    VORG *subset_table = c.start_serialize<VORG> ();
--    if (unlikely (!c.extend_min (*subset_table)))
--      return false;
--
--    subset_table->version.major = 1;
--    subset_table->version.minor = 0;
-+    if (unlikely (!c->extend_min ((*this))))  return;
- 
--    subset_table->defaultVertOriginY = vorg_table->defaultVertOriginY;
--    subset_table->vertYOrigins.len = subset_metrics.length;
-+    this->version.major = 1;
-+    this->version.minor = 0;
- 
--    bool success = true;
--    if (subset_metrics.length > 0)
--    {
--      unsigned int  size = VertOriginMetric::static_size * subset_metrics.length;
--      VertOriginMetric  *metrics = c.allocate_size<VertOriginMetric> (size);
--      if (likely (metrics != nullptr))
--        memcpy (metrics, &subset_metrics[0], size);
--      else
--        success = false;
--    }
--    c.end_serialize ();
-+    this->defaultVertOriginY = defaultVertOriginY;
-+    this->vertYOrigins.len = it.len ();
- 
--    return success;
-+    + it
-+    | hb_apply ([c] (const VertOriginMetric& _) { c->copy (_);})
-+    ;
-   }
- 
--  bool subset (hb_subset_plan_t *plan) const
-+  bool subset (hb_subset_context_t *c) const
-   {
--    hb_blob_t *vorg_blob = hb_sanitize_context_t().reference_table<VORG> (plan->source);
--    const VORG *vorg_table = vorg_blob->as<VORG> ();
--
--    /* count the number of glyphs to be included in the subset table */
--    hb_vector_t<VertOriginMetric> subset_metrics;
--    subset_metrics.init ();
--
--
--    hb_codepoint_t old_glyph = HB_SET_VALUE_INVALID;
--    unsigned int i = 0;
--    while (i < vertYOrigins.len
--           && plan->glyphset ()->next (&old_glyph))
--    {
--      while (old_glyph > vertYOrigins[i].glyph)
--      {
--        i++;
--        if (i >= vertYOrigins.len)
--          break;
--      }
-+    TRACE_SUBSET (this);
-+    VORG *vorg_prime = c->serializer->start_embed<VORG> ();
-+    if (unlikely (!c->serializer->check_success (vorg_prime))) return_trace (false);
- 
--      if (old_glyph == vertYOrigins[i].glyph)
--      {
--        hb_codepoint_t new_glyph;
--        if (plan->new_gid_for_old_gid (old_glyph, &new_glyph))
--        {
--          VertOriginMetric *metrics = subset_metrics.push ();
--          metrics->glyph = new_glyph;
--          metrics->vertOriginY = vertYOrigins[i].vertOriginY;
--        }
--      }
--    }
-+    auto it =
-+    + vertYOrigins.as_array ()
-+    | hb_filter (c->plan->glyphset (), &VertOriginMetric::glyph)
-+    | hb_map ([&] (const VertOriginMetric& _)
-+              {
-+                hb_codepoint_t new_glyph = HB_SET_VALUE_INVALID;
-+                c->plan->new_gid_for_old_gid (_.glyph, &new_glyph);
- 
--    /* alloc the new table */
--    unsigned int dest_sz = VORG::min_size + VertOriginMetric::static_size * subset_metrics.length;
--    void *dest = (void *) malloc (dest_sz);
--    if (unlikely (!dest))
--    {
--      subset_metrics.fini ();
--      hb_blob_destroy (vorg_blob);
--      return false;
--    }
-+                VertOriginMetric metric;
-+                metric.glyph = new_glyph;
-+                metric.vertOriginY = _.vertOriginY;
-+                return metric;
-+              })
-+    ;
- 
-     /* serialize the new table */
--    if (!_subset (plan, vorg_table, subset_metrics, dest_sz, dest))
--    {
--      subset_metrics.fini ();
--      free (dest);
--      hb_blob_destroy (vorg_blob);
--      return false;
--    }
--
--    hb_blob_t *result = hb_blob_create ((const char *)dest,
--                                        dest_sz,
--                                        HB_MEMORY_MODE_READONLY,
--                                        dest,
--                                        free);
--    bool success = plan->add_table (HB_OT_TAG_VORG, result);
--    hb_blob_destroy (result);
--    subset_metrics.fini ();
--    hb_blob_destroy (vorg_blob);
--    return success;
-+    vorg_prime->serialize (c->serializer, it, defaultVertOriginY);
-+    return_trace (true);
-   }
- 
-   bool sanitize (hb_sanitize_context_t *c) const
-   {
-     TRACE_SANITIZE (this);
-     return_trace (c->check_struct (this) &&
-                   version.major == 1 &&
-                   vertYOrigins.sanitize (c));
-diff --git a/gfx/harfbuzz/src/hb-serialize.hh b/gfx/harfbuzz/src/hb-serialize.hh
---- a/gfx/harfbuzz/src/hb-serialize.hh
-+++ b/gfx/harfbuzz/src/hb-serialize.hh
-@@ -370,17 +370,17 @@ struct hb_serialize_context_t
-   Type *embed (const Type &obj)
-   { return embed (hb_addressof (obj)); }
- 
-   template <typename Type, typename ...Ts> auto
-   _copy (const Type &src, hb_priority<1>, Ts&&... ds) HB_RETURN
-   (Type *, src.copy (this, hb_forward<Ts> (ds)...))
- 
-   template <typename Type> auto
--  _copy (const Type &src, hb_priority<0>) -> decltype (&(src = src))
-+  _copy (const Type &src, hb_priority<0>) -> decltype (&(hb_declval<Type> () = src))
-   {
-     Type *ret = this->allocate_size<Type> (sizeof (Type));
-     if (unlikely (!ret)) return nullptr;
-     *ret = src;
-     return ret;
-   }
- 
-   /* Like embed, but active: calls obj.operator=() or obj.copy() to transfer data
-diff --git a/gfx/harfbuzz/src/hb-shaper-list.hh b/gfx/harfbuzz/src/hb-shaper-list.hh
---- a/gfx/harfbuzz/src/hb-shaper-list.hh
-+++ b/gfx/harfbuzz/src/hb-shaper-list.hh
-@@ -42,11 +42,11 @@ HB_SHAPER_IMPLEMENT (uniscribe)
- #endif
- #ifdef HAVE_DIRECTWRITE
- HB_SHAPER_IMPLEMENT (directwrite)
- #endif
- #ifdef HAVE_CORETEXT
- HB_SHAPER_IMPLEMENT (coretext)
- #endif
- 
--#ifdef HAVE_FALLBACK
-+#ifndef HB_NO_FALLBACK_SHAPE
- HB_SHAPER_IMPLEMENT (fallback) /* <--- This should be last. */
- #endif
-diff --git a/gfx/harfbuzz/src/hb-static.cc b/gfx/harfbuzz/src/hb-static.cc
---- a/gfx/harfbuzz/src/hb-static.cc
-+++ b/gfx/harfbuzz/src/hb-static.cc
-@@ -34,18 +34,18 @@
- #include "hb-ot-layout-common.hh"
- #include "hb-ot-cmap-table.hh"
- #include "hb-ot-head-table.hh"
- #include "hb-ot-maxp-table.hh"
- 
- #ifndef HB_NO_VISIBILITY
- #include "hb-ot-name-language-static.hh"
- 
--hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
--/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
-+uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
-+/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
- 
- DEFINE_NULL_NAMESPACE_BYTES (OT, Index) =  {0xFF,0xFF};
- DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
- DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
- DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
- DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
- /* Hand-coded because Lookup is a template.  Sad. */
- const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
-diff --git a/gfx/harfbuzz/src/hb-subset-cff-common.cc b/gfx/harfbuzz/src/hb-subset-cff-common.cc
---- a/gfx/harfbuzz/src/hb-subset-cff-common.cc
-+++ b/gfx/harfbuzz/src/hb-subset-cff-common.cc
-@@ -19,16 +19,20 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Adobe Author(s): Michiharu Ariza
-  */
- 
-+#include "hb.hh"
-+
-+#ifndef HB_NO_SUBSET_CFF
-+
- #include "hb-ot-cff-common.hh"
- #include "hb-ot-cff2-table.hh"
- #include "hb-subset-cff-common.hh"
- 
- /* Disable FDSelect format 0 for compatibility with fonttools which doesn't seem choose it.
-  * Rarely any/much smaller than format 3 anyway. */
- #define CFF_SERIALIZE_FDSELECT_0  0
- 
-@@ -39,43 +43,43 @@ using namespace CFF;
-  * Determine an optimal FDSelect format according to a provided plan.
-  *
-  * Return value: FDSelect format, size, and ranges for the most compact subset FDSelect
-  * along with a font index remapping table
-  **/
- 
- bool
- hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
--			    unsigned int fdCount,
--			    const FDSelect &src, /* IN */
--			    unsigned int &subset_fd_count /* OUT */,
--			    unsigned int &subset_fdselect_size /* OUT */,
--			    unsigned int &subset_fdselect_format /* OUT */,
--			    hb_vector_t<code_pair_t> &fdselect_ranges /* OUT */,
--			    remap_t &fdmap /* OUT */)
-+			     unsigned int fdCount,
-+			     const FDSelect &src, /* IN */
-+			     unsigned int &subset_fd_count /* OUT */,
-+			     unsigned int &subset_fdselect_size /* OUT */,
-+			     unsigned int &subset_fdselect_format /* OUT */,
-+			     hb_vector_t<code_pair_t> &fdselect_ranges /* OUT */,
-+			     hb_inc_bimap_t &fdmap /* OUT */)
- {
-   subset_fd_count = 0;
-   subset_fdselect_size = 0;
-   subset_fdselect_format = 0;
--  unsigned int  num_ranges = 0;
-+  unsigned int num_ranges = 0;
- 
-   unsigned int subset_num_glyphs = plan->num_output_glyphs ();
-   if (subset_num_glyphs == 0)
-     return true;
- 
-   {
-     /* use hb_set to determine the subset of font dicts */
--    hb_set_t  *set = hb_set_create ();
-+    hb_set_t *set = hb_set_create ();
-     if (set == &Null (hb_set_t))
-       return false;
--    hb_codepoint_t  prev_fd = CFF_UNDEF_CODE;
-+    hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
-     for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
-     {
--      hb_codepoint_t	glyph;
--      hb_codepoint_t  	fd;
-+      hb_codepoint_t glyph;
-+      hb_codepoint_t fd;
-       if (!plan->old_gid_for_new_gid (i, &glyph))
-       {
- 	/* fonttools retains FDSelect & font dicts for missing glyphs. do the same */
- 	glyph = i;
-       }
-       fd = src.get_fd (glyph);
-       set->add (fd);
- 
-@@ -93,27 +97,23 @@ hb_plan_subset_cff_fdselect (const hb_su
-     {
-       /* all font dicts belong to the subset. no need to subset FDSelect & FDArray */
-       fdmap.identity (fdCount);
-       hb_set_destroy (set);
-     }
-     else
-     {
-       /* create a fdmap */
--      if (!fdmap.reset (fdCount))
--      {
--	hb_set_destroy (set);
--	return false;
--      }
-+      fdmap.reset ();
- 
--      hb_codepoint_t  fd = CFF_UNDEF_CODE;
-+      hb_codepoint_t fd = CFF_UNDEF_CODE;
-       while (set->next (&fd))
- 	fdmap.add (fd);
-       hb_set_destroy (set);
--      if (unlikely (fdmap.get_count () != subset_fd_count))
-+      if (unlikely (fdmap.get_population () != subset_fd_count))
-       	return false;
-     }
- 
-     /* update each font dict index stored as "code" in fdselect_ranges */
-     for (unsigned int i = 0; i < fdselect_ranges.length; i++)
-       fdselect_ranges[i].code = fdmap[fdselect_ranges[i].code];
-   }
- 
-@@ -147,87 +147,82 @@ hb_plan_subset_cff_fdselect (const hb_su
-   }
- 
-   return true;
- }
- 
- template <typename FDSELECT3_4>
- static inline bool
- serialize_fdselect_3_4 (hb_serialize_context_t *c,
--			  const unsigned int num_glyphs,
--			  const FDSelect &src,
--			  unsigned int size,
--			  const hb_vector_t<code_pair_t> &fdselect_ranges)
-+			const unsigned int num_glyphs,
-+			const FDSelect &src,
-+			unsigned int size,
-+			const hb_vector_t<code_pair_t> &fdselect_ranges)
- {
-   TRACE_SERIALIZE (this);
-   FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
-   if (unlikely (p == nullptr)) return_trace (false);
-   p->nRanges () = fdselect_ranges.length;
-   for (unsigned int i = 0; i < fdselect_ranges.length; i++)
-   {
-     p->ranges[i].first = fdselect_ranges[i].glyph;
-     p->ranges[i].fd = fdselect_ranges[i].code;
-   }
--  p->sentinel() = num_glyphs;
-+  p->sentinel () = num_glyphs;
-   return_trace (true);
- }
- 
- /**
-  * hb_serialize_cff_fdselect
-  * Serialize a subset FDSelect format planned above.
-  **/
- bool
- hb_serialize_cff_fdselect (hb_serialize_context_t *c,
--			  const unsigned int num_glyphs,
--			  const FDSelect &src,
--			  unsigned int fd_count,
--			  unsigned int fdselect_format,
--			  unsigned int size,
--			  const hb_vector_t<code_pair_t> &fdselect_ranges)
-+			   const unsigned int num_glyphs,
-+			   const FDSelect &src,
-+			   unsigned int fd_count,
-+			   unsigned int fdselect_format,
-+			   unsigned int size,
-+			   const hb_vector_t<code_pair_t> &fdselect_ranges)
- {
-   TRACE_SERIALIZE (this);
--  FDSelect  *p = c->allocate_min<FDSelect> ();
-+  FDSelect *p = c->allocate_min<FDSelect> ();
-   if (unlikely (p == nullptr)) return_trace (false);
-   p->format = fdselect_format;
-   size -= FDSelect::min_size;
- 
-   switch (fdselect_format)
-   {
- #if CFF_SERIALIZE_FDSELECT_0
--    case 0:
-+  case 0:
-+  {
-+    FDSelect0 *p = c->allocate_size<FDSelect0> (size);
-+    if (unlikely (p == nullptr)) return_trace (false);
-+    unsigned int range_index = 0;
-+    unsigned int fd = fdselect_ranges[range_index++].code;
-+    for (unsigned int i = 0; i < num_glyphs; i++)
-     {
--      FDSelect0 *p = c->allocate_size<FDSelect0> (size);
--      if (unlikely (p == nullptr)) return_trace (false);
--      unsigned int range_index = 0;
--      unsigned int  fd = fdselect_ranges[range_index++].code;
--      for (unsigned int i = 0; i < num_glyphs; i++)
-+      if ((range_index < fdselect_ranges.len) &&
-+	  (i >= fdselect_ranges[range_index].glyph))
-       {
--	if ((range_index < fdselect_ranges.len) &&
--	    (i >= fdselect_ranges[range_index].glyph))
--	{
--	  fd = fdselect_ranges[range_index++].code;
--	}
--	p->fds[i] = fd;
-+	fd = fdselect_ranges[range_index++].code;
-       }
--      break;
-+      p->fds[i] = fd;
-     }
-+    return_trace (true);
-+  }
- #endif /* CFF_SERIALIZE_FDSELECT_0 */
- 
--    case 3:
--      return serialize_fdselect_3_4<FDSelect3> (c,
--						num_glyphs,
--						src,
--						size,
--						fdselect_ranges);
-+  case 3:
-+    return serialize_fdselect_3_4<FDSelect3> (c, num_glyphs, src,
-+					      size, fdselect_ranges);
-+
-+  case 4:
-+    return serialize_fdselect_3_4<FDSelect4> (c, num_glyphs, src,
-+					      size, fdselect_ranges);
- 
--    case 4:
--      return serialize_fdselect_3_4<FDSelect4> (c,
--						num_glyphs,
--						src,
--						size,
--						fdselect_ranges);
-+  default:
-+    return_trace (false);
-+  }
-+}
- 
--    default:
--      assert(false);
--  }
- 
--  return_trace (true);
--}
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-subset-cff-common.hh b/gfx/harfbuzz/src/hb-subset-cff-common.hh
---- a/gfx/harfbuzz/src/hb-subset-cff-common.hh
-+++ b/gfx/harfbuzz/src/hb-subset-cff-common.hh
-@@ -536,65 +536,55 @@ struct subr_subset_param_t
-   parsed_cs_str_t	*parsed_charstring;
-   parsed_cs_str_vec_t	*parsed_global_subrs;
-   parsed_cs_str_vec_t	*parsed_local_subrs;
-   hb_set_t      *global_closure;
-   hb_set_t      *local_closure;
-   bool	  drop_hints;
- };
- 
--struct subr_remap_t : remap_t
-+struct subr_remap_t : hb_inc_bimap_t
- {
-   void create (hb_set_t *closure)
-   {
-     /* create a remapping of subroutine numbers from old to new.
-      * no optimization based on usage counts. fonttools doesn't appear doing that either.
-      */
--    reset (closure->get_max () + 1);
--    for (hb_codepoint_t old_num = 0; old_num < length; old_num++)
--    {
--      if (hb_set_has (closure, old_num))
--	add (old_num);
--    }
-+    
-+    hb_codepoint_t old_num = HB_SET_VALUE_INVALID;
-+    while (hb_set_next (closure, &old_num))
-+      add (old_num);
- 
--    if (get_count () < 1240)
-+    if (get_population () < 1240)
-       bias = 107;
--    else if (get_count () < 33900)
-+    else if (get_population () < 33900)
-       bias = 1131;
-     else
-       bias = 32768;
-   }
- 
--  hb_codepoint_t operator[] (unsigned int old_num) const
--  {
--    if (old_num >= length)
--      return CFF_UNDEF_CODE;
--    else
--      return remap_t::operator[] (old_num);
--  }
--
-   int biased_num (unsigned int old_num) const
-   {
--    hb_codepoint_t new_num = (*this)[old_num];
-+    hb_codepoint_t new_num = get (old_num);
-     return (int)new_num - bias;
-   }
- 
-   protected:
-   int bias;
- };
- 
--struct subr_remap_ts
-+struct subr_remaps_t
- {
--  subr_remap_ts ()
-+  subr_remaps_t ()
-   {
-     global_remap.init ();
-     local_remaps.init ();
-   }
- 
--  ~subr_remap_ts () { fini (); }
-+  ~subr_remaps_t () { fini (); }
- 
-   void init (unsigned int fdCount)
-   {
-     local_remaps.resize (fdCount);
-     for (unsigned int i = 0; i < fdCount; i++)
-       local_remaps[i].init ();
-   }
- 
-@@ -760,17 +750,17 @@ struct subr_subsetter_t
-       if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
- 	return false;
-     }
-     return true;
-   }
- 
-   bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const
-   {
--    unsigned int  count = remap.get_count ();
-+    unsigned int  count = remap.get_population ();
- 
-     if (unlikely (!buffArray.resize (count)))
-       return false;
-     for (unsigned int old_num = 0; old_num < subrs.length; old_num++)
-     {
-       hb_codepoint_t new_num = remap[old_num];
-       if (new_num != CFF_UNDEF_CODE)
-       {
-@@ -1000,33 +990,33 @@ struct subr_subsetter_t
-   const hb_subset_plan_t	*plan;
- 
-   subr_closures_t		closures;
- 
-   parsed_cs_str_vec_t		parsed_charstrings;
-   parsed_cs_str_vec_t		parsed_global_subrs;
-   hb_vector_t<parsed_cs_str_vec_t>  parsed_local_subrs;
- 
--  subr_remap_ts			remaps;
-+  subr_remaps_t			remaps;
- 
-   private:
-   typedef typename SUBRS::count_type subr_count_type;
- };
- 
- } /* namespace CFF */
- 
- HB_INTERNAL bool
- hb_plan_subset_cff_fdselect (const hb_subset_plan_t *plan,
- 			    unsigned int fdCount,
- 			    const CFF::FDSelect &src, /* IN */
- 			    unsigned int &subset_fd_count /* OUT */,
- 			    unsigned int &subset_fdselect_size /* OUT */,
- 			    unsigned int &subset_fdselect_format /* OUT */,
- 			    hb_vector_t<CFF::code_pair_t> &fdselect_ranges /* OUT */,
--			    CFF::remap_t &fdmap /* OUT */);
-+			    hb_inc_bimap_t &fdmap /* OUT */);
- 
- HB_INTERNAL bool
- hb_serialize_cff_fdselect (hb_serialize_context_t *c,
- 			  unsigned int num_glyphs,
- 			  const CFF::FDSelect &src,
- 			  unsigned int fd_count,
- 			  unsigned int fdselect_format,
- 			  unsigned int size,
-diff --git a/gfx/harfbuzz/src/hb-subset-cff1.cc b/gfx/harfbuzz/src/hb-subset-cff1.cc
---- a/gfx/harfbuzz/src/hb-subset-cff1.cc
-+++ b/gfx/harfbuzz/src/hb-subset-cff1.cc
-@@ -19,44 +19,47 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Adobe Author(s): Michiharu Ariza
-  */
- 
-+#include "hb.hh"
-+
-+#ifndef HB_NO_SUBSET_CFF
-+
- #include "hb-open-type.hh"
- #include "hb-ot-cff1-table.hh"
- #include "hb-set.h"
-+#include "hb-bimap.hh"
- #include "hb-subset-cff1.hh"
- #include "hb-subset-plan.hh"
- #include "hb-subset-cff-common.hh"
- #include "hb-cff1-interp-cs.hh"
- 
--#ifndef HB_NO_SUBSET_CFF
--
- using namespace CFF;
- 
--struct remap_sid_t : remap_t
-+struct remap_sid_t : hb_inc_bimap_t
- {
-   unsigned int add (unsigned int sid)
-   {
-     if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
--      return offset_sid (remap_t::add (unoffset_sid (sid)));
-+      return offset_sid (hb_inc_bimap_t::add (unoffset_sid (sid)));
-     else
-       return sid;
-   }
- 
-   unsigned int operator[] (unsigned int sid) const
-   {
-     if (is_std_std (sid) || (sid == CFF_UNDEF_SID))
-       return sid;
-     else
--      return offset_sid (remap_t::operator [] (unoffset_sid (sid)));
-+      return offset_sid (get (unoffset_sid (sid)));
-   }
- 
-   static const unsigned int num_std_strings = 391;
- 
-   static bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
-   static unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
-   static unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
- };
-@@ -574,32 +577,31 @@ struct cff_subset_plan {
- 
-     return Charset::calculate_serialized_size (
- 			subset_charset_format,
- 			subset_charset_format? subset_charset_ranges.length: plan->num_output_glyphs ());
-   }
- 
-   bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
-   {
--    if (unlikely (!sidmap.reset (acc.stringIndex->count)))
--      return false;
-+    sidmap.reset ();
- 
-     for (unsigned int i = 0; i < name_dict_values_t::ValCount; i++)
-     {
-       unsigned int sid = acc.topDict.nameSIDs[i];
-       if (sid != CFF_UNDEF_SID)
-       {
- 	(void)sidmap.add (sid);
- 	topDictModSIDs[i] = sidmap[sid];
-       }
-     }
- 
-     if (acc.fdArray != &Null(CFF1FDArray))
-       for (unsigned int i = 0; i < orig_fdcount; i++)
--	if (fdmap.includes (i))
-+	if (fdmap.has (i))
- 	  (void)sidmap.add (acc.fontDicts[i].fontName);
- 
-     return true;
-   }
- 
-   bool create (const OT::cff1::accelerator_subset_t &acc,
- 	       hb_subset_plan_t *plan)
-   {
-@@ -675,17 +677,17 @@ struct cff_subset_plan {
-     else
-       fdmap.identity (1);
- 
-     /* remove unused SIDs & reassign SIDs */
-     {
-       /* SIDs for name strings in dicts are added before glyph names so they fit in 16-bit int range */
-       if (unlikely (!collect_sids_in_dicts (acc)))
- 	return false;
--      if (unlikely (sidmap.get_count () > 0x8000))	/* assumption: a dict won't reference that many strings */
-+      if (unlikely (sidmap.get_population () > 0x8000))	/* assumption: a dict won't reference that many strings */
-       	return false;
-       if (subset_charset)
- 	offsets.charsetInfo.size = plan_subset_charset (acc, plan);
- 
-       topdict_mod.reassignSIDs (sidmap);
-     }
- 
-     /* String INDEX */
-@@ -732,17 +734,17 @@ struct cff_subset_plan {
-       if (!offsets.localSubrsInfos.resize (orig_fdcount))
- 	return false;
-       if (!subset_localsubrs.resize (orig_fdcount))
- 	return false;
-       for (unsigned int fd = 0; fd < orig_fdcount; fd++)
-       {
- 	subset_localsubrs[fd].init ();
- 	offsets.localSubrsInfos[fd].init ();
--	if (fdmap.includes (fd))
-+	if (fdmap.has (fd))
- 	{
- 	  if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
- 	    return false;
- 
- 	  unsigned int dataSize = subset_localsubrs[fd].total_size ();
- 	  if (dataSize > 0)
- 	  {
- 	    offsets.localSubrsInfos[fd].offset = final_size;
-@@ -783,17 +785,17 @@ struct cff_subset_plan {
-     }
- 
-     /* FDArray (FDIndex) */
-     if (acc.fdArray != &Null(CFF1FDArray)) {
-       offsets.FDArrayInfo.offset = final_size;
-       cff1_font_dict_op_serializer_t fontSzr;
-       unsigned int dictsSize = 0;
-       for (unsigned int i = 0; i < acc.fontDicts.length; i++)
--	if (fdmap.includes (i))
-+	if (fdmap.has (i))
- 	  dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
- 
-       offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
-       if (unlikely (offsets.FDArrayInfo.offSize > 4))
-       	return false;
-       final_size += CFF1Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
-     }
- 
-@@ -806,17 +808,17 @@ struct cff_subset_plan {
-       	return false;
-       final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->num_output_glyphs (), dataSize);
-     }
- 
-     /* private dicts & local subrs */
-     offsets.privateDictInfo.offset = final_size;
-     for (unsigned int i = 0; i < orig_fdcount; i++)
-     {
--      if (fdmap.includes (i))
-+      if (fdmap.has (i))
-       {
- 	bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
- 	cff_private_dict_op_serializer_t privSzr (desubroutinize, plan->drop_hints);
- 	unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
- 	table_info_t  privInfo = { final_size, priv_size, 0 };
- 	font_dict_values_mod_t fontdict_mod;
- 	if (!acc.is_CID ())
- 	  fontdict_mod.init ( &Null(cff1_font_dict_values_t), CFF_UNDEF_SID, privInfo );
-@@ -850,17 +852,17 @@ struct cff_subset_plan {
-   unsigned int    num_glyphs;
-   unsigned int    orig_fdcount;
-   unsigned int    subset_fdcount;
-   unsigned int    subset_fdselect_format;
-   hb_vector_t<code_pair_t>   subset_fdselect_ranges;
- 
-   /* font dict index remap table from fullset FDArray to subset FDArray.
-    * set to CFF_UNDEF_CODE if excluded from subset */
--  remap_t   fdmap;
-+  hb_inc_bimap_t   fdmap;
- 
-   str_buff_vec_t		subset_charstrings;
-   str_buff_vec_t		subset_globalsubrs;
-   hb_vector_t<str_buff_vec_t>	subset_localsubrs;
-   hb_vector_t<font_dict_values_mod_t>  fontdicts_mod;
- 
-   bool		drop_hints;
- 
-@@ -1027,25 +1029,25 @@ static inline bool _write_cff1 (const cf
-       return false;
-     }
-   }
- 
-   /* private dicts & local subrs */
-   assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start));
-   for (unsigned int i = 0; i < acc.privateDicts.length; i++)
-   {
--    if (plan.fdmap.includes (i))
-+    if (plan.fdmap.has (i))
-     {
-       PrivateDict  *pd = c.start_embed<PrivateDict> ();
-       if (unlikely (pd == nullptr)) return false;
-       unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
-       bool result;
-       cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
-       /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
--      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
-+      unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
-       result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
-       if (unlikely (!result))
-       {
- 	DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
- 	return false;
-       }
-       if (plan.offsets.localSubrsInfos[i].size > 0)
-       {
-@@ -1116,9 +1118,10 @@ hb_subset_cff1 (hb_subset_plan_t *plan,
-   bool result = likely (acc.is_valid ()) &&
- 			_hb_subset_cff1 (acc, data, plan, prime);
-   hb_blob_destroy (cff_blob);
-   acc.fini ();
- 
-   return result;
- }
- 
-+
- #endif
-diff --git a/gfx/harfbuzz/src/hb-subset-cff2.cc b/gfx/harfbuzz/src/hb-subset-cff2.cc
---- a/gfx/harfbuzz/src/hb-subset-cff2.cc
-+++ b/gfx/harfbuzz/src/hb-subset-cff2.cc
-@@ -19,26 +19,28 @@
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Adobe Author(s): Michiharu Ariza
-  */
- 
-+#include "hb.hh"
-+
-+#ifndef HB_NO_SUBSET_CFF
-+
- #include "hb-open-type.hh"
- #include "hb-ot-cff2-table.hh"
- #include "hb-set.h"
- #include "hb-subset-cff2.hh"
- #include "hb-subset-plan.hh"
- #include "hb-subset-cff-common.hh"
- #include "hb-cff2-interp-cs.hh"
- 
--#ifndef HB_NO_SUBSET_CFF
--
- using namespace CFF;
- 
- struct cff2_sub_table_offsets_t : cff_sub_table_offsets_t
- {
-   cff2_sub_table_offsets_t ()
-     : cff_sub_table_offsets_t (),
-       varStoreOffset (0)
-   {}
-@@ -323,28 +325,25 @@ struct cff2_subset_plan {
-       if (!offsets.localSubrsInfos.resize (orig_fdcount))
- 	return false;
-       if (!subset_localsubrs.resize (orig_fdcount))
- 	return false;
-       for (unsigned int fd = 0; fd < orig_fdcount; fd++)
-       {
- 	subset_localsubrs[fd].init ();
- 	offsets.localSubrsInfos[fd].init ();
--	if (fdmap.includes (fd))
--	{
--	  if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
--	    return false;
-+        if (!subr_subsetter.encode_localsubrs (fd, subset_localsubrs[fd]))
-+          return false;
- 
--	  unsigned int dataSize = subset_localsubrs[fd].total_size ();
--	  if (dataSize > 0)
--	  {
--	    offsets.localSubrsInfos[fd].offset = final_size;
--	    offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
--	    offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
--	  }
-+        unsigned int dataSize = subset_localsubrs[fd].total_size ();
-+        if (dataSize > 0)
-+        {
-+          offsets.localSubrsInfos[fd].offset = final_size;
-+          offsets.localSubrsInfos[fd].offSize = calcOffSize (dataSize);
-+          offsets.localSubrsInfos[fd].size = CFF2Subrs::calculate_serialized_size (offsets.localSubrsInfos[fd].offSize, subset_localsubrs[fd].length, dataSize);
- 	}
-       }
-     }
- 
-     /* global subrs */
-     offsets.globalSubrsInfo.offset = final_size;
-     final_size += offsets.globalSubrsInfo.size;
- 
-@@ -375,17 +374,17 @@ struct cff2_subset_plan {
-       fdmap.identity (1);
- 
-     /* FDArray (FDIndex) */
-     {
-       offsets.FDArrayInfo.offset = final_size;
-       cff_font_dict_op_serializer_t fontSzr;
-       unsigned int dictsSize = 0;
-       for (unsigned int i = 0; i < acc.fontDicts.length; i++)
--	if (fdmap.includes (i))
-+	if (fdmap.has (i))
- 	  dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
- 
-       offsets.FDArrayInfo.offSize = calcOffSize (dictsSize);
-       final_size += CFF2Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
-     }
- 
-     /* CharStrings */
-     {
-@@ -394,17 +393,17 @@ struct cff2_subset_plan {
-       offsets.charStringsInfo.offSize = calcOffSize (dataSize);
-       final_size += CFF2CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->num_output_glyphs (), dataSize);
-     }
- 
-     /* private dicts & local subrs */
-     offsets.privateDictsOffset = final_size;
-     for (unsigned int i = 0; i < orig_fdcount; i++)
-     {
--      if (fdmap.includes (i))
-+      if (fdmap.has (i))
-       {
- 	bool  has_localsubrs = offsets.localSubrsInfos[i].size > 0;
- 	cff_private_dict_op_serializer_t privSzr (desubroutinize, drop_hints);
- 	unsigned int  priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr, has_localsubrs);
- 	table_info_t  privInfo = { final_size, priv_size, 0 };
- 	privateDictInfos.push (privInfo);
- 	final_size += privInfo.size;
- 
-@@ -424,17 +423,17 @@ struct cff2_subset_plan {
-   unsigned int	final_size;
-   cff2_sub_table_offsets_t offsets;
- 
-   unsigned int    orig_fdcount;
-   unsigned int    subset_fdcount;
-   unsigned int    subset_fdselect_format;
-   hb_vector_t<code_pair_t>   subset_fdselect_ranges;
- 
--  remap_t   fdmap;
-+  hb_inc_bimap_t   fdmap;
- 
-   str_buff_vec_t	    subset_charstrings;
-   str_buff_vec_t	    subset_globalsubrs;
-   hb_vector_t<str_buff_vec_t> subset_localsubrs;
-   hb_vector_t<table_info_t>  privateDictInfos;
- 
-   bool	    drop_hints;
-   bool	    desubroutinize;
-@@ -534,25 +533,25 @@ static inline bool _write_cff2 (const cf
-       return false;
-     }
-   }
- 
-   /* private dicts & local subrs */
-   assert (plan.offsets.privateDictsOffset == (unsigned) (c.head - c.start));
-   for (unsigned int i = 0; i < acc.privateDicts.length; i++)
-   {
--    if (plan.fdmap.includes (i))
-+    if (plan.fdmap.has (i))
-     {
-       PrivateDict  *pd = c.start_embed<PrivateDict> ();
-       if (unlikely (pd == nullptr)) return false;
-       unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size;
-       bool result;
-       cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
-       /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
--      unsigned int  subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0;
-+      unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
-       result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
-       if (unlikely (!result))
-       {
- 	DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
- 	return false;
-       }
-       if (plan.offsets.localSubrsInfos[i].size > 0)
-       {
-@@ -624,9 +623,10 @@ hb_subset_cff2 (hb_subset_plan_t *plan,
- 		_hb_subset_cff2 (acc, data, plan, prime);
- 
-   hb_blob_destroy (cff2_blob);
-   acc.fini ();
- 
-   return result;
- }
- 
-+
- #endif
-diff --git a/gfx/harfbuzz/src/hb-subset-plan.cc b/gfx/harfbuzz/src/hb-subset-plan.cc
---- a/gfx/harfbuzz/src/hb-subset-plan.cc
-+++ b/gfx/harfbuzz/src/hb-subset-plan.cc
-@@ -189,33 +189,22 @@ static void
-   | hb_sink (glyph_map)
-   ;
- }
- 
- static void
- _nameid_closure (hb_face_t           *face,
-                  hb_set_t            *nameids)
- {
--  hb_tag_t table_tags[32];
--  unsigned count = ARRAY_LENGTH (table_tags);
--  hb_face_get_table_tags (face, 0, &count, table_tags);
--  for (unsigned int i = 0; i < count; i++)
--  {
--    hb_tag_t tag = table_tags[i];
--    switch (tag) {
--      case HB_OT_TAG_STAT:
--        face->table.STAT->collect_name_ids (nameids);
--        break;
--      case HB_OT_TAG_fvar:
--        face->table.fvar->collect_name_ids (nameids);
--        break;
--      default:
--        break;
--    }
--  }
-+#ifndef HB_NO_STAT
-+  face->table.STAT->collect_name_ids (nameids);
-+#endif
-+#ifndef HB_NO_VAR
-+  face->table.fvar->collect_name_ids (nameids);
-+#endif
- }
- 
- /**
-  * hb_subset_plan_create:
-  * Computes a plan for subsetting the supplied face according
-  * to a provided input. The plan describes
-  * which tables and glyphs should be retained.
-  *
-diff --git a/gfx/harfbuzz/src/hb-subset.cc b/gfx/harfbuzz/src/hb-subset.cc
---- a/gfx/harfbuzz/src/hb-subset.cc
-+++ b/gfx/harfbuzz/src/hb-subset.cc
-@@ -62,17 +62,17 @@ static inline unsigned int
- 
-   return 512 + (unsigned int) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
- }
- 
- template<typename TableType>
- static bool
- _subset2 (hb_subset_plan_t *plan)
- {
--  bool result = true;
-+  bool result = false;
-   hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
-   const TableType *table = source_blob->as<TableType> ();
- 
-   hb_tag_t tag = TableType::tableTag;
-   if (source_blob->data)
-   {
-     hb_vector_t<char> buf;
-     /* TODO Not all tables are glyph-related.  'name' table size for example should not be
-@@ -167,49 +167,49 @@ static bool
-       // TODO that won't work well if there is no glyf
-       DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
-       result = true;
-       break;
-     case HB_OT_TAG_hhea:
-       DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
-       return true;
-     case HB_OT_TAG_hmtx:
--      result = _subset<const OT::hmtx> (plan);
-+      result = _subset2<const OT::hmtx> (plan);
-       break;
-     case HB_OT_TAG_vhea:
-       DEBUG_MSG(SUBSET, nullptr, "skip vhea handled by vmtx");
-       return true;
-     case HB_OT_TAG_vmtx:
--      result = _subset<const OT::vmtx> (plan);
-+      result = _subset2<const OT::vmtx> (plan);
-       break;
-     case HB_OT_TAG_maxp:
--      result = _subset<const OT::maxp> (plan);
-+      result = _subset2<const OT::maxp> (plan);
-       break;
-     case HB_OT_TAG_loca:
-       DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
-       return true;
-     case HB_OT_TAG_cmap:
-       result = _subset<const OT::cmap> (plan);
-       break;
-     case HB_OT_TAG_OS2:
--      result = _subset<const OT::OS2> (plan);
-+      result = _subset2<const OT::OS2> (plan);
-       break;
-     case HB_OT_TAG_post:
--      result = _subset<const OT::post> (plan);
-+      result = _subset2<const OT::post> (plan);
-       break;
- 
- #ifndef HB_NO_SUBSET_CFF
-     case HB_OT_TAG_cff1:
-       result = _subset<const OT::cff1> (plan);
-       break;
-     case HB_OT_TAG_cff2:
-       result = _subset<const OT::cff2> (plan);
-       break;
-     case HB_OT_TAG_VORG:
--      result = _subset<const OT::VORG> (plan);
-+      result = _subset2<const OT::VORG> (plan);
-       break;
- #endif
- 
- #ifndef HB_NO_SUBSET_LAYOUT
-     case HB_OT_TAG_GDEF:
-       result = _subset2<const OT::GDEF> (plan);
-       break;
-     case HB_OT_TAG_GSUB:
-diff --git a/gfx/harfbuzz/src/hb-ucd-table.hh b/gfx/harfbuzz/src/hb-ucd-table.hh
---- a/gfx/harfbuzz/src/hb-ucd-table.hh
-+++ b/gfx/harfbuzz/src/hb-ucd-table.hh
-@@ -1,25 +1,24 @@
- /* == Start of generated table == */
- /*
-  * The following table is generated by running:
-  *
-- *   ./gen-ucd-table.py ucd.nonunihan.grouped.xml
-+ *   ./gen-ucd-table.py ucd.nounihan.grouped.xml
-  *
-  * on file with this description: Unicode 12.1.0
-  */
- 
- #ifndef HB_UCD_TABLE_HH
- #define HB_UCD_TABLE_HH
- 
--
- #include "hb.hh"
- 
- static const hb_script_t
--_hb_ucd_sc_map[138] =
-+_hb_ucd_sc_map[153] =
- {
-                    HB_SCRIPT_COMMON,              HB_SCRIPT_INHERITED,
-                   HB_SCRIPT_UNKNOWN,                 HB_SCRIPT_ARABIC,
-                  HB_SCRIPT_ARMENIAN,                HB_SCRIPT_BENGALI,
-                  HB_SCRIPT_CYRILLIC,             HB_SCRIPT_DEVANAGARI,
-                  HB_SCRIPT_GEORGIAN,                  HB_SCRIPT_GREEK,
-                  HB_SCRIPT_GUJARATI,               HB_SCRIPT_GURMUKHI,
-                    HB_SCRIPT_HANGUL,                    HB_SCRIPT_HAN,
-@@ -80,19 +79,27 @@ static const hb_script_t
-           HB_SCRIPT_PSALTER_PAHLAVI,                HB_SCRIPT_SIDDHAM,
-                   HB_SCRIPT_TIRHUTA,            HB_SCRIPT_WARANG_CITI,
-                      HB_SCRIPT_AHOM,  HB_SCRIPT_ANATOLIAN_HIEROGLYPHS,
-                    HB_SCRIPT_HATRAN,                HB_SCRIPT_MULTANI,
-             HB_SCRIPT_OLD_HUNGARIAN,            HB_SCRIPT_SIGNWRITING,
-                     HB_SCRIPT_ADLAM,              HB_SCRIPT_BHAIKSUKI,
-                   HB_SCRIPT_MARCHEN,                  HB_SCRIPT_OSAGE,
-                    HB_SCRIPT_TANGUT,                   HB_SCRIPT_NEWA,
-+            HB_SCRIPT_MASARAM_GONDI,                  HB_SCRIPT_NUSHU,
-+                  HB_SCRIPT_SOYOMBO,       HB_SCRIPT_ZANABAZAR_SQUARE,
-+                    HB_SCRIPT_DOGRA,          HB_SCRIPT_GUNJALA_GONDI,
-+          HB_SCRIPT_HANIFI_ROHINGYA,                HB_SCRIPT_MAKASAR,
-+              HB_SCRIPT_MEDEFAIDRIN,            HB_SCRIPT_OLD_SOGDIAN,
-+                  HB_SCRIPT_SOGDIAN,                HB_SCRIPT_ELYMAIC,
-+              HB_SCRIPT_NANDINAGARI, HB_SCRIPT_NYIAKENG_PUACHUE_HMONG,
-+                   HB_SCRIPT_WANCHO,
- };
--static const hb_codepoint_t
--_hb_ucd_dm1_map[935] =
-+static const uint16_t
-+_hb_ucd_dm1_p0_map[825] =
- {
-    0x003Bu, 0x004Bu, 0x0060u, 0x00B4u, 0x00B7u, 0x00C5u, 0x02B9u, 0x0300u,
-    0x0301u, 0x0313u, 0x0385u, 0x0386u, 0x0388u, 0x0389u, 0x038Au, 0x038Cu,
-    0x038Eu, 0x038Fu, 0x0390u, 0x03A9u, 0x03ACu, 0x03ADu, 0x03AEu, 0x03AFu,
-    0x03B0u, 0x03B9u, 0x03CCu, 0x03CDu, 0x03CEu, 0x2002u, 0x2003u, 0x3008u,
-    0x3009u, 0x349Eu, 0x34B9u, 0x34BBu, 0x34DFu, 0x3515u, 0x36EEu, 0x36FCu,
-    0x3781u, 0x382Fu, 0x3862u, 0x387Cu, 0x38C7u, 0x38E3u, 0x391Cu, 0x393Au,
-    0x3A2Eu, 0x3A6Cu, 0x3AE4u, 0x3B08u, 0x3B19u, 0x3B49u, 0x3B9Du, 0x3C18u,
-@@ -187,353 +194,681 @@ static const hb_codepoint_t
-    0x9415u, 0x958Bu, 0x95ADu, 0x95B7u, 0x962Eu, 0x964Bu, 0x964Du, 0x9675u,
-    0x9678u, 0x967Cu, 0x9686u, 0x96A3u, 0x96B7u, 0x96B8u, 0x96C3u, 0x96E2u,
-    0x96E3u, 0x96F6u, 0x96F7u, 0x9723u, 0x9732u, 0x9748u, 0x9756u, 0x97DBu,
-    0x97E0u, 0x97FFu, 0x980Bu, 0x9818u, 0x9829u, 0x983Bu, 0x985Eu, 0x98E2u,
-    0x98EFu, 0x98FCu, 0x9928u, 0x9929u, 0x99A7u, 0x99C2u, 0x99F1u, 0x99FEu,
-    0x9A6Au, 0x9B12u, 0x9B6Fu, 0x9C40u, 0x9C57u, 0x9CFDu, 0x9D67u, 0x9DB4u,
-    0x9DFAu, 0x9E1Eu, 0x9E7Fu, 0x9E97u, 0x9E9Fu, 0x9EBBu, 0x9ECEu, 0x9EF9u,
-    0x9EFEu, 0x9F05u, 0x9F0Fu, 0x9F16u, 0x9F3Bu, 0x9F43u, 0x9F8Du, 0x9F8Eu,
--   0x9F9Cu,0x20122u,0x2051Cu,0x20525u,0x2054Bu,0x2063Au,0x20804u,0x208DEu,
--  0x20A2Cu,0x20B63u,0x214E4u,0x216A8u,0x216EAu,0x219C8u,0x21B18u,0x21D0Bu,
--  0x21DE4u,0x21DE6u,0x22183u,0x2219Fu,0x22331u,0x226D4u,0x22844u,0x2284Au,
--  0x22B0Cu,0x22BF1u,0x2300Au,0x232B8u,0x2335Fu,0x23393u,0x2339Cu,0x233C3u,
--  0x233D5u,0x2346Du,0x236A3u,0x238A7u,0x23A8Du,0x23AFAu,0x23CBCu,0x23D1Eu,
--  0x23ED1u,0x23F5Eu,0x23F8Eu,0x24263u,0x242EEu,0x243ABu,0x24608u,0x24735u,
--  0x24814u,0x24C36u,0x24C92u,0x24FA1u,0x24FB8u,0x25044u,0x250F2u,0x250F3u,
--  0x25119u,0x25133u,0x25249u,0x2541Du,0x25626u,0x2569Au,0x256C5u,0x2597Cu,
--  0x25AA7u,0x25BABu,0x25C80u,0x25CD0u,0x25F86u,0x261DAu,0x26228u,0x26247u,
--  0x262D9u,0x2633Eu,0x264DAu,0x26523u,0x265A8u,0x267A7u,0x267B5u,0x26B3Cu,
--  0x26C36u,0x26CD5u,0x26D6Bu,0x26F2Cu,0x26FB1u,0x270D2u,0x273CAu,0x27667u,
--  0x278AEu,0x27966u,0x27CA8u,0x27ED3u,0x27F2Fu,0x285D2u,0x285EDu,0x2872Eu,
--  0x28BFAu,0x28D77u,0x29145u,0x291DFu,0x2921Au,0x2940Au,0x29496u,0x295B6u,
--  0x29B30u,0x2A0CEu,0x2A105u,0x2A20Eu,0x2A291u,0x2A392u,0x2A600u,
-+   0x9F9Cu,
-+};
-+static const uint16_t
-+_hb_ucd_dm1_p2_map[110] =
-+{
-+   0x0122u, 0x051Cu, 0x0525u, 0x054Bu, 0x063Au, 0x0804u, 0x08DEu, 0x0A2Cu,
-+   0x0B63u, 0x14E4u, 0x16A8u, 0x16EAu, 0x19C8u, 0x1B18u, 0x1D0Bu, 0x1DE4u,
-+   0x1DE6u, 0x2183u, 0x219Fu, 0x2331u, 0x26D4u, 0x2844u, 0x284Au, 0x2B0Cu,
-+   0x2BF1u, 0x300Au, 0x32B8u, 0x335Fu, 0x3393u, 0x339Cu, 0x33C3u, 0x33D5u,
-+   0x346Du, 0x36A3u, 0x38A7u, 0x3A8Du, 0x3AFAu, 0x3CBCu, 0x3D1Eu, 0x3ED1u,
-+   0x3F5Eu, 0x3F8Eu, 0x4263u, 0x42EEu, 0x43ABu, 0x4608u, 0x4735u, 0x4814u,
-+   0x4C36u, 0x4C92u, 0x4FA1u, 0x4FB8u, 0x5044u, 0x50F2u, 0x50F3u, 0x5119u,
-+   0x5133u, 0x5249u, 0x541Du, 0x5626u, 0x569Au, 0x56C5u, 0x597Cu, 0x5AA7u,
-+   0x5BABu, 0x5C80u, 0x5CD0u, 0x5F86u, 0x61DAu, 0x6228u, 0x6247u, 0x62D9u,
-+   0x633Eu, 0x64DAu, 0x6523u, 0x65A8u, 0x67A7u, 0x67B5u, 0x6B3Cu, 0x6C36u,
-+   0x6CD5u, 0x6D6Bu, 0x6F2Cu, 0x6FB1u, 0x70D2u, 0x73CAu, 0x7667u, 0x78AEu,
-+   0x7966u, 0x7CA8u, 0x7ED3u, 0x7F2Fu, 0x85D2u, 0x85EDu, 0x872Eu, 0x8BFAu,
-+   0x8D77u, 0x9145u, 0x91DFu, 0x921Au, 0x940Au, 0x9496u, 0x95B6u, 0x9B30u,
-+   0xA0CEu, 0xA105u, 0xA20Eu, 0xA291u, 0xA392u, 0xA600u,
-+};
-+static const uint32_t
-+_hb_ucd_dm2_u32_map[638] =
-+{
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x003Cu, 0x0338u, 0x226Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x003Du, 0x0338u, 0x2260u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x003Eu, 0x0338u, 0x226Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0300u, 0x00C0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0301u, 0x00C1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0302u, 0x00C2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0303u, 0x00C3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0304u, 0x0100u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0306u, 0x0102u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0307u, 0x0226u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0308u, 0x00C4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0309u, 0x1EA2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Au, 0x00C5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Cu, 0x01CDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x030Fu, 0x0200u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0311u, 0x0202u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0323u, 0x1EA0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0325u, 0x1E00u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0041u, 0x0328u, 0x0104u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0307u, 0x1E02u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0323u, 0x1E04u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0042u, 0x0331u, 0x1E06u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0301u, 0x0106u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0302u, 0x0108u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0307u, 0x010Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x030Cu, 0x010Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0043u, 0x0327u, 0x00C7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0307u, 0x1E0Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x030Cu, 0x010Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0323u, 0x1E0Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0327u, 0x1E10u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x032Du, 0x1E12u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0044u, 0x0331u, 0x1E0Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0300u, 0x00C8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0301u, 0x00C9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0302u, 0x00CAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0303u, 0x1EBCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0304u, 0x0112u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0306u, 0x0114u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0307u, 0x0116u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0308u, 0x00CBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0309u, 0x1EBAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x030Cu, 0x011Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x030Fu, 0x0204u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0311u, 0x0206u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0323u, 0x1EB8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0327u, 0x0228u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0328u, 0x0118u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x032Du, 0x1E18u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0045u, 0x0330u, 0x1E1Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0046u, 0x0307u, 0x1E1Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0301u, 0x01F4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0302u, 0x011Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0304u, 0x1E20u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0306u, 0x011Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0307u, 0x0120u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x030Cu, 0x01E6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0047u, 0x0327u, 0x0122u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0302u, 0x0124u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0307u, 0x1E22u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0308u, 0x1E26u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x030Cu, 0x021Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0323u, 0x1E24u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x0327u, 0x1E28u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0048u, 0x032Eu, 0x1E2Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0300u, 0x00CCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0301u, 0x00CDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0302u, 0x00CEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0303u, 0x0128u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0304u, 0x012Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0306u, 0x012Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0307u, 0x0130u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0308u, 0x00CFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0309u, 0x1EC8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x030Cu, 0x01CFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x030Fu, 0x0208u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0311u, 0x020Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0323u, 0x1ECAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0328u, 0x012Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0049u, 0x0330u, 0x1E2Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Au, 0x0302u, 0x0134u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0301u, 0x1E30u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x030Cu, 0x01E8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0323u, 0x1E32u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0327u, 0x0136u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Bu, 0x0331u, 0x1E34u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0301u, 0x0139u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x030Cu, 0x013Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0323u, 0x1E36u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0327u, 0x013Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x032Du, 0x1E3Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Cu, 0x0331u, 0x1E3Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0301u, 0x1E3Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0307u, 0x1E40u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Du, 0x0323u, 0x1E42u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0300u, 0x01F8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0301u, 0x0143u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0303u, 0x00D1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0307u, 0x1E44u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x030Cu, 0x0147u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0323u, 0x1E46u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0327u, 0x0145u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x032Du, 0x1E4Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Eu, 0x0331u, 0x1E48u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0300u, 0x00D2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0301u, 0x00D3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0302u, 0x00D4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0303u, 0x00D5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0304u, 0x014Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0306u, 0x014Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0307u, 0x022Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0308u, 0x00D6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0309u, 0x1ECEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Bu, 0x0150u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Cu, 0x01D1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x030Fu, 0x020Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0311u, 0x020Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x031Bu, 0x01A0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0323u, 0x1ECCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x004Fu, 0x0328u, 0x01EAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0050u, 0x0301u, 0x1E54u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0050u, 0x0307u, 0x1E56u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0301u, 0x0154u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0307u, 0x1E58u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x030Cu, 0x0158u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x030Fu, 0x0210u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0311u, 0x0212u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0323u, 0x1E5Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0327u, 0x0156u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0052u, 0x0331u, 0x1E5Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0301u, 0x015Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0302u, 0x015Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0307u, 0x1E60u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x030Cu, 0x0160u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0323u, 0x1E62u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0326u, 0x0218u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0053u, 0x0327u, 0x015Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0307u, 0x1E6Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x030Cu, 0x0164u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0323u, 0x1E6Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0326u, 0x021Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0327u, 0x0162u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x032Du, 0x1E70u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0054u, 0x0331u, 0x1E6Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0300u, 0x00D9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0301u, 0x00DAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0302u, 0x00DBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0303u, 0x0168u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0304u, 0x016Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0306u, 0x016Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0308u, 0x00DCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0309u, 0x1EE6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Au, 0x016Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Bu, 0x0170u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Cu, 0x01D3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x030Fu, 0x0214u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0311u, 0x0216u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x031Bu, 0x01AFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0323u, 0x1EE4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0324u, 0x1E72u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0328u, 0x0172u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x032Du, 0x1E76u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0055u, 0x0330u, 0x1E74u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0056u, 0x0303u, 0x1E7Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0056u, 0x0323u, 0x1E7Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0300u, 0x1E80u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0301u, 0x1E82u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0302u, 0x0174u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0307u, 0x1E86u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0308u, 0x1E84u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0057u, 0x0323u, 0x1E88u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0058u, 0x0307u, 0x1E8Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0058u, 0x0308u, 0x1E8Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0300u, 0x1EF2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0301u, 0x00DDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0302u, 0x0176u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0303u, 0x1EF8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0304u, 0x0232u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0307u, 0x1E8Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0308u, 0x0178u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0309u, 0x1EF6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0059u, 0x0323u, 0x1EF4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0301u, 0x0179u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0302u, 0x1E90u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0307u, 0x017Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x030Cu, 0x017Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0323u, 0x1E92u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x005Au, 0x0331u, 0x1E94u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0300u, 0x00E0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0301u, 0x00E1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0302u, 0x00E2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0303u, 0x00E3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0304u, 0x0101u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0306u, 0x0103u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0307u, 0x0227u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0308u, 0x00E4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0309u, 0x1EA3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Au, 0x00E5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Cu, 0x01CEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x030Fu, 0x0201u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0311u, 0x0203u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0323u, 0x1EA1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0325u, 0x1E01u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0061u, 0x0328u, 0x0105u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0307u, 0x1E03u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0323u, 0x1E05u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0062u, 0x0331u, 0x1E07u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0301u, 0x0107u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0302u, 0x0109u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0307u, 0x010Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x030Cu, 0x010Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0063u, 0x0327u, 0x00E7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0307u, 0x1E0Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x030Cu, 0x010Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0323u, 0x1E0Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0327u, 0x1E11u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x032Du, 0x1E13u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0064u, 0x0331u, 0x1E0Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0300u, 0x00E8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0301u, 0x00E9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0302u, 0x00EAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0303u, 0x1EBDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0304u, 0x0113u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0306u, 0x0115u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0307u, 0x0117u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0308u, 0x00EBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0309u, 0x1EBBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x030Cu, 0x011Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x030Fu, 0x0205u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0311u, 0x0207u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0323u, 0x1EB9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0327u, 0x0229u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0328u, 0x0119u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x032Du, 0x1E19u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0065u, 0x0330u, 0x1E1Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0066u, 0x0307u, 0x1E1Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0301u, 0x01F5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0302u, 0x011Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0304u, 0x1E21u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0306u, 0x011Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0307u, 0x0121u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x030Cu, 0x01E7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0067u, 0x0327u, 0x0123u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0302u, 0x0125u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0307u, 0x1E23u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0308u, 0x1E27u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x030Cu, 0x021Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0323u, 0x1E25u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0327u, 0x1E29u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x032Eu, 0x1E2Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0068u, 0x0331u, 0x1E96u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0300u, 0x00ECu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0301u, 0x00EDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0302u, 0x00EEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0303u, 0x0129u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0304u, 0x012Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0306u, 0x012Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0308u, 0x00EFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0309u, 0x1EC9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x030Cu, 0x01D0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x030Fu, 0x0209u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0311u, 0x020Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0323u, 0x1ECBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0328u, 0x012Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0069u, 0x0330u, 0x1E2Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Au, 0x0302u, 0x0135u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Au, 0x030Cu, 0x01F0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0301u, 0x1E31u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x030Cu, 0x01E9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0323u, 0x1E33u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0327u, 0x0137u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Bu, 0x0331u, 0x1E35u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0301u, 0x013Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x030Cu, 0x013Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0323u, 0x1E37u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0327u, 0x013Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x032Du, 0x1E3Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Cu, 0x0331u, 0x1E3Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0301u, 0x1E3Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0307u, 0x1E41u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Du, 0x0323u, 0x1E43u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0300u, 0x01F9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0301u, 0x0144u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0303u, 0x00F1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0307u, 0x1E45u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x030Cu, 0x0148u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0323u, 0x1E47u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0327u, 0x0146u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x032Du, 0x1E4Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Eu, 0x0331u, 0x1E49u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0300u, 0x00F2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0301u, 0x00F3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0302u, 0x00F4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0303u, 0x00F5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0304u, 0x014Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0306u, 0x014Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0307u, 0x022Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0308u, 0x00F6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0309u, 0x1ECFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Bu, 0x0151u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Cu, 0x01D2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x030Fu, 0x020Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0311u, 0x020Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x031Bu, 0x01A1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0323u, 0x1ECDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x006Fu, 0x0328u, 0x01EBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0070u, 0x0301u, 0x1E55u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0070u, 0x0307u, 0x1E57u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0301u, 0x0155u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0307u, 0x1E59u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x030Cu, 0x0159u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x030Fu, 0x0211u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0311u, 0x0213u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0323u, 0x1E5Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0327u, 0x0157u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0072u, 0x0331u, 0x1E5Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0301u, 0x015Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0302u, 0x015Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0307u, 0x1E61u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x030Cu, 0x0161u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0323u, 0x1E63u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0326u, 0x0219u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0073u, 0x0327u, 0x015Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0307u, 0x1E6Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0308u, 0x1E97u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x030Cu, 0x0165u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0323u, 0x1E6Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0326u, 0x021Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0327u, 0x0163u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x032Du, 0x1E71u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0074u, 0x0331u, 0x1E6Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0300u, 0x00F9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0301u, 0x00FAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0302u, 0x00FBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0303u, 0x0169u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0304u, 0x016Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0306u, 0x016Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0308u, 0x00FCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0309u, 0x1EE7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Au, 0x016Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Bu, 0x0171u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Cu, 0x01D4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x030Fu, 0x0215u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0311u, 0x0217u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x031Bu, 0x01B0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0323u, 0x1EE5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0324u, 0x1E73u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0328u, 0x0173u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x032Du, 0x1E77u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0075u, 0x0330u, 0x1E75u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0076u, 0x0303u, 0x1E7Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0076u, 0x0323u, 0x1E7Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0300u, 0x1E81u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0301u, 0x1E83u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0302u, 0x0175u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0307u, 0x1E87u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0308u, 0x1E85u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x030Au, 0x1E98u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0077u, 0x0323u, 0x1E89u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0078u, 0x0307u, 0x1E8Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0078u, 0x0308u, 0x1E8Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0300u, 0x1EF3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0301u, 0x00FDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0302u, 0x0177u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0303u, 0x1EF9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0304u, 0x0233u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0307u, 0x1E8Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0308u, 0x00FFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0309u, 0x1EF7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x030Au, 0x1E99u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0079u, 0x0323u, 0x1EF5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0301u, 0x017Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0302u, 0x1E91u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0307u, 0x017Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x030Cu, 0x017Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0323u, 0x1E93u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x007Au, 0x0331u, 0x1E95u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0300u, 0x1FEDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0301u, 0x0385u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00A8u, 0x0342u, 0x1FC1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0300u, 0x1EA6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0301u, 0x1EA4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0303u, 0x1EAAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C2u, 0x0309u, 0x1EA8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C4u, 0x0304u, 0x01DEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C5u, 0x0301u, 0x01FAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C6u, 0x0301u, 0x01FCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C6u, 0x0304u, 0x01E2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00C7u, 0x0301u, 0x1E08u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0300u, 0x1EC0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0301u, 0x1EBEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0303u, 0x1EC4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CAu, 0x0309u, 0x1EC2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00CFu, 0x0301u, 0x1E2Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0300u, 0x1ED2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0301u, 0x1ED0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0303u, 0x1ED6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D4u, 0x0309u, 0x1ED4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0301u, 0x1E4Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0304u, 0x022Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D5u, 0x0308u, 0x1E4Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D6u, 0x0304u, 0x022Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00D8u, 0x0301u, 0x01FEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0300u, 0x01DBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0301u, 0x01D7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x0304u, 0x01D5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00DCu, 0x030Cu, 0x01D9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0300u, 0x1EA7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0301u, 0x1EA5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0303u, 0x1EABu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E2u, 0x0309u, 0x1EA9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E4u, 0x0304u, 0x01DFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E5u, 0x0301u, 0x01FBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E6u, 0x0301u, 0x01FDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E6u, 0x0304u, 0x01E3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00E7u, 0x0301u, 0x1E09u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0300u, 0x1EC1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0301u, 0x1EBFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0303u, 0x1EC5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EAu, 0x0309u, 0x1EC3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00EFu, 0x0301u, 0x1E2Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0300u, 0x1ED3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0301u, 0x1ED1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0303u, 0x1ED7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F4u, 0x0309u, 0x1ED5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0301u, 0x1E4Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0304u, 0x022Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F5u, 0x0308u, 0x1E4Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F6u, 0x0304u, 0x022Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00F8u, 0x0301u, 0x01FFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0300u, 0x01DCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0301u, 0x01D8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x0304u, 0x01D6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x00FCu, 0x030Cu, 0x01DAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0300u, 0x1EB0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0301u, 0x1EAEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0303u, 0x1EB4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0102u, 0x0309u, 0x1EB2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0300u, 0x1EB1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0301u, 0x1EAFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0303u, 0x1EB5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0103u, 0x0309u, 0x1EB3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0112u, 0x0300u, 0x1E14u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0112u, 0x0301u, 0x1E16u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0113u, 0x0300u, 0x1E15u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0113u, 0x0301u, 0x1E17u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x014Cu, 0x0300u, 0x1E50u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x014Cu, 0x0301u, 0x1E52u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x014Du, 0x0300u, 0x1E51u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x014Du, 0x0301u, 0x1E53u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x015Au, 0x0307u, 0x1E64u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x015Bu, 0x0307u, 0x1E65u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0160u, 0x0307u, 0x1E66u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0161u, 0x0307u, 0x1E67u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0168u, 0x0301u, 0x1E78u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0169u, 0x0301u, 0x1E79u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x016Au, 0x0308u, 0x1E7Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x016Bu, 0x0308u, 0x1E7Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x017Fu, 0x0307u, 0x1E9Bu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0300u, 0x1EDCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0301u, 0x1EDAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0303u, 0x1EE0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0309u, 0x1EDEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A0u, 0x0323u, 0x1EE2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0300u, 0x1EDDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0301u, 0x1EDBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0303u, 0x1EE1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0309u, 0x1EDFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01A1u, 0x0323u, 0x1EE3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0300u, 0x1EEAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0301u, 0x1EE8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0303u, 0x1EEEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0309u, 0x1EECu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01AFu, 0x0323u, 0x1EF0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0300u, 0x1EEBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0301u, 0x1EE9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0303u, 0x1EEFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0309u, 0x1EEDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B0u, 0x0323u, 0x1EF1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01B7u, 0x030Cu, 0x01EEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01EAu, 0x0304u, 0x01ECu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x01EBu, 0x0304u, 0x01EDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0226u, 0x0304u, 0x01E0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0227u, 0x0304u, 0x01E1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0228u, 0x0306u, 0x1E1Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0229u, 0x0306u, 0x1E1Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x022Eu, 0x0304u, 0x0230u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x022Fu, 0x0304u, 0x0231u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0292u, 0x030Cu, 0x01EFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0308u, 0x0301u, 0x0000u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0300u, 0x1FBAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0301u, 0x0386u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0304u, 0x1FB9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0306u, 0x1FB8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0313u, 0x1F08u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0314u, 0x1F09u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0391u, 0x0345u, 0x1FBCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0300u, 0x1FC8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0301u, 0x0388u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0313u, 0x1F18u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0395u, 0x0314u, 0x1F19u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0300u, 0x1FCAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0301u, 0x0389u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0313u, 0x1F28u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0314u, 0x1F29u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0397u, 0x0345u, 0x1FCCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0300u, 0x1FDAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0301u, 0x038Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0304u, 0x1FD9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0306u, 0x1FD8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0308u, 0x03AAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0313u, 0x1F38u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0399u, 0x0314u, 0x1F39u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0300u, 0x1FF8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0301u, 0x038Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0313u, 0x1F48u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x039Fu, 0x0314u, 0x1F49u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A1u, 0x0314u, 0x1FECu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0300u, 0x1FEAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0301u, 0x038Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0304u, 0x1FE9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0306u, 0x1FE8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0308u, 0x03ABu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A5u, 0x0314u, 0x1F59u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0300u, 0x1FFAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0301u, 0x038Fu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0313u, 0x1F68u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0314u, 0x1F69u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03A9u, 0x0345u, 0x1FFCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03ACu, 0x0345u, 0x1FB4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03AEu, 0x0345u, 0x1FC4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0300u, 0x1F70u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0301u, 0x03ACu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0304u, 0x1FB1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0306u, 0x1FB0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0313u, 0x1F00u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0314u, 0x1F01u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0342u, 0x1FB6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B1u, 0x0345u, 0x1FB3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0300u, 0x1F72u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0301u, 0x03ADu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0313u, 0x1F10u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B5u, 0x0314u, 0x1F11u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0300u, 0x1F74u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0301u, 0x03AEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0313u, 0x1F20u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0314u, 0x1F21u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0342u, 0x1FC6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B7u, 0x0345u, 0x1FC3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0300u, 0x1F76u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0301u, 0x03AFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0304u, 0x1FD1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0306u, 0x1FD0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0308u, 0x03CAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0313u, 0x1F30u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0314u, 0x1F31u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03B9u, 0x0342u, 0x1FD6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0300u, 0x1F78u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0301u, 0x03CCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0313u, 0x1F40u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03BFu, 0x0314u, 0x1F41u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C1u, 0x0313u, 0x1FE4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C1u, 0x0314u, 0x1FE5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0300u, 0x1F7Au),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0301u, 0x03CDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0304u, 0x1FE1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0306u, 0x1FE0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0308u, 0x03CBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0313u, 0x1F50u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0314u, 0x1F51u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C5u, 0x0342u, 0x1FE6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0300u, 0x1F7Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0301u, 0x03CEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0313u, 0x1F60u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0314u, 0x1F61u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0342u, 0x1FF6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03C9u, 0x0345u, 0x1FF3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0300u, 0x1FD2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0301u, 0x0390u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CAu, 0x0342u, 0x1FD7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0300u, 0x1FE2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0301u, 0x03B0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CBu, 0x0342u, 0x1FE7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03CEu, 0x0345u, 0x1FF4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03D2u, 0x0301u, 0x03D3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x03D2u, 0x0308u, 0x03D4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0406u, 0x0308u, 0x0407u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0410u, 0x0306u, 0x04D0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0410u, 0x0308u, 0x04D2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0413u, 0x0301u, 0x0403u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0300u, 0x0400u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0306u, 0x04D6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0415u, 0x0308u, 0x0401u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0416u, 0x0306u, 0x04C1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0416u, 0x0308u, 0x04DCu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0417u, 0x0308u, 0x04DEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0300u, 0x040Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0304u, 0x04E2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0306u, 0x0419u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0418u, 0x0308u, 0x04E4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x041Au, 0x0301u, 0x040Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x041Eu, 0x0308u, 0x04E6u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0304u, 0x04EEu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0306u, 0x040Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x0308u, 0x04F0u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0423u, 0x030Bu, 0x04F2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0427u, 0x0308u, 0x04F4u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x042Bu, 0x0308u, 0x04F8u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x042Du, 0x0308u, 0x04ECu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0430u, 0x0306u, 0x04D1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0430u, 0x0308u, 0x04D3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0433u, 0x0301u, 0x0453u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0300u, 0x0450u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0306u, 0x04D7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0435u, 0x0308u, 0x0451u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0436u, 0x0306u, 0x04C2u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0436u, 0x0308u, 0x04DDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0437u, 0x0308u, 0x04DFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0300u, 0x045Du),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0304u, 0x04E3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0306u, 0x0439u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0438u, 0x0308u, 0x04E5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x043Au, 0x0301u, 0x045Cu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x043Eu, 0x0308u, 0x04E7u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0304u, 0x04EFu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0306u, 0x045Eu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x0308u, 0x04F1u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0443u, 0x030Bu, 0x04F3u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0447u, 0x0308u, 0x04F5u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x044Bu, 0x0308u, 0x04F9u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x044Du, 0x0308u, 0x04EDu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0456u, 0x0308u, 0x0457u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0474u, 0x030Fu, 0x0476u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x0475u, 0x030Fu, 0x0477u),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x04D8u, 0x0308u, 0x04DAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x04D9u, 0x0308u, 0x04DBu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x04E8u, 0x0308u, 0x04EAu),
-+   HB_CODEPOINT_ENCODE3_11_7_14 (0x04E9u, 0x0308u, 0x04EBu),
- };
- static const uint64_t
--_hb_ucd_dm2_map[1025] =
-+_hb_ucd_dm2_u64_map[387] =
- {
--     HB_CODEPOINT_ENCODE3 (0x003Cu, 0x0338u, 0x226Eu),   HB_CODEPOINT_ENCODE3 (0x003Du, 0x0338u, 0x2260u),
--     HB_CODEPOINT_ENCODE3 (0x003Eu, 0x0338u, 0x226Fu),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0300u, 0x00C0u),
--     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0301u, 0x00C1u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0302u, 0x00C2u),
--     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0303u, 0x00C3u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0304u, 0x0100u),
--     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0306u, 0x0102u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0307u, 0x0226u),
--     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0308u, 0x00C4u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0309u, 0x1EA2u),
--     HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Au, 0x00C5u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Cu, 0x01CDu),
--     HB_CODEPOINT_ENCODE3 (0x0041u, 0x030Fu, 0x0200u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0311u, 0x0202u),
--     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0323u, 0x1EA0u),   HB_CODEPOINT_ENCODE3 (0x0041u, 0x0325u, 0x1E00u),
--     HB_CODEPOINT_ENCODE3 (0x0041u, 0x0328u, 0x0104u),   HB_CODEPOINT_ENCODE3 (0x0042u, 0x0307u, 0x1E02u),
--     HB_CODEPOINT_ENCODE3 (0x0042u, 0x0323u, 0x1E04u),   HB_CODEPOINT_ENCODE3 (0x0042u, 0x0331u, 0x1E06u),
--     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0301u, 0x0106u),   HB_CODEPOINT_ENCODE3 (0x0043u, 0x0302u, 0x0108u),
--     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0307u, 0x010Au),   HB_CODEPOINT_ENCODE3 (0x0043u, 0x030Cu, 0x010Cu),
--     HB_CODEPOINT_ENCODE3 (0x0043u, 0x0327u, 0x00C7u),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x0307u, 0x1E0Au),
--     HB_CODEPOINT_ENCODE3 (0x0044u, 0x030Cu, 0x010Eu),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x0323u, 0x1E0Cu),
--     HB_CODEPOINT_ENCODE3 (0x0044u, 0x0327u, 0x1E10u),   HB_CODEPOINT_ENCODE3 (0x0044u, 0x032Du, 0x1E12u),
--     HB_CODEPOINT_ENCODE3 (0x0044u, 0x0331u, 0x1E0Eu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0300u, 0x00C8u),
--     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0301u, 0x00C9u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0302u, 0x00CAu),
--     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0303u, 0x1EBCu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0304u, 0x0112u),
--     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0306u, 0x0114u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0307u, 0x0116u),
--     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0308u, 0x00CBu),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0309u, 0x1EBAu),
--     HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Cu, 0x011Au),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x030Fu, 0x0204u),
--     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0311u, 0x0206u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0323u, 0x1EB8u),
--     HB_CODEPOINT_ENCODE3 (0x0045u, 0x0327u, 0x0228u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0328u, 0x0118u),
--     HB_CODEPOINT_ENCODE3 (0x0045u, 0x032Du, 0x1E18u),   HB_CODEPOINT_ENCODE3 (0x0045u, 0x0330u, 0x1E1Au),
--     HB_CODEPOINT_ENCODE3 (0x0046u, 0x0307u, 0x1E1Eu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0301u, 0x01F4u),
--     HB_CODEPOINT_ENCODE3 (0x0047u, 0x0302u, 0x011Cu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0304u, 0x1E20u),
--     HB_CODEPOINT_ENCODE3 (0x0047u, 0x0306u, 0x011Eu),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0307u, 0x0120u),
--     HB_CODEPOINT_ENCODE3 (0x0047u, 0x030Cu, 0x01E6u),   HB_CODEPOINT_ENCODE3 (0x0047u, 0x0327u, 0x0122u),
--     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0302u, 0x0124u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x0307u, 0x1E22u),
--     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0308u, 0x1E26u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x030Cu, 0x021Eu),
--     HB_CODEPOINT_ENCODE3 (0x0048u, 0x0323u, 0x1E24u),   HB_CODEPOINT_ENCODE3 (0x0048u, 0x0327u, 0x1E28u),
--     HB_CODEPOINT_ENCODE3 (0x0048u, 0x032Eu, 0x1E2Au),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0300u, 0x00CCu),
--     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0301u, 0x00CDu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0302u, 0x00CEu),
--     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0303u, 0x0128u),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0304u, 0x012Au),
--     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0306u, 0x012Cu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0307u, 0x0130u),
--     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0308u, 0x00CFu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0309u, 0x1EC8u),
--     HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Cu, 0x01CFu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x030Fu, 0x0208u),
--     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0311u, 0x020Au),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0323u, 0x1ECAu),
--     HB_CODEPOINT_ENCODE3 (0x0049u, 0x0328u, 0x012Eu),   HB_CODEPOINT_ENCODE3 (0x0049u, 0x0330u, 0x1E2Cu),
--     HB_CODEPOINT_ENCODE3 (0x004Au, 0x0302u, 0x0134u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0301u, 0x1E30u),
--     HB_CODEPOINT_ENCODE3 (0x004Bu, 0x030Cu, 0x01E8u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0323u, 0x1E32u),
--     HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0327u, 0x0136u),   HB_CODEPOINT_ENCODE3 (0x004Bu, 0x0331u, 0x1E34u),
--     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0301u, 0x0139u),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x030Cu, 0x013Du),
--     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0323u, 0x1E36u),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0327u, 0x013Bu),
--     HB_CODEPOINT_ENCODE3 (0x004Cu, 0x032Du, 0x1E3Cu),   HB_CODEPOINT_ENCODE3 (0x004Cu, 0x0331u, 0x1E3Au),
--     HB_CODEPOINT_ENCODE3 (0x004Du, 0x0301u, 0x1E3Eu),   HB_CODEPOINT_ENCODE3 (0x004Du, 0x0307u, 0x1E40u),
--     HB_CODEPOINT_ENCODE3 (0x004Du, 0x0323u, 0x1E42u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0300u, 0x01F8u),
--     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0301u, 0x0143u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0303u, 0x00D1u),
--     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0307u, 0x1E44u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x030Cu, 0x0147u),
--     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0323u, 0x1E46u),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0327u, 0x0145u),
--     HB_CODEPOINT_ENCODE3 (0x004Eu, 0x032Du, 0x1E4Au),   HB_CODEPOINT_ENCODE3 (0x004Eu, 0x0331u, 0x1E48u),
--     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0300u, 0x00D2u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0301u, 0x00D3u),
--     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0302u, 0x00D4u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0303u, 0x00D5u),
--     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0304u, 0x014Cu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0306u, 0x014Eu),
--     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0307u, 0x022Eu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0308u, 0x00D6u),
--     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0309u, 0x1ECEu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Bu, 0x0150u),
--     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Cu, 0x01D1u),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x030Fu, 0x020Cu),
--     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0311u, 0x020Eu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x031Bu, 0x01A0u),
--     HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0323u, 0x1ECCu),   HB_CODEPOINT_ENCODE3 (0x004Fu, 0x0328u, 0x01EAu),
--     HB_CODEPOINT_ENCODE3 (0x0050u, 0x0301u, 0x1E54u),   HB_CODEPOINT_ENCODE3 (0x0050u, 0x0307u, 0x1E56u),
--     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0301u, 0x0154u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0307u, 0x1E58u),
--     HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Cu, 0x0158u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x030Fu, 0x0210u),
--     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0311u, 0x0212u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0323u, 0x1E5Au),
--     HB_CODEPOINT_ENCODE3 (0x0052u, 0x0327u, 0x0156u),   HB_CODEPOINT_ENCODE3 (0x0052u, 0x0331u, 0x1E5Eu),
--     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0301u, 0x015Au),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x0302u, 0x015Cu),
--     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0307u, 0x1E60u),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x030Cu, 0x0160u),
--     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0323u, 0x1E62u),   HB_CODEPOINT_ENCODE3 (0x0053u, 0x0326u, 0x0218u),
--     HB_CODEPOINT_ENCODE3 (0x0053u, 0x0327u, 0x015Eu),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0307u, 0x1E6Au),
--     HB_CODEPOINT_ENCODE3 (0x0054u, 0x030Cu, 0x0164u),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0323u, 0x1E6Cu),
--     HB_CODEPOINT_ENCODE3 (0x0054u, 0x0326u, 0x021Au),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0327u, 0x0162u),
--     HB_CODEPOINT_ENCODE3 (0x0054u, 0x032Du, 0x1E70u),   HB_CODEPOINT_ENCODE3 (0x0054u, 0x0331u, 0x1E6Eu),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0300u, 0x00D9u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0301u, 0x00DAu),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0302u, 0x00DBu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0303u, 0x0168u),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0304u, 0x016Au),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0306u, 0x016Cu),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0308u, 0x00DCu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0309u, 0x1EE6u),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Au, 0x016Eu),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Bu, 0x0170u),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Cu, 0x01D3u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x030Fu, 0x0214u),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0311u, 0x0216u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x031Bu, 0x01AFu),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0323u, 0x1EE4u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x0324u, 0x1E72u),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0328u, 0x0172u),   HB_CODEPOINT_ENCODE3 (0x0055u, 0x032Du, 0x1E76u),
--     HB_CODEPOINT_ENCODE3 (0x0055u, 0x0330u, 0x1E74u),   HB_CODEPOINT_ENCODE3 (0x0056u, 0x0303u, 0x1E7Cu),
--     HB_CODEPOINT_ENCODE3 (0x0056u, 0x0323u, 0x1E7Eu),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0300u, 0x1E80u),
--     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0301u, 0x1E82u),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0302u, 0x0174u),
--     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0307u, 0x1E86u),   HB_CODEPOINT_ENCODE3 (0x0057u, 0x0308u, 0x1E84u),
--     HB_CODEPOINT_ENCODE3 (0x0057u, 0x0323u, 0x1E88u),   HB_CODEPOINT_ENCODE3 (0x0058u, 0x0307u, 0x1E8Au),
--     HB_CODEPOINT_ENCODE3 (0x0058u, 0x0308u, 0x1E8Cu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0300u, 0x1EF2u),
--     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0301u, 0x00DDu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0302u, 0x0176u),
--     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0303u, 0x1EF8u),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0304u, 0x0232u),
--     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0307u, 0x1E8Eu),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0308u, 0x0178u),
--     HB_CODEPOINT_ENCODE3 (0x0059u, 0x0309u, 0x1EF6u),   HB_CODEPOINT_ENCODE3 (0x0059u, 0x0323u, 0x1EF4u),
--     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0301u, 0x0179u),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x0302u, 0x1E90u),
--     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0307u, 0x017Bu),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x030Cu, 0x017Du),
--     HB_CODEPOINT_ENCODE3 (0x005Au, 0x0323u, 0x1E92u),   HB_CODEPOINT_ENCODE3 (0x005Au, 0x0331u, 0x1E94u),
--     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0300u, 0x00E0u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0301u, 0x00E1u),
--     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0302u, 0x00E2u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0303u, 0x00E3u),
--     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0304u, 0x0101u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0306u, 0x0103u),
--     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0307u, 0x0227u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0308u, 0x00E4u),
--     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0309u, 0x1EA3u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Au, 0x00E5u),
--     HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Cu, 0x01CEu),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x030Fu, 0x0201u),
--     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0311u, 0x0203u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0323u, 0x1EA1u),
--     HB_CODEPOINT_ENCODE3 (0x0061u, 0x0325u, 0x1E01u),   HB_CODEPOINT_ENCODE3 (0x0061u, 0x0328u, 0x0105u),
--     HB_CODEPOINT_ENCODE3 (0x0062u, 0x0307u, 0x1E03u),   HB_CODEPOINT_ENCODE3 (0x0062u, 0x0323u, 0x1E05u),
--     HB_CODEPOINT_ENCODE3 (0x0062u, 0x0331u, 0x1E07u),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0301u, 0x0107u),
--     HB_CODEPOINT_ENCODE3 (0x0063u, 0x0302u, 0x0109u),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0307u, 0x010Bu),
--     HB_CODEPOINT_ENCODE3 (0x0063u, 0x030Cu, 0x010Du),   HB_CODEPOINT_ENCODE3 (0x0063u, 0x0327u, 0x00E7u),
--     HB_CODEPOINT_ENCODE3 (0x0064u, 0x0307u, 0x1E0Bu),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x030Cu, 0x010Fu),
--     HB_CODEPOINT_ENCODE3 (0x0064u, 0x0323u, 0x1E0Du),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x0327u, 0x1E11u),
--     HB_CODEPOINT_ENCODE3 (0x0064u, 0x032Du, 0x1E13u),   HB_CODEPOINT_ENCODE3 (0x0064u, 0x0331u, 0x1E0Fu),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0300u, 0x00E8u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0301u, 0x00E9u),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0302u, 0x00EAu),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0303u, 0x1EBDu),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0304u, 0x0113u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0306u, 0x0115u),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0307u, 0x0117u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0308u, 0x00EBu),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0309u, 0x1EBBu),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Cu, 0x011Bu),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x030Fu, 0x0205u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0311u, 0x0207u),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0323u, 0x1EB9u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x0327u, 0x0229u),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0328u, 0x0119u),   HB_CODEPOINT_ENCODE3 (0x0065u, 0x032Du, 0x1E19u),
--     HB_CODEPOINT_ENCODE3 (0x0065u, 0x0330u, 0x1E1Bu),   HB_CODEPOINT_ENCODE3 (0x0066u, 0x0307u, 0x1E1Fu),
--     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0301u, 0x01F5u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x0302u, 0x011Du),
--     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0304u, 0x1E21u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x0306u, 0x011Fu),
--     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0307u, 0x0121u),   HB_CODEPOINT_ENCODE3 (0x0067u, 0x030Cu, 0x01E7u),
--     HB_CODEPOINT_ENCODE3 (0x0067u, 0x0327u, 0x0123u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0302u, 0x0125u),
--     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0307u, 0x1E23u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0308u, 0x1E27u),
--     HB_CODEPOINT_ENCODE3 (0x0068u, 0x030Cu, 0x021Fu),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x0323u, 0x1E25u),
--     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0327u, 0x1E29u),   HB_CODEPOINT_ENCODE3 (0x0068u, 0x032Eu, 0x1E2Bu),
--     HB_CODEPOINT_ENCODE3 (0x0068u, 0x0331u, 0x1E96u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0300u, 0x00ECu),
--     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0301u, 0x00EDu),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0302u, 0x00EEu),
--     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0303u, 0x0129u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0304u, 0x012Bu),
--     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0306u, 0x012Du),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0308u, 0x00EFu),
--     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0309u, 0x1EC9u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Cu, 0x01D0u),
--     HB_CODEPOINT_ENCODE3 (0x0069u, 0x030Fu, 0x0209u),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0311u, 0x020Bu),
--     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0323u, 0x1ECBu),   HB_CODEPOINT_ENCODE3 (0x0069u, 0x0328u, 0x012Fu),
--     HB_CODEPOINT_ENCODE3 (0x0069u, 0x0330u, 0x1E2Du),   HB_CODEPOINT_ENCODE3 (0x006Au, 0x0302u, 0x0135u),
--     HB_CODEPOINT_ENCODE3 (0x006Au, 0x030Cu, 0x01F0u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0301u, 0x1E31u),
--     HB_CODEPOINT_ENCODE3 (0x006Bu, 0x030Cu, 0x01E9u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0323u, 0x1E33u),
--     HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0327u, 0x0137u),   HB_CODEPOINT_ENCODE3 (0x006Bu, 0x0331u, 0x1E35u),
--     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0301u, 0x013Au),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x030Cu, 0x013Eu),
--     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0323u, 0x1E37u),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0327u, 0x013Cu),
--     HB_CODEPOINT_ENCODE3 (0x006Cu, 0x032Du, 0x1E3Du),   HB_CODEPOINT_ENCODE3 (0x006Cu, 0x0331u, 0x1E3Bu),
--     HB_CODEPOINT_ENCODE3 (0x006Du, 0x0301u, 0x1E3Fu),   HB_CODEPOINT_ENCODE3 (0x006Du, 0x0307u, 0x1E41u),
--     HB_CODEPOINT_ENCODE3 (0x006Du, 0x0323u, 0x1E43u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0300u, 0x01F9u),
--     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0301u, 0x0144u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0303u, 0x00F1u),
--     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0307u, 0x1E45u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x030Cu, 0x0148u),
--     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0323u, 0x1E47u),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0327u, 0x0146u),
--     HB_CODEPOINT_ENCODE3 (0x006Eu, 0x032Du, 0x1E4Bu),   HB_CODEPOINT_ENCODE3 (0x006Eu, 0x0331u, 0x1E49u),
--     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0300u, 0x00F2u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0301u, 0x00F3u),
--     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0302u, 0x00F4u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0303u, 0x00F5u),
--     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0304u, 0x014Du),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0306u, 0x014Fu),
--     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0307u, 0x022Fu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0308u, 0x00F6u),
--     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0309u, 0x1ECFu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Bu, 0x0151u),
--     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Cu, 0x01D2u),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x030Fu, 0x020Du),
--     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0311u, 0x020Fu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x031Bu, 0x01A1u),
--     HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0323u, 0x1ECDu),   HB_CODEPOINT_ENCODE3 (0x006Fu, 0x0328u, 0x01EBu),
--     HB_CODEPOINT_ENCODE3 (0x0070u, 0x0301u, 0x1E55u),   HB_CODEPOINT_ENCODE3 (0x0070u, 0x0307u, 0x1E57u),
--     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0301u, 0x0155u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0307u, 0x1E59u),
--     HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Cu, 0x0159u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x030Fu, 0x0211u),
--     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0311u, 0x0213u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0323u, 0x1E5Bu),
--     HB_CODEPOINT_ENCODE3 (0x0072u, 0x0327u, 0x0157u),   HB_CODEPOINT_ENCODE3 (0x0072u, 0x0331u, 0x1E5Fu),
--     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0301u, 0x015Bu),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x0302u, 0x015Du),
--     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0307u, 0x1E61u),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x030Cu, 0x0161u),
--     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0323u, 0x1E63u),   HB_CODEPOINT_ENCODE3 (0x0073u, 0x0326u, 0x0219u),
--     HB_CODEPOINT_ENCODE3 (0x0073u, 0x0327u, 0x015Fu),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x0307u, 0x1E6Bu),
--     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0308u, 0x1E97u),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x030Cu, 0x0165u),
--     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0323u, 0x1E6Du),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x0326u, 0x021Bu),
--     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0327u, 0x0163u),   HB_CODEPOINT_ENCODE3 (0x0074u, 0x032Du, 0x1E71u),
--     HB_CODEPOINT_ENCODE3 (0x0074u, 0x0331u, 0x1E6Fu),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0300u, 0x00F9u),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0301u, 0x00FAu),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0302u, 0x00FBu),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0303u, 0x0169u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0304u, 0x016Bu),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0306u, 0x016Du),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0308u, 0x00FCu),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0309u, 0x1EE7u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Au, 0x016Fu),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Bu, 0x0171u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Cu, 0x01D4u),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x030Fu, 0x0215u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0311u, 0x0217u),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x031Bu, 0x01B0u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0323u, 0x1EE5u),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x0324u, 0x1E73u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0328u, 0x0173u),
--     HB_CODEPOINT_ENCODE3 (0x0075u, 0x032Du, 0x1E77u),   HB_CODEPOINT_ENCODE3 (0x0075u, 0x0330u, 0x1E75u),
--     HB_CODEPOINT_ENCODE3 (0x0076u, 0x0303u, 0x1E7Du),   HB_CODEPOINT_ENCODE3 (0x0076u, 0x0323u, 0x1E7Fu),
--     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0300u, 0x1E81u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x0301u, 0x1E83u),
--     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0302u, 0x0175u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x0307u, 0x1E87u),
--     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0308u, 0x1E85u),   HB_CODEPOINT_ENCODE3 (0x0077u, 0x030Au, 0x1E98u),
--     HB_CODEPOINT_ENCODE3 (0x0077u, 0x0323u, 0x1E89u),   HB_CODEPOINT_ENCODE3 (0x0078u, 0x0307u, 0x1E8Bu),
--     HB_CODEPOINT_ENCODE3 (0x0078u, 0x0308u, 0x1E8Du),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0300u, 0x1EF3u),
--     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0301u, 0x00FDu),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0302u, 0x0177u),
--     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0303u, 0x1EF9u),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0304u, 0x0233u),
--     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0307u, 0x1E8Fu),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x0308u, 0x00FFu),
--     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0309u, 0x1EF7u),   HB_CODEPOINT_ENCODE3 (0x0079u, 0x030Au, 0x1E99u),
--     HB_CODEPOINT_ENCODE3 (0x0079u, 0x0323u, 0x1EF5u),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0301u, 0x017Au),
--     HB_CODEPOINT_ENCODE3 (0x007Au, 0x0302u, 0x1E91u),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0307u, 0x017Cu),
--     HB_CODEPOINT_ENCODE3 (0x007Au, 0x030Cu, 0x017Eu),   HB_CODEPOINT_ENCODE3 (0x007Au, 0x0323u, 0x1E93u),
--     HB_CODEPOINT_ENCODE3 (0x007Au, 0x0331u, 0x1E95u),   HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0300u, 0x1FEDu),
--     HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0301u, 0x0385u),   HB_CODEPOINT_ENCODE3 (0x00A8u, 0x0342u, 0x1FC1u),
--     HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0300u, 0x1EA6u),   HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0301u, 0x1EA4u),
--     HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0303u, 0x1EAAu),   HB_CODEPOINT_ENCODE3 (0x00C2u, 0x0309u, 0x1EA8u),
--     HB_CODEPOINT_ENCODE3 (0x00C4u, 0x0304u, 0x01DEu),   HB_CODEPOINT_ENCODE3 (0x00C5u, 0x0301u, 0x01FAu),
--     HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0301u, 0x01FCu),   HB_CODEPOINT_ENCODE3 (0x00C6u, 0x0304u, 0x01E2u),
--     HB_CODEPOINT_ENCODE3 (0x00C7u, 0x0301u, 0x1E08u),   HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0300u, 0x1EC0u),
--     HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0301u, 0x1EBEu),   HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0303u, 0x1EC4u),
--     HB_CODEPOINT_ENCODE3 (0x00CAu, 0x0309u, 0x1EC2u),   HB_CODEPOINT_ENCODE3 (0x00CFu, 0x0301u, 0x1E2Eu),
--     HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0300u, 0x1ED2u),   HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0301u, 0x1ED0u),
--     HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0303u, 0x1ED6u),   HB_CODEPOINT_ENCODE3 (0x00D4u, 0x0309u, 0x1ED4u),
--     HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0301u, 0x1E4Cu),   HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0304u, 0x022Cu),
--     HB_CODEPOINT_ENCODE3 (0x00D5u, 0x0308u, 0x1E4Eu),   HB_CODEPOINT_ENCODE3 (0x00D6u, 0x0304u, 0x022Au),
--     HB_CODEPOINT_ENCODE3 (0x00D8u, 0x0301u, 0x01FEu),   HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0300u, 0x01DBu),
--     HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0301u, 0x01D7u),   HB_CODEPOINT_ENCODE3 (0x00DCu, 0x0304u, 0x01D5u),
--     HB_CODEPOINT_ENCODE3 (0x00DCu, 0x030Cu, 0x01D9u),   HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0300u, 0x1EA7u),
--     HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0301u, 0x1EA5u),   HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0303u, 0x1EABu),
--     HB_CODEPOINT_ENCODE3 (0x00E2u, 0x0309u, 0x1EA9u),   HB_CODEPOINT_ENCODE3 (0x00E4u, 0x0304u, 0x01DFu),
--     HB_CODEPOINT_ENCODE3 (0x00E5u, 0x0301u, 0x01FBu),   HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0301u, 0x01FDu),
--     HB_CODEPOINT_ENCODE3 (0x00E6u, 0x0304u, 0x01E3u),   HB_CODEPOINT_ENCODE3 (0x00E7u, 0x0301u, 0x1E09u),
--     HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0300u, 0x1EC1u),   HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0301u, 0x1EBFu),
--     HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0303u, 0x1EC5u),   HB_CODEPOINT_ENCODE3 (0x00EAu, 0x0309u, 0x1EC3u),
--     HB_CODEPOINT_ENCODE3 (0x00EFu, 0x0301u, 0x1E2Fu),   HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0300u, 0x1ED3u),
--     HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0301u, 0x1ED1u),   HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0303u, 0x1ED7u),
--     HB_CODEPOINT_ENCODE3 (0x00F4u, 0x0309u, 0x1ED5u),   HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0301u, 0x1E4Du),
--     HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0304u, 0x022Du),   HB_CODEPOINT_ENCODE3 (0x00F5u, 0x0308u, 0x1E4Fu),
--     HB_CODEPOINT_ENCODE3 (0x00F6u, 0x0304u, 0x022Bu),   HB_CODEPOINT_ENCODE3 (0x00F8u, 0x0301u, 0x01FFu),
--     HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0300u, 0x01DCu),   HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0301u, 0x01D8u),
--     HB_CODEPOINT_ENCODE3 (0x00FCu, 0x0304u, 0x01D6u),   HB_CODEPOINT_ENCODE3 (0x00FCu, 0x030Cu, 0x01DAu),
--     HB_CODEPOINT_ENCODE3 (0x0102u, 0x0300u, 0x1EB0u),   HB_CODEPOINT_ENCODE3 (0x0102u, 0x0301u, 0x1EAEu),
--     HB_CODEPOINT_ENCODE3 (0x0102u, 0x0303u, 0x1EB4u),   HB_CODEPOINT_ENCODE3 (0x0102u, 0x0309u, 0x1EB2u),
--     HB_CODEPOINT_ENCODE3 (0x0103u, 0x0300u, 0x1EB1u),   HB_CODEPOINT_ENCODE3 (0x0103u, 0x0301u, 0x1EAFu),
--     HB_CODEPOINT_ENCODE3 (0x0103u, 0x0303u, 0x1EB5u),   HB_CODEPOINT_ENCODE3 (0x0103u, 0x0309u, 0x1EB3u),
--     HB_CODEPOINT_ENCODE3 (0x0112u, 0x0300u, 0x1E14u),   HB_CODEPOINT_ENCODE3 (0x0112u, 0x0301u, 0x1E16u),
--     HB_CODEPOINT_ENCODE3 (0x0113u, 0x0300u, 0x1E15u),   HB_CODEPOINT_ENCODE3 (0x0113u, 0x0301u, 0x1E17u),
--     HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0300u, 0x1E50u),   HB_CODEPOINT_ENCODE3 (0x014Cu, 0x0301u, 0x1E52u),
--     HB_CODEPOINT_ENCODE3 (0x014Du, 0x0300u, 0x1E51u),   HB_CODEPOINT_ENCODE3 (0x014Du, 0x0301u, 0x1E53u),
--     HB_CODEPOINT_ENCODE3 (0x015Au, 0x0307u, 0x1E64u),   HB_CODEPOINT_ENCODE3 (0x015Bu, 0x0307u, 0x1E65u),
--     HB_CODEPOINT_ENCODE3 (0x0160u, 0x0307u, 0x1E66u),   HB_CODEPOINT_ENCODE3 (0x0161u, 0x0307u, 0x1E67u),
--     HB_CODEPOINT_ENCODE3 (0x0168u, 0x0301u, 0x1E78u),   HB_CODEPOINT_ENCODE3 (0x0169u, 0x0301u, 0x1E79u),
--     HB_CODEPOINT_ENCODE3 (0x016Au, 0x0308u, 0x1E7Au),   HB_CODEPOINT_ENCODE3 (0x016Bu, 0x0308u, 0x1E7Bu),
--     HB_CODEPOINT_ENCODE3 (0x017Fu, 0x0307u, 0x1E9Bu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0300u, 0x1EDCu),
--     HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0301u, 0x1EDAu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0303u, 0x1EE0u),
--     HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0309u, 0x1EDEu),   HB_CODEPOINT_ENCODE3 (0x01A0u, 0x0323u, 0x1EE2u),
--     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0300u, 0x1EDDu),   HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0301u, 0x1EDBu),
--     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0303u, 0x1EE1u),   HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0309u, 0x1EDFu),
--     HB_CODEPOINT_ENCODE3 (0x01A1u, 0x0323u, 0x1EE3u),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0300u, 0x1EEAu),
--     HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0301u, 0x1EE8u),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0303u, 0x1EEEu),
--     HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0309u, 0x1EECu),   HB_CODEPOINT_ENCODE3 (0x01AFu, 0x0323u, 0x1EF0u),
--     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0300u, 0x1EEBu),   HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0301u, 0x1EE9u),
--     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0303u, 0x1EEFu),   HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0309u, 0x1EEDu),
--     HB_CODEPOINT_ENCODE3 (0x01B0u, 0x0323u, 0x1EF1u),   HB_CODEPOINT_ENCODE3 (0x01B7u, 0x030Cu, 0x01EEu),
--     HB_CODEPOINT_ENCODE3 (0x01EAu, 0x0304u, 0x01ECu),   HB_CODEPOINT_ENCODE3 (0x01EBu, 0x0304u, 0x01EDu),
--     HB_CODEPOINT_ENCODE3 (0x0226u, 0x0304u, 0x01E0u),   HB_CODEPOINT_ENCODE3 (0x0227u, 0x0304u, 0x01E1u),
--     HB_CODEPOINT_ENCODE3 (0x0228u, 0x0306u, 0x1E1Cu),   HB_CODEPOINT_ENCODE3 (0x0229u, 0x0306u, 0x1E1Du),
--     HB_CODEPOINT_ENCODE3 (0x022Eu, 0x0304u, 0x0230u),   HB_CODEPOINT_ENCODE3 (0x022Fu, 0x0304u, 0x0231u),
--     HB_CODEPOINT_ENCODE3 (0x0292u, 0x030Cu, 0x01EFu),   HB_CODEPOINT_ENCODE3 (0x0308u, 0x0301u, 0x0000u),
--     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0300u, 0x1FBAu),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0301u, 0x0386u),
--     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0304u, 0x1FB9u),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0306u, 0x1FB8u),
--     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0313u, 0x1F08u),   HB_CODEPOINT_ENCODE3 (0x0391u, 0x0314u, 0x1F09u),
--     HB_CODEPOINT_ENCODE3 (0x0391u, 0x0345u, 0x1FBCu),   HB_CODEPOINT_ENCODE3 (0x0395u, 0x0300u, 0x1FC8u),
--     HB_CODEPOINT_ENCODE3 (0x0395u, 0x0301u, 0x0388u),   HB_CODEPOINT_ENCODE3 (0x0395u, 0x0313u, 0x1F18u),
--     HB_CODEPOINT_ENCODE3 (0x0395u, 0x0314u, 0x1F19u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0300u, 0x1FCAu),
--     HB_CODEPOINT_ENCODE3 (0x0397u, 0x0301u, 0x0389u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0313u, 0x1F28u),
--     HB_CODEPOINT_ENCODE3 (0x0397u, 0x0314u, 0x1F29u),   HB_CODEPOINT_ENCODE3 (0x0397u, 0x0345u, 0x1FCCu),
--     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0300u, 0x1FDAu),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0301u, 0x038Au),
--     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0304u, 0x1FD9u),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0306u, 0x1FD8u),
--     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0308u, 0x03AAu),   HB_CODEPOINT_ENCODE3 (0x0399u, 0x0313u, 0x1F38u),
--     HB_CODEPOINT_ENCODE3 (0x0399u, 0x0314u, 0x1F39u),   HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0300u, 0x1FF8u),
--     HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0301u, 0x038Cu),   HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0313u, 0x1F48u),
--     HB_CODEPOINT_ENCODE3 (0x039Fu, 0x0314u, 0x1F49u),   HB_CODEPOINT_ENCODE3 (0x03A1u, 0x0314u, 0x1FECu),
--     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0300u, 0x1FEAu),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0301u, 0x038Eu),
--     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0304u, 0x1FE9u),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0306u, 0x1FE8u),
--     HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0308u, 0x03ABu),   HB_CODEPOINT_ENCODE3 (0x03A5u, 0x0314u, 0x1F59u),
--     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0300u, 0x1FFAu),   HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0301u, 0x038Fu),
--     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0313u, 0x1F68u),   HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0314u, 0x1F69u),
--     HB_CODEPOINT_ENCODE3 (0x03A9u, 0x0345u, 0x1FFCu),   HB_CODEPOINT_ENCODE3 (0x03ACu, 0x0345u, 0x1FB4u),
--     HB_CODEPOINT_ENCODE3 (0x03AEu, 0x0345u, 0x1FC4u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0300u, 0x1F70u),
--     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0301u, 0x03ACu),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0304u, 0x1FB1u),
--     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0306u, 0x1FB0u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0313u, 0x1F00u),
--     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0314u, 0x1F01u),   HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0342u, 0x1FB6u),
--     HB_CODEPOINT_ENCODE3 (0x03B1u, 0x0345u, 0x1FB3u),   HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0300u, 0x1F72u),
--     HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0301u, 0x03ADu),   HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0313u, 0x1F10u),
--     HB_CODEPOINT_ENCODE3 (0x03B5u, 0x0314u, 0x1F11u),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0300u, 0x1F74u),
--     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0301u, 0x03AEu),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0313u, 0x1F20u),
--     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0314u, 0x1F21u),   HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0342u, 0x1FC6u),
--     HB_CODEPOINT_ENCODE3 (0x03B7u, 0x0345u, 0x1FC3u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0300u, 0x1F76u),
--     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0301u, 0x03AFu),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0304u, 0x1FD1u),
--     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0306u, 0x1FD0u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0308u, 0x03CAu),
--     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0313u, 0x1F30u),   HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0314u, 0x1F31u),
--     HB_CODEPOINT_ENCODE3 (0x03B9u, 0x0342u, 0x1FD6u),   HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0300u, 0x1F78u),
--     HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0301u, 0x03CCu),   HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0313u, 0x1F40u),
--     HB_CODEPOINT_ENCODE3 (0x03BFu, 0x0314u, 0x1F41u),   HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0313u, 0x1FE4u),
--     HB_CODEPOINT_ENCODE3 (0x03C1u, 0x0314u, 0x1FE5u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0300u, 0x1F7Au),
--     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0301u, 0x03CDu),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0304u, 0x1FE1u),
--     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0306u, 0x1FE0u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0308u, 0x03CBu),
--     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0313u, 0x1F50u),   HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0314u, 0x1F51u),
--     HB_CODEPOINT_ENCODE3 (0x03C5u, 0x0342u, 0x1FE6u),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0300u, 0x1F7Cu),
--     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0301u, 0x03CEu),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0313u, 0x1F60u),
--     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0314u, 0x1F61u),   HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0342u, 0x1FF6u),
--     HB_CODEPOINT_ENCODE3 (0x03C9u, 0x0345u, 0x1FF3u),   HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0300u, 0x1FD2u),
--     HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0301u, 0x0390u),   HB_CODEPOINT_ENCODE3 (0x03CAu, 0x0342u, 0x1FD7u),
--     HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0300u, 0x1FE2u),   HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0301u, 0x03B0u),
--     HB_CODEPOINT_ENCODE3 (0x03CBu, 0x0342u, 0x1FE7u),   HB_CODEPOINT_ENCODE3 (0x03CEu, 0x0345u, 0x1FF4u),
--     HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0301u, 0x03D3u),   HB_CODEPOINT_ENCODE3 (0x03D2u, 0x0308u, 0x03D4u),
--     HB_CODEPOINT_ENCODE3 (0x0406u, 0x0308u, 0x0407u),   HB_CODEPOINT_ENCODE3 (0x0410u, 0x0306u, 0x04D0u),
--     HB_CODEPOINT_ENCODE3 (0x0410u, 0x0308u, 0x04D2u),   HB_CODEPOINT_ENCODE3 (0x0413u, 0x0301u, 0x0403u),
--     HB_CODEPOINT_ENCODE3 (0x0415u, 0x0300u, 0x0400u),   HB_CODEPOINT_ENCODE3 (0x0415u, 0x0306u, 0x04D6u),
--     HB_CODEPOINT_ENCODE3 (0x0415u, 0x0308u, 0x0401u),   HB_CODEPOINT_ENCODE3 (0x0416u, 0x0306u, 0x04C1u),
--     HB_CODEPOINT_ENCODE3 (0x0416u, 0x0308u, 0x04DCu),   HB_CODEPOINT_ENCODE3 (0x0417u, 0x0308u, 0x04DEu),
--     HB_CODEPOINT_ENCODE3 (0x0418u, 0x0300u, 0x040Du),   HB_CODEPOINT_ENCODE3 (0x0418u, 0x0304u, 0x04E2u),
--     HB_CODEPOINT_ENCODE3 (0x0418u, 0x0306u, 0x0419u),   HB_CODEPOINT_ENCODE3 (0x0418u, 0x0308u, 0x04E4u),
--     HB_CODEPOINT_ENCODE3 (0x041Au, 0x0301u, 0x040Cu),   HB_CODEPOINT_ENCODE3 (0x041Eu, 0x0308u, 0x04E6u),
--     HB_CODEPOINT_ENCODE3 (0x0423u, 0x0304u, 0x04EEu),   HB_CODEPOINT_ENCODE3 (0x0423u, 0x0306u, 0x040Eu),
--     HB_CODEPOINT_ENCODE3 (0x0423u, 0x0308u, 0x04F0u),   HB_CODEPOINT_ENCODE3 (0x0423u, 0x030Bu, 0x04F2u),
--     HB_CODEPOINT_ENCODE3 (0x0427u, 0x0308u, 0x04F4u),   HB_CODEPOINT_ENCODE3 (0x042Bu, 0x0308u, 0x04F8u),
--     HB_CODEPOINT_ENCODE3 (0x042Du, 0x0308u, 0x04ECu),   HB_CODEPOINT_ENCODE3 (0x0430u, 0x0306u, 0x04D1u),
--     HB_CODEPOINT_ENCODE3 (0x0430u, 0x0308u, 0x04D3u),   HB_CODEPOINT_ENCODE3 (0x0433u, 0x0301u, 0x0453u),
--     HB_CODEPOINT_ENCODE3 (0x0435u, 0x0300u, 0x0450u),   HB_CODEPOINT_ENCODE3 (0x0435u, 0x0306u, 0x04D7u),
--     HB_CODEPOINT_ENCODE3 (0x0435u, 0x0308u, 0x0451u),   HB_CODEPOINT_ENCODE3 (0x0436u, 0x0306u, 0x04C2u),
--     HB_CODEPOINT_ENCODE3 (0x0436u, 0x0308u, 0x04DDu),   HB_CODEPOINT_ENCODE3 (0x0437u, 0x0308u, 0x04DFu),
--     HB_CODEPOINT_ENCODE3 (0x0438u, 0x0300u, 0x045Du),   HB_CODEPOINT_ENCODE3 (0x0438u, 0x0304u, 0x04E3u),
--     HB_CODEPOINT_ENCODE3 (0x0438u, 0x0306u, 0x0439u),   HB_CODEPOINT_ENCODE3 (0x0438u, 0x0308u, 0x04E5u),
--     HB_CODEPOINT_ENCODE3 (0x043Au, 0x0301u, 0x045Cu),   HB_CODEPOINT_ENCODE3 (0x043Eu, 0x0308u, 0x04E7u),
--     HB_CODEPOINT_ENCODE3 (0x0443u, 0x0304u, 0x04EFu),   HB_CODEPOINT_ENCODE3 (0x0443u, 0x0306u, 0x045Eu),
--     HB_CODEPOINT_ENCODE3 (0x0443u, 0x0308u, 0x04F1u),   HB_CODEPOINT_ENCODE3 (0x0443u, 0x030Bu, 0x04F3u),
--     HB_CODEPOINT_ENCODE3 (0x0447u, 0x0308u, 0x04F5u),   HB_CODEPOINT_ENCODE3 (0x044Bu, 0x0308u, 0x04F9u),
--     HB_CODEPOINT_ENCODE3 (0x044Du, 0x0308u, 0x04EDu),   HB_CODEPOINT_ENCODE3 (0x0456u, 0x0308u, 0x0457u),
--     HB_CODEPOINT_ENCODE3 (0x0474u, 0x030Fu, 0x0476u),   HB_CODEPOINT_ENCODE3 (0x0475u, 0x030Fu, 0x0477u),
--     HB_CODEPOINT_ENCODE3 (0x04D8u, 0x0308u, 0x04DAu),   HB_CODEPOINT_ENCODE3 (0x04D9u, 0x0308u, 0x04DBu),
--     HB_CODEPOINT_ENCODE3 (0x04E8u, 0x0308u, 0x04EAu),   HB_CODEPOINT_ENCODE3 (0x04E9u, 0x0308u, 0x04EBu),
-      HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B7u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05B8u, 0x0000u),
-      HB_CODEPOINT_ENCODE3 (0x05D0u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BCu, 0x0000u),
-      HB_CODEPOINT_ENCODE3 (0x05D1u, 0x05BFu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D2u, 0x05BCu, 0x0000u),
-      HB_CODEPOINT_ENCODE3 (0x05D3u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D4u, 0x05BCu, 0x0000u),
-      HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05B9u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D5u, 0x05BCu, 0x0000u),
-      HB_CODEPOINT_ENCODE3 (0x05D6u, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D8u, 0x05BCu, 0x0000u),
-      HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05B4u, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05D9u, 0x05BCu, 0x0000u),
-      HB_CODEPOINT_ENCODE3 (0x05DAu, 0x05BCu, 0x0000u),   HB_CODEPOINT_ENCODE3 (0x05DBu, 0x05BCu, 0x0000u),
-@@ -723,17 +1058,17 @@ static const uint64_t
-    HB_CODEPOINT_ENCODE3 (0x1D1BAu, 0x1D165u, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Eu, 0x0000u),
-    HB_CODEPOINT_ENCODE3 (0x1D1BBu, 0x1D16Fu, 0x0000u), HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Eu, 0x0000u),
-    HB_CODEPOINT_ENCODE3 (0x1D1BCu, 0x1D16Fu, 0x0000u),
- };
- 
- #ifndef HB_OPTIMIZE_SIZE
- 
- static const uint8_t
--_hb_ucd_u8[31814] =
-+_hb_ucd_u8[32102] =
- {
-     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 26, 26, 26, 26,
-    26, 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 28,
-    29, 26, 30, 31, 32, 33, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
-    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 34, 35, 35, 35, 35,
-@@ -2334,21 +2669,27 @@ static const uint8_t
-     2,  2,  2,  2, 82, 82, 82, 82, 82, 82, 82, 82,122,122,122,122,
-   122,122,122,122,122,122,122,122,122,122,122,122,122,122,  2,  2,
-     2,  2,  2,  2,  2,122,122,122,122,  2,  2,  2,  2,  2,  2,  2,
-     2,  2,  2,  2,  2,122,122,122,122,122,122,122, 89, 89, 89, 89,
-    89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
-    89, 89, 89, 89, 89,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,
-   130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,130,130,130,  2,
--    2,  2,  2,  2,  2,  2,130,130,130,130,130,130,  0,  0,  0,  0,
--    0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
--    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  1,  1,  1,  1,
--    1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
--    3,  3,  3,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 94, 94, 94,
-+    2,  2,  2,  2,  2,  2,130,130,130,130,130,130,144,144,144,144,
-+  144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,
-+  144,144,144,144,  2,  2,  2,  2,  2,  2,  2,  2,144,144,144,144,
-+  144,144,144,144,144,144,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,147,147,147,147,
-+  147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,
-+  147,147,147,147,  2,  2,  2,  2,  2,  2,  2,  2,148,148,148,148,
-+  148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
-+  148,148,148,148,148,148,  2,  2,  2,  2,  2,  2,149,149,149,149,
-+  149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
-+  149,149,149,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 94, 94, 94,
-    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
-    94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2, 94, 94,
-    94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 94, 85, 85, 85, 85,
-    85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,  2,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,101,101,
-   101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
-   101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,101,101,
-@@ -2391,45 +2732,51 @@ static const uint8_t
-   114,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,114,114,114,114,
-   114,114,114,114,114,114,  2,  2,  2,  2,  2,  2, 32, 32, 32, 32,
-    32, 32, 32, 32, 32, 32, 32, 32, 32,  2,  2,  2,102,102,102,102,
-   102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
-   102,102,102,102,102,  2,  2,  2,  2,  2,  2,  2,102,102,102,102,
-   102,102,102,102,102,102,  2,  2,  2,  2,  2,  2,126,126,126,126,
-   126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
-   126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,126,126,
--  126,126,126,126,126,126,126,126,  2,  2,  2,  2,  4,  4,  4,  4,
--    4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,125,125,125,125,
-+  126,126,126,126,126,126,126,126,  2,  2,  2,  2,142,142,142,142,
-+  142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
-+  142,142,142,142,142,142,142,142,  2,  2,  2,  2,125,125,125,125,
-   125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,  2,
--    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,  5,  5,  5,  5,
--    5,  5,  5,  5,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
--    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,
--    5,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  6,  6,  6,  6,
--    6,  6,  6,  6,  2,  2,  2,  2,  2,  2,  2,  2,  7,  7,  7,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,125,150,150,150,150,
-+  150,150,150,150,  2,  2,150,150,150,150,150,150,150,150,150,150,
-+  150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
-+  150,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,141,141,141,141,
-+  141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
-+  141,141,141,141,  2,  2,  2,  2,  2,  2,  2,  2,140,140,140,140,
-+  140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,121,121,121,121,
-   121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
-   121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,133,133,133,133,
-   133,133,133,133,133,  2,133,133,133,133,133,133,133,133,133,133,
-   133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
-   133,133,133,  2,133,133,133,133,133,133,133,133,133,133,133,133,
-   133,133,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,133,133,133,133,
-   133,133,133,133,133,133,133,133,133,  2,  2,  2,134,134,134,134,
-   134,134,134,134,134,134,134,134,134,134,134,134,  2,  2,134,134,
-   134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
-   134,134,134,134,  2,134,134,134,134,134,134,134,134,134,134,134,
--  134,134,134,  2,  2,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
--    8,  8,  8,  2,  8,  8,  2,  8,  8,  8,  8,  8,  8,  8,  8,  8,
--    8,  8,  8,  2,  2,  2,  8,  2,  8,  8,  2,  8,  8,  8,  8,  8,
--    8,  8,  8,  8,  2,  2,  2,  2,  2,  2,  2,  2,  8,  8,  8,  8,
--    8,  8,  8,  8,  8,  8,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
--    9,  9,  2,  9,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  2,  9,
--    9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2,  2,  9,  9,  9,  9,
--    9,  9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2, 10, 10, 10, 10,
--   10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
--   10, 10, 10, 10, 10,  2,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
-+  134,134,134,  2,  2,  2,  2,  2,  2,  2,  2,  2,138,138,138,138,
-+  138,138,138,  2,138,138,  2,138,138,138,138,138,138,138,138,138,
-+  138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,
-+  138,138,138,  2,  2,  2,138,  2,138,138,  2,138,138,138,138,138,
-+  138,138,138,138,  2,  2,  2,  2,  2,  2,  2,  2,138,138,138,138,
-+  138,138,138,138,138,138,  2,  2,  2,  2,  2,  2,143,143,143,143,
-+  143,143,  2,143,143,  2,143,143,143,143,143,143,143,143,143,143,
-+  143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
-+  143,143,143,143,143,143,143,143,143,143,143,  2,143,143,  2,143,
-+  143,143,143,143,143,  2,  2,  2,  2,  2,  2,  2,143,143,143,143,
-+  143,143,143,143,143,143,  2,  2,  2,  2,  2,  2,145,145,145,145,
-+  145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,
-+  145,145,145,145,145,  2,  2,  2,  2,  2,  2,  2, 22, 22, 22, 22,
-    22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,  2,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63, 63, 63,
-    63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
-    63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63, 63, 63,
-    63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,  2, 63, 63, 63, 63,
-    63,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 63, 63, 63, 63,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 80, 80, 80, 80,
-    80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
-@@ -2443,30 +2790,32 @@ static const uint8_t
-   115,115,115,115,115,115,  2,  2,  2,  2,115,115,103,103,103,103,
-   103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,
-   103,103,103,103,103,103,103,103,103,103,  2,  2,103,103,103,103,
-   103,103,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,119,119,119,119,
-   119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
-   119,119,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,119,119,119,119,
-   119,119,119,119,119,119,  2,119,119,119,119,119,119,119,  2,119,
-   119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
--  119,119,119,119,  2,  2,  2,  2,  2,119,119,119, 11, 11, 11, 11,
--   11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
--   11, 11, 11, 11, 11, 11, 11,  2,  2,  2,  2,  2, 99, 99, 99, 99,
-+  119,119,119,119,  2,  2,  2,  2,  2,119,119,119,146,146,146,146,
-+  146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
-+  146,146,146,146,146,146,146,  2,  2,  2,  2,  2, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-    99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99, 99, 99, 99, 99,
--   99, 99, 99, 99,  2,  2,  2,  2,  2,  2,  2, 99,136, 12,  0,  0,
-+   99, 99, 99, 99,  2,  2,  2,  2,  2,  2,  2, 99,136,139,  0,  0,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,136,136,136,136,
-   136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
-   136,136,136,136,  2,  2,  2,  2,  2,  2,  2,  2,136,136,136,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 17, 15, 15, 15,
-    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  2, 15, 15, 15,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,
--   17, 17, 17, 17,  2,  2,  2,  2,  2,  2,  2,  2,105,105,105,105,
-+   17, 17, 17, 17,  2,  2,  2,  2,  2,  2,  2,  2,139,139,139,139,
-+  139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,
-+  139,139,139,139,139,139,139,139,  2,  2,  2,  2,105,105,105,105,
-   105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
-   105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,105,105,
-   105,105,105,105,105,105,105,105,105,  2,  2,  2,105,105,105,105,
-   105,105,105,105,105,  2,  2,  2,  2,  2,  2,  2,105,105,105,105,
-   105,105,105,105,105,105,  2,  2,105,105,105,105,  0,  0,  0,  0,
-     0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-     0,  0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-@@ -2486,20 +2835,23 @@ static const uint8_t
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,131,131,131,131,
-   131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
-   131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,  2,  2,
-     2,  2,  2,  2,  2,  2,  2,131,131,131,131,131,  2,131,131,131,
-   131,131,131,131,131,131,131,131,131,131,131,131, 56, 56, 56, 56,
-    56, 56, 56,  2, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
-    56, 56, 56, 56, 56,  2,  2, 56, 56, 56, 56, 56, 56, 56,  2, 56,
--   56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2, 13, 13, 13, 13,
--   13, 13, 13, 13, 13, 13, 13, 13, 13,  2,  2,  2, 13, 13, 13, 13,
--   13, 13, 13, 13, 13, 13,  2,  2,  2,  2, 13, 13, 14, 14, 14, 14,
--   14, 14, 14, 14, 14, 14,  2,  2,  2,  2,  2, 14,113,113,113,113,
-+   56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2,151,151,151,151,
-+  151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,
-+  151,151,151,151,151,151,151,151,151,  2,  2,  2,151,151,151,151,
-+  151,151,151,151,151,151,151,151,151,151,  2,  2,151,151,151,151,
-+  151,151,151,151,151,151,  2,  2,  2,  2,151,151,152,152,152,152,
-+  152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
-+  152,152,152,152,152,152,  2,  2,  2,  2,  2,152,113,113,113,113,
-   113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-   113,  2,  2,113,113,113,113,113,113,113,113,113,113,113,113,113,
-   113,113,113,  2,  2,  2,  2,  2,  2,  2,  2,  2,132,132,132,132,
-   132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
-   132,132,132,132,132,132,132,132,  2,  2,  2,  2,132,132,132,132,
-   132,132,132,132,132,132,  2,  2,  2,  2,132,132,  0,  0,  0,  0,
-     0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  3,  3,  3,  3,
-@@ -2512,16 +2864,17 @@ static const uint8_t
-     3,  3,  3,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,  3,  3,
-     3,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-     3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,  3,  3,
-     2,  3,  3,  3,  3,  3,  2,  3,  3,  3,  3,  3,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,
-     2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 15,  0,  0,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  2,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-+    0,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,
-     0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,
-     2,  0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,  0,  0,
-     2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  2,  2,  0,  0,  0,  2,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13, 13, 13,
-    13, 13, 13,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13, 13, 13,
-    13,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 13, 13,  2,  2,
-@@ -2999,112 +3352,112 @@ static const uint16_t
-    376, 376, 377, 378, 378, 378, 379,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-    380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380, 380,
-    380, 380, 380, 381, 380, 382, 383,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-    384, 385, 385, 386, 387, 388, 389, 389, 390, 391, 392,  45,  45,  45, 393, 394,
-    395, 396, 397, 398,  45,  45,  45,  45, 399, 399, 400, 401, 400, 402, 400, 400,
-    403, 404, 405, 406, 407, 407, 408, 408, 409, 409,  45,  45, 410, 410, 411, 412,
-    413, 413, 413, 414, 415, 416, 417, 418, 419, 420, 421,  45,  45,  45,  45,  45,
-    422, 422, 422, 422, 423,  45,  45,  45, 424, 424, 424, 425, 424, 424, 424, 426,
--     0,   0, 427, 285,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--    45,  45,  45,  45,  45,  45,  27, 428,  45,  45,  45,  45,  45,  45,  45,  45,
--     8,   8, 429,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  27, 430,
--   431, 431, 431, 431, 432, 433, 431, 434, 435, 435, 435, 435, 436, 437, 438, 439,
--   440, 440, 440, 441, 442, 443, 443, 444, 445, 445, 445, 445, 446, 445, 447, 448,
--   449, 450, 449, 451,  45,  45,  45,  45, 452, 453, 454, 455, 455, 455, 456, 457,
--   458, 459, 460, 461, 462, 463, 464, 465,  45,  45,  45,  45,  45,  45,  45,  45,
--   466, 466, 466, 466, 466, 467,  45,  45, 468, 468, 468, 468, 469, 470,  45,  45,
--    45,  45,  45,  45,  45,  45,  45,  45, 471, 471, 471, 472, 471, 473,  45,  45,
--   474, 474, 474, 474, 475, 476, 477,  45, 478, 478, 478, 479, 480,  45,  45,  45,
--   481, 482, 483, 481,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--    17,  17,  17, 484,  45,  45,  45,  45,  45,  45, 485, 485, 485, 485, 485, 486,
--    45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 487, 488, 488, 487, 489,  45,
--    14,  14,  14,  14, 490,  49,  49,  49,  49,  49, 491,  45, 492, 492, 492, 493,
-+   427, 427, 428, 429,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  27, 430,  45,  45,  45,  45,  45,  45,  45,  45,
-+   431, 431, 432, 433, 433, 434,  45,  45,  45,  45,  45,  45,  45,  45, 435, 436,
-+   437, 437, 437, 437, 438, 439, 437, 440, 441, 441, 441, 441, 442, 443, 444, 445,
-+   446, 446, 446, 447, 448, 449, 449, 450, 451, 451, 451, 451, 452, 451, 453, 454,
-+   455, 456, 455, 457,  45,  45,  45,  45, 458, 459, 460, 461, 461, 461, 462, 463,
-+   464, 465, 466, 467, 468, 469, 470, 471,  45,  45,  45,  45,  45,  45,  45,  45,
-+   472, 472, 472, 472, 472, 473,  45,  45, 474, 474, 474, 474, 475, 476,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45, 477, 477, 477, 478, 477, 479,  45,  45,
-+   480, 480, 480, 480, 481, 482, 483,  45, 484, 484, 484, 485, 486,  45,  45,  45,
-+   487, 488, 489, 487,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   490, 490, 490, 491,  45,  45,  45,  45,  45,  45, 492, 492, 492, 492, 492, 493,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 494, 495, 495, 494, 496,  45,
-+   497, 497, 497, 497, 498, 499, 499, 499, 499, 499, 500,  45, 501, 501, 501, 502,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   494, 495, 495, 496, 497, 495, 498, 499, 499, 500, 501, 502,  45,  45,  45,  45,
--   503, 139, 139, 504, 505, 506, 507,  11, 349, 508, 509,  45,  45,  45,  45,  45,
--    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 510, 511,
--    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 512, 512, 512, 513,
--   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
--   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
--   514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514, 514,
--   514, 514, 514, 514, 514, 514, 514, 514, 514, 515,  45,  45,  45,  45,  45,  45,
--   514, 514, 514, 514, 514, 514, 516, 517, 514, 514, 514, 514, 514, 514, 514, 514,
--   514, 514, 514, 514, 518,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519,
--   519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519,
--   519, 519, 520, 521,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   503, 504, 504, 505, 506, 504, 507, 508, 508, 509, 510, 511,  45,  45,  45,  45,
-+   512, 513, 513, 514, 515, 516, 517, 518, 519, 520, 521,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 522, 523,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 524, 524, 524, 525,
-+   526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526,
-+   526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526,
-+   526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, 526,
-+   526, 526, 526, 526, 526, 526, 526, 526, 526, 527,  45,  45,  45,  45,  45,  45,
-+   526, 526, 526, 526, 526, 526, 528, 529, 526, 526, 526, 526, 526, 526, 526, 526,
-+   526, 526, 526, 526, 530,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531,
-+   531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531, 531,
-+   531, 531, 532, 533,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522,
--   522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522,
--   522, 522, 522, 522, 523,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
-+   534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
-+   534, 534, 534, 534, 535,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-    277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
-    277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
--   277, 277, 277, 524, 525, 526, 527,  45,  45,  45,  45,  45,  45, 528, 529, 530,
--   531, 531, 531, 531, 532, 533, 534, 535, 531,  45,  45,  45,  45,  45,  45,  45,
--    45,  45,  45,  45, 536, 536, 536, 536, 536, 537,  45,  45,  45,  45,  45,  45,
--   538, 538, 538, 538, 539, 538, 538, 538, 540, 538,  45,  45,  45,  45, 541,  45,
--   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
--   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
--   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542,
--   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 543,
--   542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 542, 544,
-+   277, 277, 277, 536, 537, 538, 539,  45,  45,  45,  45,  45,  45, 540, 541, 542,
-+   543, 543, 543, 543, 544, 545, 546, 547, 543,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45, 548, 548, 548, 548, 548, 549,  45,  45,  45,  45,  45,  45,
-+   550, 550, 550, 550, 551, 550, 550, 550, 552, 550,  45,  45,  45,  45, 553,  45,
-+   554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554,
-+   554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554,
-+   554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554,
-+   554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 555,
-+   554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 556,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   545, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
--   257, 546,  45,  45,  45, 547, 548, 142, 142, 142, 142, 142, 142, 142, 142, 142,
--   142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 317,
-+   557, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
-+   257, 558,  45,  45,  45, 559, 560, 561, 561, 561, 561, 561, 561, 561, 561, 561,
-+   561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 562,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   549, 549, 549, 549, 549, 549, 550, 551, 552, 553, 267,  45,  45,  45,  45,  45,
-+   563, 563, 563, 563, 563, 563, 564, 565, 566, 567, 267,  45,  45,  45,  45,  45,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 554,
--     0,   0, 555,   0,   0,   0, 556, 557, 558,   0, 559,   0,   0,   0, 560,  45,
--    11,  11,  11,  11, 561,  45,  45,  45,  45,  45,  45,  45,  45,  45,   0, 267,
--     0,   0,   0,   0,   0, 234,   0, 560,  45,  45,  45,  45,  45,  45,  45,  45,
--     0,   0,   0,   0,   0, 225,   0,   0,   0, 562, 563, 564, 565,   0,   0,   0,
--   566, 567,   0, 568, 569, 570,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 568,
-+     0,   0, 569,   0,   0,   0, 570, 571, 572,   0, 573,   0,   0,   0, 574,  45,
-+    11,  11,  11,  11, 575,  45,  45,  45,  45,  45,  45,  45,  45,  45,   0, 267,
-+     0,   0,   0,   0,   0, 234,   0, 574,  45,  45,  45,  45,  45,  45,  45,  45,
-+     0,   0,   0,   0,   0, 225,   0,   0,   0, 576, 577, 578, 579,   0,   0,   0,
-+   580, 581,   0, 582, 583, 584,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 238,   0,   0,   0,   0,   0,
--     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 571,   0,   0,   0,
--   572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572,
--   572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572, 572,
--   572, 572, 572, 572, 572, 572, 572, 572, 573, 574, 575,  45,  45,  45,  45,  45,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 585,   0,   0,   0,
-+   586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586,
-+   586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, 586,
-+   586, 586, 586, 586, 586, 586, 586, 586, 587, 588, 589,  45,  45,  45,  45,  45,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   576, 577, 578,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   248, 248, 579, 318, 580,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  21,  21,  21, 581,
-+   590, 591, 592,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   593, 593, 594, 595, 596,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45, 597, 597, 597, 598,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 584,  45,  45,
--   585, 585, 585, 585, 586, 587,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--    45,  45,  45,  45,  45,  45,  45, 334,   0,   0,   0, 588,  45,  45,  45,  45,
--   334,   0,   0, 589,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   590,  27, 591, 592, 593, 594, 595, 596, 597, 598, 599, 598,  45,  45,  45, 324,
-+   599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, 600, 601,  45,  45,
-+   602, 602, 602, 602, 603, 604,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+    45,  45,  45,  45,  45,  45,  45, 334,   0,   0,   0, 605,  45,  45,  45,  45,
-+   334,   0,   0, 606,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+   607,  27, 608, 609, 610, 611, 612, 613, 614, 615, 616, 615,  45,  45,  45, 324,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--     0,   0, 252,   0,   0,   0,   0,   0,   0, 267, 227, 334, 334, 334,   0, 554,
--   600,   0,   0,   0,   0,   0, 600,   0,   0,   0, 600,  45,  45,  45, 601,   0,
--   602,   0,   0, 252, 560, 603, 554,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-+     0,   0, 252,   0,   0,   0,   0,   0,   0, 267, 227, 334, 334, 334,   0, 568,
-+   617,   0,   0,   0,   0,   0, 617,   0,   0,   0, 617,  45,  45,  45, 618,   0,
-+   619,   0,   0, 252, 574, 620, 568,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
--     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 554, 600, 235,
--     0,   0,   0,   0,   0,   0,   0, 267,   0,   0,   0,   0,   0, 560, 252,  45,
--   252,   0,   0,   0, 427, 285,   0,   0, 427,   0, 589,  45,  45,  45,  45,  45,
--   604,   0,   0,   0,   0,   0,   0, 605,   0,   0, 606,   0, 607,   0,   0,   0,
--     0,   0,   0,   0,   0, 267, 589, 608, 609, 554,  45,  45,  45,  45,  45,  45,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 568, 617, 235,
-+     0,   0,   0,   0,   0,   0,   0, 267,   0,   0,   0,   0,   0, 574, 252,  45,
-+   252,   0,   0,   0, 621, 285,   0,   0, 621,   0, 606,  45,  45,  45,  45,  45,
-+   622,   0,   0,   0,   0,   0,   0, 623,   0,   0, 624,   0, 625,   0,   0,   0,
-+     0,   0,   0,   0,   0, 267, 606, 626, 627, 568,  45,  45,  45,  45,  45,  45,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 610,  45,  45,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 628,  45,  45,
-    248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-    248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
--   248, 248, 248, 611, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-+   248, 248, 248, 629, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-    248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-    248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
--   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 612, 248, 248, 248, 248, 248,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 630, 248, 248, 248, 248, 248,
-    248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
-    248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
--   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 613,  45,
-+   248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 631,  45,
-    248, 318,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
-     45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,  45,
--   614,  45,   0,   0,   0,   0,   0,   0,  45,  45,  45,  45,  45,  45,  45,  45,
-+   632,  45,   0,   0,   0,   0,   0,   0,  45,  45,  45,  45,  45,  45,  45,  45,
-      8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   8,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
-      0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
-   1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
-@@ -3463,24 +3816,24 @@ static inline int_fast16_t
- static inline uint_fast8_t
- _hb_ucd_sc (unsigned u)
- {
-   return u<918000u?_hb_ucd_u8[18924+(((_hb_ucd_u16[3008+(((_hb_ucd_u8[17130+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:2;
- }
- static inline uint_fast16_t
- _hb_ucd_dm (unsigned u)
- {
--  return u<195102u?_hb_ucd_u16[6048+(((_hb_ucd_u8[28764+(u>>6)])<<6)+((u)&63u))]:0;
-+  return u<195102u?_hb_ucd_u16[6048+(((_hb_ucd_u8[29052+(u>>6)])<<6)+((u)&63u))]:0;
- }
- 
- 
--#else
-+#elif !defined(HB_NO_UCD_UNASSIGNED)
- 
- static const uint8_t
--_hb_ucd_u8[16998] =
-+_hb_ucd_u8[17198] =
- {
-     0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,  7,  7,
-     7,  7,  7,  9, 10, 11,  7,  7,  7,  7, 12, 13, 14, 14, 14, 15,
-    16, 17, 18, 19, 20, 21, 22, 21, 23, 21, 21, 21, 21, 24,  7,  7,
-    25, 26, 21, 21, 21, 21, 27, 28, 21, 21, 29, 30, 31, 32, 33, 34,
-     7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-     7,  7,  7,  7, 35,  7, 36, 37,  7, 38,  7,  7,  7, 39, 21, 40,
-    21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-@@ -4133,31 +4486,31 @@ static const uint8_t
-    97,144,145,146,147, 97,148,149, 97,150,151,152, 97, 97,153,154,
-   155,156, 97,157, 97,158,159,159,159,159,159,159,159,160,161,159,
-   162, 97, 97, 97, 97, 97,163,163,163,163,163,163,163,163,164, 97,
-    97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,165,165,
-   165,165,166, 97, 97, 97,167,167,167,167,168,169,170,171, 97, 97,
-    97, 97,172,173,174,175,176,176,176,176,176,176,176,176,176,176,
-   176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-   176,176,176,176,176,177,176,176,176,176,176,178, 97, 97, 97, 97,
--   97, 97, 97, 97, 97, 97,179,180,181, 32, 32,182, 97, 97, 97, 97,
--   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,183,184,
--   97, 97, 97, 97, 97, 97, 59,185,186,187,188,189,190, 97,191,192,
--  193, 59, 59,194, 59,195,196,196,196,196,196,197, 97, 97, 97, 97,
--   97, 97, 97, 97, 97, 97,198, 97,199, 97, 97,200, 97, 97, 97, 97,
--   97, 97, 97, 97, 97, 97,201,202,203, 97, 97, 97, 97, 97,204,205,
--  206, 97,207,208, 97, 97,209,210,211,212,213, 97, 59, 59, 59, 59,
--   59, 59, 59,214,215,216,217,218,219,220,221,222, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97,179,180,181,182,182,183, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,184,185,
-+   97, 97, 97, 97, 97, 97, 59,186,187,188,189,190,191, 97,192,193,
-+  194, 59, 59,195, 59,196,197,197,197,197,197,198, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97,199, 97,200, 97, 97,201, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97,202,203,204, 97, 97, 97, 97, 97,205,206,
-+  207, 97,208,209, 97, 97,210,211,212,213,214, 97, 59, 59, 59, 59,
-+   59, 59, 59,215,216,217,218,219,220,221,222,223, 97, 97, 97, 97,
-    97, 97, 97, 97, 97, 97, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
--   70, 70, 70,223, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
--   70, 70, 70, 70,224, 70,225, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70,224, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-+   70, 70, 70, 70,225, 70,226, 70, 70, 70, 70, 70, 70, 70, 70, 70,
-    70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
--   70, 70, 70,226, 70, 70, 70, 70, 70, 70, 70, 70, 70,227, 97, 97,
--   97, 97, 97, 97, 97, 97, 70, 70, 70, 70,228, 97, 97, 97, 97, 97,
--   97, 97, 97, 97, 97, 97,229, 97,230,231,  0,  1,  2,  2,  0,  1,
-+   70, 70, 70,227, 70, 70, 70, 70, 70, 70, 70, 70, 70,228, 97, 97,
-+   97, 97, 97, 97, 97, 97, 70, 70, 70, 70,229, 97, 97, 97, 97, 97,
-+   97, 97, 97, 97, 97, 97,230, 97,231,232,  0,  1,  2,  2,  0,  1,
-     2,  2,  2,  3,  4,  5,  0,  0,  0,  0,  0,  0,  0,  0,  0, 19,
-    19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
-    19,  0,  0,  0,  0,  0,  0,  0, 19,  0,  0,  0,  0,  0, 19, 19,
-    19, 19, 19, 19, 19,  0, 19,  0,  0,  0,  0,  0,  0,  0, 19, 19,
-    19, 19, 19,  0,  0,  0,  0,  0, 26, 26,  0,  0,  0,  0,  1,  1,
-     1,  1,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,  2,  2,
-     9,  9,  9,  9,  0,  9,  2,  2,  2,  2,  9,  0,  9,  0,  9,  9,
-     9,  2,  9,  2,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-@@ -4377,177 +4730,189 @@ static const uint8_t
-   112,112,112,112,112,  2,  2,  2,  2,112,112,112,112,112, 78, 78,
-    78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,  2,  2,  2, 78,
-    78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
-    83, 83, 83, 83,  2,  2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
-    82,  2,  2,  2,  2,  2,122,122,122,122,122,122,122,122,122,122,
-     2,  2,  2,  2,  2,  2,  2,122,122,122,122,  2,  2,  2,  2,122,
-   122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89,  2,
-     2,  2,  2,  2,  2,  2,130,130,130,130,130,130,130,130,130,130,
--  130,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,130,130,  3,  3,
--    3,  3,  3,  3,  3,  2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
--   94, 94, 94, 94,  2,  2,  2,  2, 94, 94, 94, 94, 94, 94,  2,  2,
--    2,  2,  2,  2,  2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
--    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 85,  2,  2,101,101,
--  101,101,101,101,101,101,101,  2,  2,  2,  2,  2,  2,  2,101,101,
--    2,  2,  2,  2,  2,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
--   96, 96, 96,  2, 96, 96, 96, 96, 96, 96, 96, 96, 96,  2,111,111,
--  111,111,111,111,111,111,111,111,111,111,111,111,111,  2,100,100,
--  100,100,100,100,100,100,100,100,100,100,100,100,  2,  2,  2, 36,
--   36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  2,  2,  2,108,108,
--  108,108,108,108,108,108,108,108,  2,108,108,108,108,108,108,108,
--  108,108,108,108,108,  2,129,129,129,129,129,129,129,  2,129,  2,
--  129,129,129,129,  2,129,129,129,129,129,129,129,129,129,129,129,
--  129,129,129,129,  2,129,129,129,  2,  2,  2,  2,  2,  2,109,109,
--  109,109,109,109,109,109,109,109,109,  2,  2,  2,  2,  2,109,109,
--    2,  2,  2,  2,  2,  2,107,107,107,107,  2,107,107,107,107,107,
--  107,107,107,  2,  2,107,107,  2,  2,107,107,107,107,107,107,107,
--  107,107,107,107,107,107,107,  2,107,107,107,107,107,107,107,  2,
--  107,107,  2,107,107,107,107,107,  2,  1,107,107,107,107,107,  2,
--    2,107,107,107,  2,  2,107,  2,  2,  2,  2,  2,  2,107,  2,  2,
--    2,  2,  2,107,107,107,107,107,107,107,  2,  2,107,107,107,107,
--  107,107,107,  2,  2,  2,137,137,137,137,137,137,137,137,137,137,
--    2,137,  2,137,137,137,124,124,124,124,124,124,124,124,124,124,
--    2,  2,  2,  2,  2,  2,123,123,123,123,123,123,123,123,123,123,
--  123,123,123,123,  2,  2,114,114,114,114,114,114,114,114,114,114,
--  114,114,114,  2,  2,  2,114,114,  2,  2,  2,  2,  2,  2, 32, 32,
--   32, 32, 32,  2,  2,  2,102,102,102,102,102,102,102,102,102,  2,
--    2,  2,  2,  2,  2,  2,102,102,  2,  2,  2,  2,  2,  2,126,126,
--  126,126,126,126,126,126,126,126,126,  2,  2,126,126,126,126,126,
--  126,126,  2,  2,  2,  2,  4,  4,  4,  4,  2,  2,  2,  2,125,125,
-+  130,  2,  2,  2,  2,  2,  2,  2,130,130,130,130,130,130,144,144,
-+  144,144,144,144,144,144,144,144,  2,  2,  2,  2,  2,  2,  3,  3,
-+    3,  3,  3,  3,  3,  2,147,147,147,147,147,147,147,147,148,148,
-+  148,148,148,148,148,148,148,148,  2,  2,  2,  2,  2,  2,149,149,
-+  149,149,149,149,149,149,149,149,149,149,149,149,149,  2, 94, 94,
-+   94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,  2,  2,  2,  2,
-+   94, 94, 94, 94, 94, 94,  2,  2,  2,  2,  2,  2,  2, 94, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85,  2,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2,  2, 85,  2,  2,101,101,101,101,101,101,101,101,101,  2,
-+    2,  2,  2,  2,  2,  2,101,101,  2,  2,  2,  2,  2,  2, 96, 96,
-+   96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,  2, 96, 96, 96, 96,
-+   96, 96, 96, 96, 96,  2,111,111,111,111,111,111,111,111,111,111,
-+  111,111,111,111,111,  2,100,100,100,100,100,100,100,100,100,100,
-+  100,100,100,100,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36,  2,  2,  2,108,108,108,108,108,108,108,108,108,108,
-+    2,108,108,108,108,108,108,108,108,108,108,108,108,  2,129,129,
-+  129,129,129,129,129,  2,129,  2,129,129,129,129,  2,129,129,129,
-+  129,129,129,129,129,129,129,129,129,129,129,129,  2,129,129,129,
-+    2,  2,  2,  2,  2,  2,109,109,109,109,109,109,109,109,109,109,
-+  109,  2,  2,  2,  2,  2,109,109,  2,  2,  2,  2,  2,  2,107,107,
-+  107,107,  2,107,107,107,107,107,107,107,107,  2,  2,107,107,  2,
-+    2,107,107,107,107,107,107,107,107,107,107,107,107,107,107,  2,
-+  107,107,107,107,107,107,107,  2,107,107,  2,107,107,107,107,107,
-+    2,  1,107,107,107,107,107,  2,  2,107,107,107,  2,  2,107,  2,
-+    2,  2,  2,  2,  2,107,  2,  2,  2,  2,  2,107,107,107,107,107,
-+  107,107,  2,  2,107,107,107,107,107,107,107,  2,  2,  2,137,137,
-+  137,137,137,137,137,137,137,137,  2,137,  2,137,137,137,124,124,
-+  124,124,124,124,124,124,124,124,  2,  2,  2,  2,  2,  2,123,123,
-+  123,123,123,123,123,123,123,123,123,123,123,123,  2,  2,114,114,
-+  114,114,114,114,114,114,114,114,114,114,114,  2,  2,  2,114,114,
-+    2,  2,  2,  2,  2,  2, 32, 32, 32, 32, 32,  2,  2,  2,102,102,
-+  102,102,102,102,102,102,102,  2,  2,  2,  2,  2,  2,  2,102,102,
-+    2,  2,  2,  2,  2,  2,126,126,126,126,126,126,126,126,126,126,
-+  126,  2,  2,126,126,126,126,126,126,126,  2,  2,  2,  2,142,142,
-+  142,142,142,142,142,142,142,142,142,142,  2,  2,  2,  2,125,125,
-   125,125,125,125,125,125,125,125,125,  2,  2,  2,  2,  2,  2,  2,
--    2,  2,  2,  2,  2,125,  2,  2,  5,  5,  5,  5,  5,  5,  5,  5,
--    5,  5,  5,  2,  2,  2,  7,  7,  7,  2,  2,  2,  2,  2,121,121,
--  121,121,121,121,121,121,121,  2,  2,  2,  2,  2,  2,  2,133,133,
--  133,133,133,133,133,133,133,  2,133,133,133,133,133,133,133,133,
--  133,133,133,133,133,  2,133,133,133,133,133,133,  2,  2,133,133,
--  133,133,133,  2,  2,  2,134,134,134,134,134,134,134,134,  2,  2,
--  134,134,134,134,134,134,  2,134,134,134,134,134,134,134,134,134,
--  134,134,134,134,134,  2,  8,  8,  8,  8,  8,  8,  8,  2,  8,  8,
--    2,  8,  8,  8,  8,  8,  2,  2,  8,  2,  8,  8,  2,  8,  8,  8,
--    2,  2,  2,  2,  2,  2,  9,  9,  9,  9,  9,  9,  2,  9,  9,  2,
--    9,  9,  9,  9,  9,  9,  9,  9,  2,  2,  2,  2,  2,  2, 22, 22,
-+    2,  2,  2,  2,  2,125,150,150,150,150,150,150,150,150,  2,  2,
-+  150,150,150,150,150,150,150,150,150,150,150,  2,  2,  2,141,141,
-+  141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,
-+  140,  2,  2,  2,  2,  2,121,121,121,121,121,121,121,121,121,  2,
-+    2,  2,  2,  2,  2,  2,133,133,133,133,133,133,133,133,133,  2,
-+  133,133,133,133,133,133,133,133,133,133,133,133,133,  2,133,133,
-+  133,133,133,133,  2,  2,133,133,133,133,133,  2,  2,  2,134,134,
-+  134,134,134,134,134,134,  2,  2,134,134,134,134,134,134,  2,134,
-+  134,134,134,134,134,134,134,134,134,134,134,134,134,  2,138,138,
-+  138,138,138,138,138,  2,138,138,  2,138,138,138,138,138,138,138,
-+  138,138,138,138,138,138,  2,  2,138,  2,138,138,  2,138,138,138,
-+    2,  2,  2,  2,  2,  2,143,143,143,143,143,143,  2,143,143,  2,
-+  143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
-+  143,143,143,143,143,  2,143,143,  2,143,143,143,143,143,143,  2,
-+    2,  2,  2,  2,  2,  2,143,143,  2,  2,  2,  2,  2,  2,145,145,
-+  145,145,145,145,145,145,145,  2,  2,  2,  2,  2,  2,  2, 22, 22,
-     2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 22, 63, 63,
-    63, 63, 63, 63, 63, 63, 63, 63,  2,  2,  2,  2,  2,  2, 63, 63,
-    63, 63, 63, 63, 63,  2, 63, 63, 63, 63, 63,  2,  2,  2, 63, 63,
-    63, 63,  2,  2,  2,  2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
-    80, 80, 80, 80, 80,  2, 80,  2,  2,  2,  2,  2,  2,  2,127,127,
-   127,127,127,127,127,127,127,127,127,127,127,127,127,  2, 79,  2,
-     2,  2,  2,  2,  2,  2,115,115,115,115,115,115,115,115,115,115,
-   115,115,115,115,115,  2,115,115,  2,  2,  2,  2,115,115,103,103,
-   103,103,103,103,103,103,103,103,103,103,103,103,  2,  2,119,119,
-   119,119,119,119,119,119,119,119,119,119,119,119,  2,  2,119,119,
--    2,119,119,119,119,119,  2,  2,  2,  2,  2,119,119,119, 11, 11,
--   11,  2,  2,  2,  2,  2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
--   99,  2,  2,  2,  2, 99,  2,  2,  2,  2,  2,  2,  2, 99,136, 12,
--    0,  0,  2,  2,  2,  2,136,136,136,136,136,136,136,136,136,136,
--  136,  2,  2,  2,  2,  2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15,
--   15,  2,  2,  2,  2,  2,  2,  2,  2,  2, 17, 17, 17, 17,105,105,
--  105,105,105,105,105,105,105,105,105,  2,  2,  2,  2,  2,105,105,
--  105,105,105,  2,  2,  2,105,  2,  2,  2,  2,  2,  2,  2,105,105,
--    2,  2,105,105,105,105,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,
--    1,  0,  0,  1,  1,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,
--    1,  1,  1,  1,  0,  0,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,
--    0,  2,  2,  0,  0,  2,  2,  0,  0,  0,  0,  2,  0,  0,  0,  0,
--    2,  0,  2,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  2,  0,  0,  0,  0,  0,
--    2,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  2,  0,  2,  2,  2,
--    0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  0,  0,131,131,
--  131,131,131,131,131,131,131,131,131,131,  2,  2,  2,  2,  2,  2,
--    2,131,131,131,131,131,  2,131,131,131,131,131,131,131, 56,  2,
--    2, 56, 56, 56, 56, 56, 56, 56,  2, 56, 56,  2, 56, 56, 56, 56,
--   56,  2,  2,  2,  2,  2, 13, 13, 13, 13, 13,  2,  2,  2, 13, 13,
--    2,  2,  2,  2, 13, 13, 14, 14,  2,  2,  2,  2,  2, 14,113,113,
-+    2,119,119,119,119,119,  2,  2,  2,  2,  2,119,119,119,146,146,
-+  146,146,146,146,146,146,146,146,146,  2,  2,  2,  2,  2, 99, 99,
-+   99, 99, 99, 99, 99, 99, 99, 99, 99,  2,  2,  2,  2, 99,  2,  2,
-+    2,  2,  2,  2,  2, 99,136,139,  0,  0,  2,  2,  2,  2,136,136,
-+  136,136,136,136,136,136,136,136,136,  2,  2,  2,  2,  2, 17, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15,  2,  2,  2,  2,  2,  2,  2,
-+    2,  2, 17, 17, 17, 17,139,139,139,139,139,139,139,139,139,139,
-+  139,139,  2,  2,  2,  2,105,105,105,105,105,105,105,105,105,105,
-+  105,  2,  2,  2,  2,  2,105,105,105,105,105,  2,  2,  2,105,  2,
-+    2,  2,  2,  2,  2,  2,105,105,  2,  2,105,105,105,105,  0,  0,
-+    0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  1,  1,  1,
-+    1,  1,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,  2,
-+    2,  2,  2,  2,  2,  2,  2,  2,  0,  2,  2,  0,  0,  2,  2,  0,
-+    0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  2,  0,  0,  0,  0,  0,
-+    0,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  2,  0,  0,  0,
-+    0,  2,  2,  0,  0,  0,  0,  0,  2,  0,  0,  0,  0,  2,  0,  0,
-+    0,  0,  0,  2,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,  2,
-+    0,  0,  0,  0,  0,  0,131,131,131,131,131,131,131,131,131,131,
-+  131,131,  2,  2,  2,  2,  2,  2,  2,131,131,131,131,131,  2,131,
-+  131,131,131,131,131,131, 56,  2,  2, 56, 56, 56, 56, 56, 56, 56,
-+    2, 56, 56,  2, 56, 56, 56, 56, 56,  2,  2,  2,  2,  2,151,151,
-+  151,151,151,151,151,151,151,151,151,151,151,  2,  2,  2,151,151,
-+  151,151,151,151,  2,  2,151,151,  2,  2,  2,  2,151,151,152,152,
-+  152,152,152,152,152,152,152,152,  2,  2,  2,  2,  2,152,113,113,
-   113,113,113,113,113,113,113,113,113,113,113,  2,  2,113,113,113,
-   113,113,113,113,113,  2,132,132,132,132,132,132,132,132,132,132,
-   132,132,  2,  2,  2,  2,132,132,  2,  2,  2,  2,132,132,  0,  0,
-     0,  0,  0,  2,  2,  2,  3,  3,  3,  3,  2,  3,  3,  3,  2,  3,
-     3,  2,  3,  2,  2,  3,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-     3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  2,  2,  2,  2,  2,  2,
-     3,  2,  2,  2,  2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  2,  3,
-     2,  3,  2,  3,  2,  3,  2,  3,  3,  3,  3,  2,  3,  2,  3,  3,
-     2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,  2,  3,
-     3,  3,  2,  3,  3,  3,  2,  2,  2,  2,  2,  2,  0,  0, 15,  0,
-     0,  2,  2,  2,  2,  2,  0,  0,  0,  2,  2,  2,  0,  0, 13, 13,
--   13, 13, 13, 13, 13,  2, 13,  2,  2,  2,  2,  2,  2,  2,  2,  0,
--    2,  2,  2,  2,  2,  2, 16, 50, 84,118, 88, 89, 90, 85, 85, 85,
--   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
--   85, 85, 85, 85, 85, 91, 85, 85,220, 85, 85, 85, 85, 85, 85, 85,
--   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
--   94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   13, 13, 13, 13, 13,  2, 13, 13, 13, 13, 13,  2,  2,  2, 13,  2,
-+    2,  2,  2,  2,  2,  2,  2,  0,  2,  2,  2,  2,  2,  2, 16, 50,
-+   84,118, 88, 89, 90, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 91, 85, 85,
-+  220, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 94, 85, 85, 85, 85, 85, 85, 85,
-    85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
--   85, 85, 85, 85, 85, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12,  0,  0,
--   13, 14, 15, 16, 17, 18, 19, 20, 21, 22,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 23,  0,  0, 24, 25, 26,
--   27, 28, 29, 30,  0,  0, 31, 32,  0, 33,  0, 34,  0, 35,  0,  0,
--    0,  0, 36, 37, 38, 39,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0, 40,  0,  0,  0,  0,  0,  0,  0,
--    0,  0, 41, 42,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0, 43, 44,  0, 45,  0,  0,  0,  0,
--    0,  0, 46, 47,  0,  0,  0,  0,  0, 48,  0, 49,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 50, 51,  0,  0,  0, 52,
--    0,  0, 53,  0,  0,  0,  0,  0,  0,  0, 54,  0,  0,  0,  0,  0,
--    0,  0, 55,  0,  0,  0,  0,  0,  0,  0, 56,  0,  0,  0,  0,  0,
--    0,  0,  0, 57,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 58, 59, 60, 61, 62, 63,
--   64, 65,  0,  0,  0,  0,  0,  0, 66,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0, 67, 68,  0, 69, 70,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
--   81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
--   97, 98, 99,100,101,102,103,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,104,  0,  0,  0,  0,  0,  0,105,
--  106,  0,107,  0,  0,  0,108,  0,109,  0,110,  0,111,112,113,  0,
--  114,  0,  0,  0,115,  0,  0,  0,116,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,117,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,118,119,120,121,  0,122,
--  123,124,125,126,  0,127,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,128,129,130,131,132,133,134,135,136,137,
--  138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
--  154,155,156,157,  0,  0,  0,158,159,160,161,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,162,
--  163,  0,  0,  0,  0,  0,  0,  0,164,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,165,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,166,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,167,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,168,169,  0,  0,  0,
--    0,170,171,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,172,173,174,175,176,177,178,179,180,181,
--  182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
--  198,199,200,201,202,203,204,205,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
--    0,  0,  1,  2,  3,  4,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 15,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  5,  6,
-+    7,  8,  9, 10, 11, 12,  0,  0, 13, 14, 15, 16, 17, 18, 19, 20,
-+   21, 22,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 23,  0,  0, 24, 25, 26, 27, 28, 29, 30,  0,  0, 31, 32,
-+    0, 33,  0, 34,  0, 35,  0,  0,  0,  0, 36, 37, 38, 39,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   40,  0,  0,  0,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   43, 44,  0, 45,  0,  0,  0,  0,  0,  0, 46, 47,  0,  0,  0,  0,
-+    0, 48,  0, 49,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 50, 51,  0,  0,  0, 52,  0,  0, 53,  0,  0,  0,  0,  0,
-+    0,  0, 54,  0,  0,  0,  0,  0,  0,  0, 55,  0,  0,  0,  0,  0,
-+    0,  0, 56,  0,  0,  0,  0,  0,  0,  0,  0, 57,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 58, 59, 60, 61, 62, 63, 64, 65,  0,  0,  0,  0,  0,  0,
-+   66,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 67, 68,
-+    0, 69, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 71, 72,
-+   73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
-+   89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  104,  0,  0,  0,  0,  0,  0,105,106,  0,107,  0,  0,  0,108,  0,
-+  109,  0,110,  0,111,112,113,  0,114,  0,  0,  0,115,  0,  0,  0,
-+  116,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,117,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,118,119,120,121,  0,122,123,124,125,126,  0,127,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,128,129,
-+  130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,
-+  146,147,148,149,150,151,152,153,154,155,156,157,  0,  0,  0,158,
-+  159,160,161,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,162,163,  0,  0,  0,  0,  0,  0,  0,
-+  164,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,165,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,166,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,167,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,168,169,  0,  0,  0,  0,170,171,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,172,173,
-+  174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,
-+  190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
- };
- static const uint16_t
--_hb_ucd_u16[8928] =
-+_hb_ucd_u16[8944] =
- {
-      0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
-     13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
-     13,  13,  13,  24,  25,  11,  11,  11,  11,  26,  11,  27,  28,  29,  30,  31,
-     32,  32,  32,  32,  32,  32,  32,  33,  34,  35,  36,  11,  37,  38,  13,  39,
-      9,   9,   9,  11,  11,  11,  13,  13,  40,  13,  13,  13,  41,  13,  13,  13,
-     13,  13,  13,  42,   9,  43,  11,  11,  44,  45,  32,  46,  47,  48,  49,  50,
-     51,  52,  48,  48,  53,  32,  54,  55,  48,  48,  48,  48,  48,  56,  57,  58,
-@@ -4790,115 +5155,116 @@ static const uint16_t
-    422, 422, 422, 423, 424, 424, 424, 425,  26,  26,  26,  26,  26,  26,  26,  26,
-    426, 426, 426, 426, 427, 427, 427, 428, 427, 427, 429, 427, 427, 427, 427, 427,
-    430, 431, 432, 433, 434, 434, 435, 436, 434, 437, 434, 437, 438, 438, 438, 438,
-    439, 439, 439, 439,  26,  26,  26,  26, 440, 440, 440, 440, 441, 442, 441,  26,
-    443, 443, 443, 443, 443, 443, 444, 445, 446, 446, 447, 446, 448, 448, 449, 448,
-    450, 450, 451, 452,  26, 453,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-    454, 454, 454, 454, 454, 454, 454, 454, 454, 455,  26,  26,  26,  26,  26,  26,
-    456, 456, 456, 456, 456, 456, 457,  26, 456, 456, 456, 456, 456, 456, 457, 458,
--     0,   0,   0,   0,   0,  26,   0, 316,  26,  26,  26,  26,  26,  26,  26,  26,
--    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31,  31, 459,
--     9,   9,   9,   9,   9,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31, 459,  26,
--   460, 460, 460, 460, 460, 460, 460, 460, 460, 461, 462, 460, 460, 460,  26, 463,
--   464, 464, 464, 464, 464, 464, 464, 464, 465, 466, 467, 467, 467, 468, 467, 469,
--   470, 470, 470, 470, 470, 470, 471, 470, 472,  26, 473, 473, 473, 473, 474,  26,
--   475, 475, 475, 475, 475, 475, 475, 475, 475, 476, 475, 475, 477, 140, 478,  26,
--   479, 479, 480, 479, 479, 479, 479, 481,  26,  26,  26,  26,  26,  26,  26,  26,
--   482, 483, 484, 485, 484, 486, 487, 487, 487, 487, 487, 487, 487, 488, 487, 489,
--   490, 491, 492, 493, 493, 494, 495, 496, 491, 497, 498, 499, 500, 501, 501,  26,
--   502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 502, 503,  26,  26,  26,  26,
--   504, 504, 504, 504, 504, 504, 504, 504, 504,  26, 504, 505,  26,  26,  26,  26,
--   506, 506, 506, 506, 506, 506, 507, 506, 506, 506, 506, 507,  26,  26,  26,  26,
--   508, 508, 508, 508, 508, 508, 508, 508, 509,  26, 508, 510, 201, 511,  26,  26,
--   512, 512, 512, 512, 512, 512, 512, 513, 512, 514,  26,  26,  26,  26,  26,  26,
--   515, 515, 515, 516, 515, 517, 515, 515,  26,  26,  26,  26,  26,  26,  26,  26,
--    21,  21,  21,  21,  21,  21,  21, 518,  26,  26,  26,  26,  26,  26,  26,  26,
--    26,  26,  26,  26, 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, 520, 521,
--    26,  26,  26,  26,  60, 522,  60,  60,  60,  60,  60, 522, 523,  26,  26,  26,
--    18,  18,  18,  18,  18,  18,  18,  18,  18,  26,  54,  54,  54,  54,  54,  54,
--    54,  54,  54,  54, 524,  26,  26,  26, 525, 525, 525, 525, 525, 525, 525, 526,
--   527, 528, 527, 527, 527, 527, 529, 527, 530,  26, 527, 527, 527, 531, 532, 532,
--   532, 532, 533, 532, 532, 534, 535,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--   536, 537, 167, 167, 167, 167, 536, 538, 167,  26, 167, 539, 540, 541,  14,  14,
--    14, 257,  15, 375,  14, 542,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  84,  84,  84,  89,
--    26,  26,  26,  26,  26,  26,  26,  26, 109, 109, 109, 109, 109, 109, 543, 544,
--   545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545,
--   545, 545, 545, 546,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--   545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 545, 547, 548,  26,
--   545, 545, 545, 545, 545, 545, 545, 545, 549,  26,  26,  26,  26,  26,  26,  26,
--   550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, 550,
--   550, 550, 550, 550, 550, 551, 550, 552,  26,  26,  26,  26,  26,  26,  26,  26,
--   553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
--   553, 553, 553, 553, 553, 553, 553, 553, 554,  26,  26,  26,  26,  26,  26,  26,
-+   459, 459, 459, 459, 459,  26, 459, 460,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  31,  31,  31, 461,
-+   462, 462, 462, 462, 462,  26, 463, 463, 463, 463, 463, 464,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 465, 465, 466,  26,
-+   467, 467, 467, 467, 467, 467, 467, 467, 467, 468, 469, 467, 467, 467,  26, 470,
-+   471, 471, 471, 471, 471, 471, 471, 471, 472, 473, 474, 474, 474, 475, 474, 476,
-+   477, 477, 477, 477, 477, 477, 478, 477, 479,  26, 480, 480, 480, 480, 481,  26,
-+   482, 482, 482, 482, 482, 482, 482, 482, 482, 483, 482, 482, 484, 140, 485,  26,
-+   486, 486, 487, 486, 486, 486, 486, 488,  26,  26,  26,  26,  26,  26,  26,  26,
-+   489, 490, 491, 492, 491, 493, 494, 494, 494, 494, 494, 494, 494, 495, 494, 496,
-+   497, 498, 499, 500, 500, 501, 502, 503, 498, 504, 505, 506, 507, 508, 508,  26,
-+   509, 509, 509, 509, 509, 509, 509, 509, 509, 509, 509, 510,  26,  26,  26,  26,
-+   511, 511, 511, 511, 511, 511, 511, 511, 511,  26, 511, 512,  26,  26,  26,  26,
-+   513, 513, 513, 513, 513, 513, 514, 513, 513, 513, 513, 514,  26,  26,  26,  26,
-+   515, 515, 515, 515, 515, 515, 515, 515, 516,  26, 515, 517, 201, 518,  26,  26,
-+   519, 519, 519, 519, 519, 519, 519, 520, 519, 521,  26,  26,  26,  26,  26,  26,
-+   522, 522, 522, 523, 522, 524, 522, 522,  26,  26,  26,  26,  26,  26,  26,  26,
-+   525, 525, 525, 525, 525, 525, 525, 526,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26, 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, 528, 529,
-+    26,  26,  26,  26, 530, 531, 530, 530, 530, 530, 530, 531, 532,  26,  26,  26,
-+   533, 533, 533, 533, 533, 533, 533, 533, 533,  26, 534, 534, 534, 534, 534, 534,
-+   534, 534, 534, 534, 535,  26,  26,  26, 536, 536, 536, 536, 536, 536, 536, 537,
-+   538, 539, 538, 538, 538, 538, 540, 538, 541,  26, 538, 538, 538, 542, 543, 543,
-+   543, 543, 544, 543, 543, 545, 546,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   547, 548, 549, 549, 549, 549, 547, 550, 549,  26, 549, 551, 552, 553, 554, 554,
-+   554, 555, 556, 557, 554, 558,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 559, 559, 559, 560,
-+    26,  26,  26,  26,  26,  26,  26,  26, 109, 109, 109, 109, 109, 109, 561, 562,
-+   563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563,
-+   563, 563, 563, 564,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 563, 565, 566,  26,
-+   563, 563, 563, 563, 563, 563, 563, 563, 567,  26,  26,  26,  26,  26,  26,  26,
-+   568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, 568,
-+   568, 568, 568, 568, 568, 569, 568, 570,  26,  26,  26,  26,  26,  26,  26,  26,
-+   571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, 571,
-+   571, 571, 571, 571, 571, 571, 571, 571, 572,  26,  26,  26,  26,  26,  26,  26,
-    309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
--   309, 309, 309, 309, 309, 309, 309, 555, 556, 556, 556, 557, 556, 558,  26,  26,
--    26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 559, 559, 559, 560, 560,  26,
--   561, 561, 561, 561, 561, 561, 561, 561, 562,  26, 561, 563, 563, 561, 561, 564,
--   561, 561,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--    26,  26,  26,  26,  26,  26,  26,  26,  72,  72,  72,  72,  72,  72,  72,  72,
--    72,  72,  72, 565,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--   566, 566, 566, 566, 566, 566, 566, 566, 566, 567, 566, 566, 566, 566, 566, 566,
--   566, 568, 566, 566,  26,  26,  26,  26,  26,  26,  26,  26, 569,  26,  26,  26,
--   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570,
--   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570,  26,
--   570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 571,  26,
--   572, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
-+   309, 309, 309, 309, 309, 309, 309, 573, 574, 574, 574, 575, 574, 576,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 577, 577, 577, 578, 578,  26,
-+   579, 579, 579, 579, 579, 579, 579, 579, 580,  26, 579, 581, 581, 579, 579, 582,
-+   579, 579,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26, 583, 583, 583, 583, 583, 583, 583, 583,
-+   583, 583, 583, 584,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   585, 585, 585, 585, 585, 585, 585, 585, 585, 586, 585, 585, 585, 585, 585, 585,
-+   585, 587, 585, 585,  26,  26,  26,  26,  26,  26,  26,  26, 588,  26,  26,  26,
-+   589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589,
-+   589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589,  26,
-+   589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 589, 590,  26,
-+   591, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
-    290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290,
--   290, 290, 290, 291,  26,  26,  26,  26,  26,  26, 573,  26, 574,  26, 171, 171,
--   171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 346,
--   575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, 576, 575, 577,
--   575, 578, 575, 579, 284,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   290, 290, 290, 291,  26,  26,  26,  26,  26,  26, 592,  26, 593,  26, 594, 594,
-+   594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594,
-+   594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 594, 595,
-+   596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, 597, 596, 598,
-+   596, 599, 596, 600, 284,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 272,  26,
--     0,   0,   0,   0, 262, 361,   0,   0,   0,   0,   0,   0, 580, 581,   0, 582,
--   583, 584,   0,   0,   0, 585,   0,   0,   0,   0,   0,   0,   0, 586,  26,  26,
-+     0,   0,   0,   0, 262, 361,   0,   0,   0,   0,   0,   0, 601, 602,   0, 603,
-+   604, 605,   0,   0,   0, 606,   0,   0,   0,   0,   0,   0,   0, 607,  26,  26,
-     14,  14,  14,  14,  14,  14,  14,  14, 251,  26,  26,  26,  26,  26,  26,  26,
-     26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,   0,   0, 284,  26,
--     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 262,  26,   0,   0,   0, 586,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 262,  26,   0,   0,   0, 607,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 259,   0,   0,   0,   0,   0,
--     0,   0,   0, 259, 587, 588,   0, 589, 590,   0,   0,   0,   0,   0,   0,   0,
--   591, 592, 259, 259,   0,   0,   0, 593, 594, 595, 596,   0,   0,   0,   0,   0,
-+     0,   0,   0, 259, 608, 609,   0, 610, 611,   0,   0,   0,   0,   0,   0,   0,
-+   612, 613, 259, 259,   0,   0,   0, 614, 615, 616, 617,   0,   0,   0,   0,   0,
-      0,   0,   0,   0, 272,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0, 271,   0,   0,   0,   0,   0,   0,
--   597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597, 597,
--   597, 598,  26, 599, 600, 597,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--   274, 273, 273, 601, 602, 603,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--   280, 280, 280, 280, 280, 604, 280, 283, 280, 605,  26,  26,  26,  26,  26,  26,
--    26,  26,  26,  26,  26,  26,  26,  26,  25,  25,  25,  25,  25,  25,  25, 606,
--   607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607,
--   607, 607, 607, 607, 607, 607, 607, 607, 608, 607, 609,  26,  26,  26,  26,  26,
--   610, 610, 610, 610, 610, 610, 610, 610, 610, 611, 610, 612,  26,  26,  26,  26,
-+   618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618,
-+   618, 619,  26, 620, 621, 618,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   274, 273, 273, 622, 623, 624,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+   625, 625, 625, 625, 625, 626, 625, 627, 625, 628,  26,  26,  26,  26,  26,  26,
-+    26,  26,  26,  26,  26,  26,  26,  26, 629, 629, 629, 629, 629, 629, 629, 630,
-+   631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631, 631,
-+   631, 631, 631, 631, 631, 631, 631, 631, 632, 631, 633,  26,  26,  26,  26,  26,
-+   634, 634, 634, 634, 634, 634, 634, 634, 634, 635, 634, 636,  26,  26,  26,  26,
-     26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26, 361,   0,
--     0,   0,   0,   0,   0,   0, 613,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-+     0,   0,   0,   0,   0,   0, 637,  26,  26,  26,  26,  26,  26,  26,  26,  26,
-    361,   0,   0,   0,   0,   0,   0, 272,  26,  26,  26,  26,  26,  26,  26,  26,
--   614,  31,  31,  31, 615, 616, 617, 618, 619, 620, 615, 621, 615, 617, 617, 622,
--    31, 623,  31, 624, 625, 623,  31, 624,  26,  26,  26,  26,  26,  26, 355,  26,
-+   638,  31,  31,  31, 639, 640, 641, 642, 643, 644, 639, 645, 639, 641, 641, 646,
-+    31, 647,  31, 648, 649, 647,  31, 648,  26,  26,  26,  26,  26,  26, 355,  26,
-      0,   0,   0,   0,   0, 284,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      0,   0, 284,  26,   0, 262, 361,   0, 361,   0, 361,   0,   0,   0, 272,  26,
--     0, 613,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 613,   0,   0,
--     0,   0,   0,   0,   0, 613,  26,  26,  26,  26,  26,  26, 626,   0,   0,   0,
--   627,  26,   0,   0,   0,   0,   0, 284,   0, 586, 316,  26, 272,  26,  26,  26,
--     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 272,  26,   0, 613,   0, 269,
-+     0, 637,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 637,   0,   0,
-+     0,   0,   0,   0,   0, 637,  26,  26,  26,  26,  26,  26, 650,   0,   0,   0,
-+   651,  26,   0,   0,   0,   0,   0, 284,   0, 607, 316,  26, 272,  26,  26,  26,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 272,  26,   0, 637,   0, 269,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 284,  26,
--     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 586,   0, 284,  26,  26,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 607,   0, 284,  26,  26,
-      0, 284,   0,   0,   0,   0,   0,   0,   0,  26,   0, 316,   0,   0,   0,   0,
-      0,  26,   0,   0,   0, 272,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--     0, 590,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 593, 595,
--     0,   0,   0,   0, 592, 628,   0,   0,   0, 592,   0,   0,   0,   0,   0,   0,
-+     0, 611,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 614, 616,
-+     0,   0,   0,   0, 613, 652,   0,   0,   0, 613,   0,   0,   0,   0,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 284,  26,   0, 272, 284, 269,
-    269,  26, 272,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 629,  26,  26,  26,  26,  26,
--   280, 280, 280, 280, 280, 280, 604,  26, 280, 280, 280, 280, 280, 280, 280, 280,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 653,  26,  26,  26,  26,  26,
-+   280, 280, 280, 280, 280, 280, 654,  26, 280, 280, 280, 280, 280, 280, 280, 280,
-    280, 280, 280, 283, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
-    280, 280, 280, 280, 348,  26, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
--   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 630,  26,  26,  26,
-+   280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 655,  26,  26,  26,
-    280, 280, 280, 283,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,  26,
--   631,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   656,  26,  26,  26,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-      9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,
-      9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   9,   0,   0,
-      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-    939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
-      0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
-   1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
-      0,1219,1226,1227,1228,1229,1233,   0,   0,1267,1268,1269,1273,1298,   0,1303,
-    943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
-@@ -5144,17 +5510,1187 @@ static inline int_fast16_t
- static inline uint_fast8_t
- _hb_ucd_sc (unsigned u)
- {
-   return u<918000u?_hb_ucd_u8[10822+(((_hb_ucd_u16[1920+(((_hb_ucd_u8[10150+(((_hb_ucd_u8[9700+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
- }
- static inline uint_fast16_t
- _hb_ucd_dm (unsigned u)
- {
--  return u<195102u?_hb_ucd_u16[5632+(((_hb_ucd_u8[15974+(((_hb_ucd_b4(15878+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0;
-+  return u<195102u?_hb_ucd_u16[5648+(((_hb_ucd_u8[16174+(((_hb_ucd_b4(16078+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0;
-+}
-+
-+
-+#else
-+
-+static const uint8_t
-+_hb_ucd_u8[13072] =
-+{
-+    0,  1,  2,  3,  4,  5,  5,  5,  5,  5,  6,  5,  5,  7,  8,  9,
-+   10, 11, 12, 13, 14, 15, 16,  5, 17, 15, 15, 18, 15, 19, 20, 21,
-+    5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 22, 23,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+   24, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-+    8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,  8,
-+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
-+   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-+   32, 33, 34, 34, 34, 34, 35, 36, 37, 34, 34, 34, 38, 39, 40, 41,
-+   42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
-+   58, 59, 60, 61, 62, 62, 63, 64, 65, 66, 67, 68, 69, 67, 70, 71,
-+   67, 67, 62, 72, 62, 62, 73, 67, 74, 75, 76, 77, 78, 67, 67, 67,
-+   79, 80, 34, 81, 82, 83, 67, 67, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 84, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   85, 34, 34, 34, 34, 34, 34, 34, 34, 86, 34, 34, 87, 88, 89, 90,
-+   91, 92, 93, 94, 95, 96, 97, 98, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
-+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+  100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,
-+  100,100, 34, 34, 34, 34,101,102, 34, 34,103,104,105,106,107,108,
-+   34, 34,109,110,111,112,113,114,115,116,117,111, 34, 34, 34,111,
-+  118,119,120,121,122,123,124,125, 34,126,127,111,128,111,129, 34,
-+  130,131,132,133,134,135,136,111,137,138,111,139,140,141,142,111,
-+  143,144,111,145,146,147,111,111,148,149,150,151,111,152,111,153,
-+   34, 34, 34, 34, 34, 34, 34, 34,154, 34, 34,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+   34, 34, 34, 34, 34, 34, 34, 34,155,111,111,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111, 34, 34, 34, 34, 34,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+   34, 34, 34, 34,156,157,158, 34,111,111,111,111,159,160,161,162,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,
-+   34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111, 34,163,111,111,111,111,111,111,
-+   67, 67,164,165,166,128, 65,111,167,168,169,170,171,172,173,174,
-+   67, 67, 67, 67,175,176,111,111,111,111,111,111,111,111,111,111,
-+  177,111,178,111,111,179,111,111,111,111,111,111,111,111,111,111,
-+   34,180,181,111,111,111,111,111,128,182,183,111, 34,184,111,111,
-+   67, 67,185, 67, 67,111, 67,186, 67, 67, 67, 67, 67, 67, 67, 67,
-+   67, 67, 67, 67, 67, 67,111,111,111,111,111,111,111,111,111,111,
-+   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
-+   34, 34, 34, 34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+   34, 34, 34, 34, 34,111,111,111,111,111,111,111,111,111,111,111,
-+  187,111,177,177,111,111,111,111,111,111,111,111,111,111,111,111,
-+  111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
-+    0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  2,  4,  5,  6,  2,
-+    7,  7,  7,  7,  7,  2,  8,  9, 10, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
-+   16, 16, 16, 16, 16, 17, 18, 19,  1, 20, 20, 21, 22, 23, 24, 25,
-+   26, 27, 15,  2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16,
-+   16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32,
-+   32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32,
-+   32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11,
-+   11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11,
-+   34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34,
-+   34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32,
-+   32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32,
-+   16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40,
-+   40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41,
-+   40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41,
-+   43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 16, 44, 16, 10,
-+   41, 41, 41, 45, 11, 11, 11, 11, 34, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34,
-+   16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 46, 34, 32, 34, 11,
-+   32, 47, 43, 43, 48, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16,
-+   11, 11, 11, 11, 49,  2,  2,  2, 16, 16, 16, 16, 50, 51, 52, 53,
-+   54, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 55,
-+   56, 57, 43, 56, 43, 43, 43, 43, 36, 36, 36, 36, 36, 36, 36, 36,
-+   36, 58,  2,  2,  2,  2,  2,  2, 59, 59, 59,  8,  9, 60,  2, 61,
-+   43, 43, 43, 43, 43, 57, 59,  2, 62, 36, 36, 36, 36, 63, 43, 43,
-+    7,  7,  7,  7,  7,  2,  2, 36, 64, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 65, 43, 43, 43, 66, 47, 43, 43, 67, 68, 69, 43, 43, 36,
-+    7,  7,  7,  7,  7, 36, 70, 71,  2,  2,  2,  2,  2,  2,  2, 72,
-+   63, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 64, 36,
-+   36, 36, 36, 43, 43, 43, 43, 43,  7,  7,  7,  7,  7, 36, 36, 36,
-+   36, 36, 36, 36, 36, 63, 43, 43, 43, 43, 40, 21,  2, 40, 68, 20,
-+   36, 36, 36, 43, 43, 68, 43, 43, 43, 43, 68, 43, 68, 43, 43, 43,
-+    2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 36, 36, 63, 43, 43,  2,
-+   36, 63, 43, 43, 43, 43, 43, 43, 43, 73, 43, 43, 43, 43, 43, 43,
-+   43, 74, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 74, 64, 75,
-+   76, 43, 43, 43, 74, 75, 76, 75, 63, 43, 43, 43, 36, 36, 36, 36,
-+   36, 43,  2,  7,  7,  7,  7,  7, 77, 36, 36, 36, 36, 36, 36, 36,
-+   63, 75, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 75,
-+   76, 43, 43, 74, 75, 75, 76, 36, 36, 36, 36, 79, 75, 75, 36, 36,
-+   36, 43, 43,  7,  7,  7,  7,  7, 36, 20, 27, 27, 27, 53, 58, 43,
-+   43, 74, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 75,
-+   76, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 64, 36, 36, 36,
-+   36, 36, 36,  7,  7,  7,  7,  7, 43, 36, 63,  2,  2,  2,  2,  2,
-+   76, 43, 43, 43, 74, 75, 76, 43, 60, 20, 20, 20, 80, 43, 43, 43,
-+   43, 75, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 64, 76,
-+   76, 43, 43, 74, 75, 75, 76, 43, 43, 43, 43, 74, 75, 75, 36, 36,
-+   71, 27, 27, 27, 27, 27, 27, 27, 43, 64, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 75, 74, 75, 75, 75, 75, 75, 76, 43,
-+   36, 36, 36, 79, 75, 75, 75, 75, 75, 75, 75,  7,  7,  7,  7,  7,
-+   27, 81, 61, 61, 53, 61, 61, 61, 74, 75, 64, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 43, 74, 75, 75, 43, 43, 43, 43, 43,
-+   43, 43, 43, 43, 36, 36, 36, 36,  7,  7,  7, 82, 27, 27, 27, 81,
-+   63, 75, 65, 36, 36, 36, 36, 36, 75, 75, 75, 74, 75, 75, 43, 43,
-+   43, 43, 74, 75, 75, 75, 75, 36, 83, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 63, 64, 75, 76, 43, 43, 75, 75, 75, 76, 70,
-+   61, 61, 36, 79, 27, 27, 27, 84, 27, 27, 27, 27, 81, 36, 36, 36,
-+   75, 75, 78, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 43, 43, 74,
-+   75, 43, 43, 43, 75, 75, 75, 75,  7, 75,  2,  2,  2,  2,  2,  2,
-+   63, 36, 43, 43, 43, 43, 43, 85, 36, 36, 36, 68, 43, 43, 43, 57,
-+    7,  7,  7,  7,  7,  2,  2,  2, 63, 36, 43, 43, 43, 43, 64, 36,
-+   36, 36, 36, 40, 43, 43, 43, 43,  7,  7,  7,  7,  7,  7, 36, 36,
-+   70, 61,  2,  2,  2,  2,  2,  2,  2, 86, 86, 61, 43, 61, 61, 61,
-+    7,  7,  7,  7,  7, 27, 27, 27, 27, 27, 47, 47, 47,  4,  4, 75,
-+   63, 43, 43, 43, 43, 43, 43, 74, 43, 43, 57, 43, 36, 36, 63, 43,
-+   43, 43, 43, 43, 43, 43, 43, 61, 61, 61, 61, 69, 61, 61, 61, 61,
-+    2,  2, 86, 61, 21,  2,  2,  2, 36, 36, 36, 36, 36, 79, 76, 43,
-+   74, 43, 43, 43, 76, 74, 76, 64, 36, 36, 36, 75, 43, 36, 36, 43,
-+   64, 75, 78, 79, 75, 75, 75, 36, 63, 43, 64, 36, 36, 36, 36, 36,
-+   36, 74, 76, 74, 75, 75, 76, 79,  7,  7,  7,  7,  7, 75, 76, 61,
-+   16, 16, 16, 16, 16, 50, 44, 16, 36, 36, 36, 36, 36, 36, 63, 43,
-+    2,  2,  2,  2, 87, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-+   61, 61, 61, 61, 61, 61, 61, 61, 11, 11, 11, 11, 16, 16, 16, 16,
-+   88, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 65,
-+   89, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 90, 91, 91,
-+   36, 36, 36, 36, 36, 58,  2, 92, 93, 36, 36, 36, 36, 36, 36, 36,
-+   36, 43, 43, 43, 43, 43, 43, 43, 36, 43, 57,  2,  2,  2,  2,  2,
-+   36, 36, 43, 76, 43, 43, 43, 75, 75, 75, 75, 74, 76, 43, 43, 43,
-+   43, 43,  2, 77,  2, 60, 63, 43,  7,  7,  7,  7,  7,  7,  7,  7,
-+    2,  2,  2, 94,  2, 56, 43, 59, 36, 95, 36, 36, 36, 36, 36, 36,
-+   36, 36, 63, 64, 36, 36, 36, 36, 36, 36, 36, 36, 63, 36, 36, 36,
-+   43, 74, 75, 76, 74, 75, 75, 75, 75, 74, 75, 75, 76, 43, 43, 43,
-+   61, 61,  2,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 27, 27, 61,
-+   36, 36, 36, 63, 74, 76, 43,  2, 36, 36, 79, 74, 43, 43, 43, 43,
-+   74, 74, 76, 43, 43, 43, 74, 75, 75, 76, 43, 43, 43, 43, 43, 43,
-+    2,  2,  2, 77,  2,  2,  2,  2, 43, 43, 43, 43, 43, 43, 43, 48,
-+   48, 48, 48, 48, 48, 48, 48, 48, 43, 43, 78, 36, 36, 36, 36, 36,
-+   36, 36, 74, 43, 43, 74, 74, 75, 75, 74, 78, 36, 36, 36, 36, 36,
-+   86, 61, 61, 61, 61, 47, 43, 43, 43, 43, 61, 61, 61, 61, 61, 61,
-+   43, 78, 36, 36, 36, 36, 36, 36, 79, 43, 43, 75, 43, 76, 43, 36,
-+   36, 36, 36, 74, 43, 75, 76, 76, 43, 75, 75, 75, 75, 75,  2,  2,
-+   36, 36, 75, 75, 75, 75, 43, 43, 43, 43, 75, 43, 43, 57,  2,  2,
-+    7,  7,  7,  7,  7,  7, 83, 36, 36, 36, 36, 36, 40, 40, 40,  2,
-+   43, 57, 43, 43, 43, 43, 43, 43, 74, 43, 43, 43, 64, 36, 63, 36,
-+   36, 36, 64, 79, 43, 36, 36, 36, 16, 16, 16, 16, 16, 16, 40, 40,
-+   40, 40, 40, 40, 40, 44, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16,
-+   16, 16, 16, 16, 16, 96, 40, 40, 32, 32, 32, 16, 16, 16, 16, 32,
-+   16, 16, 16, 16, 11, 11, 11, 11, 16, 16, 16, 16, 34, 11, 11, 11,
-+   16, 16, 16, 16, 97, 97, 97, 97, 16, 16, 16, 16, 11, 11, 98, 99,
-+   41, 16, 16, 16, 11, 11, 98, 41, 16, 16, 16, 16, 11, 11,100, 41,
-+  101,101,101,101,101,102, 59, 59, 51, 51, 51,  2,103,104,103,104,
-+    2,  2,  2,  2,105, 59, 59,106,  2,  2,  2,  2,107,108,  2,109,
-+  110,  2,111,112,  2,  2,  2,  2,  2,  9,110,  2,  2,  2,  2,113,
-+   59, 59, 59, 59, 59, 59, 59, 59,114, 40, 27, 27, 27,  8,111,115,
-+   27, 27, 27, 27, 27,  8,111, 91, 20, 20, 20, 20, 20, 20, 20, 20,
-+   43, 43, 43, 43, 43, 43,116, 48,117, 48,117, 43, 43, 43, 43, 43,
-+   61,118, 61,119, 61, 34, 11, 16, 11, 32,119, 61, 46, 11, 11, 61,
-+   61, 61,118,118,118, 11, 11,120, 11, 11, 35, 36, 39, 61, 16, 11,
-+    8,  8, 46, 16, 16, 26, 61,121, 92, 92, 92, 92, 92, 92, 92, 92,
-+   92,122,123, 92,124, 61, 61, 61,  8,  8,125, 61, 61,  8, 61, 61,
-+  125, 26, 61,125, 61, 61, 61,125, 61, 61, 61, 61, 61, 61, 61,  8,
-+   61,125,125, 61, 61, 61, 61, 61, 61, 61,  8,  8,  8,  8,  8,  8,
-+    8,  8,  8,  8,  8,  8,  8,  8, 61, 61, 61, 61,  4,  4, 61, 61,
-+    8, 61, 61, 61,126,127, 61, 61, 61, 61, 61, 61, 61, 61,125, 61,
-+   61, 61, 61, 61, 61, 26,  8,  8,  8,  8, 61, 61, 61, 61, 61, 61,
-+   61, 61, 61, 61, 61, 61,  8,  8,  8, 61, 61, 61, 61, 61, 61, 61,
-+   27, 27, 27, 27, 27, 27, 61, 61, 61, 61, 61, 61, 61, 27, 27, 27,
-+   61, 61, 61, 26, 61, 61, 61, 61, 26, 61, 61, 61, 61, 61, 61, 61,
-+   61, 61, 61, 61,  8,  8,  8,  8, 61, 61, 61, 61, 61, 61, 61, 26,
-+   61, 61, 61, 61,  4,  4,  4,  4,  4,  4,  4, 27, 27, 27, 27, 27,
-+   27, 27, 61, 61, 61, 61, 61, 61,  8,  8,111,128,  8,  8,  8,  8,
-+    8,  8,  8,  4,  4,  4,  4,  4,  8,111,129,129,129,129,129,129,
-+  129,129,129,129,128,  8,  8,  8,  8,  8,  8,  8,  4,  4,  8,  8,
-+    8,  8,  8,  8,  8,  8,  4,  8,  8,  8,125, 26,  8,  8,125, 61,
-+   32, 11, 32, 34, 34, 34, 34, 11, 32, 32, 34, 16, 16, 16, 40, 11,
-+   32, 32,121, 61, 61,119, 34,130, 43, 32, 16, 16, 50,  2, 87,  2,
-+   36, 36, 36, 36, 36, 36, 36, 95,  2,  2,  2,  2,  2,  2,  2, 56,
-+    2,103,103,  2,107,108,103,  2,  2,  2,  2,  6,  2, 94,103,  2,
-+  103,  4,  4,  4,  4,  2,  2, 77,  2,  2,  2,  2,  2, 51,  2,  2,
-+   94,131,  2,  2,  2,  2,  2,  2,  1,  2,132,133,  4,  4,  4,  4,
-+    4, 61,  4,  4,  4,  4,134, 91,135, 92, 92, 92, 92, 43, 43, 75,
-+  136, 40, 40, 61, 92,137, 58, 61, 71, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 63,138,139, 62, 36, 36, 36, 36, 36, 58, 40, 62,
-+   61, 27, 27, 61, 61, 61, 61, 61, 27, 27, 27, 27, 27, 61, 61, 61,
-+   61, 61, 61, 61, 27, 27, 27, 27,140, 27, 27, 27, 27, 27, 27, 27,
-+   36, 36, 95, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,141,  2,
-+   32, 32, 32, 32, 32, 32, 32, 63, 48,142, 43, 43, 43, 43, 43, 77,
-+   32, 32, 32, 32, 32, 32, 40, 43, 36, 36, 36, 92, 92, 92, 92, 92,
-+   43,  2,  2,  2,  2,  2,  2,  2, 41, 41, 41,139, 40, 40, 40, 40,
-+   41, 32, 32, 32, 32, 32, 32, 32, 16, 32, 32, 32, 32, 32, 32, 32,
-+   44, 16, 16, 16, 34, 34, 34, 32, 32, 32, 32, 32, 42,143, 34, 35,
-+   32, 32, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 11, 11, 32,
-+   11, 11, 32, 32, 32, 32, 32, 32, 16, 32, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11,144, 40, 35, 36, 36, 36, 64, 36, 64, 36, 63, 36, 36,
-+   36, 79, 76, 74, 61, 61, 61, 61, 27, 27, 27, 61,145, 61, 61, 61,
-+   36, 36,  2,  2,  2,  2,  2,  2, 75, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 75, 75, 75, 75, 75, 75, 75, 75, 43, 43, 43, 43, 43,  2,
-+   43, 36, 36, 36,  2, 65, 65, 63, 36, 36, 36, 43, 43, 43, 43,  2,
-+   36, 36, 36, 63, 43, 43, 43, 43, 43, 75, 75, 75, 75, 75, 75,146,
-+   36, 63, 75, 43, 43, 75, 43, 75,146,  2,  2,  2,  2,  2,  2, 77,
-+    7,  7,  7,  7,  7,  7,  7,  2, 36, 36, 63, 62, 36, 36, 36, 36,
-+   36, 36, 36, 36, 63, 43, 43, 74, 76, 74, 76, 43, 43, 43, 43, 43,
-+   36, 63, 36, 36, 36, 36, 74, 75,  7,  7,  7,  7,  7,  7,  2,  2,
-+   62, 36, 36, 70, 61, 79, 74, 36, 64, 43, 64, 63, 64, 36, 36, 43,
-+   36, 36, 36, 36, 36, 36, 95,  2, 36, 36, 36, 36, 36, 79, 43, 75,
-+    2, 95,147, 43, 43, 43, 43, 43, 16, 16, 16, 16, 16, 99, 40, 40,
-+   36, 79, 76, 75, 74,146, 76, 43,148,148,148,148,148,148,148,148,
-+  149,149,149,149,149,149,149,149, 16, 16, 16, 16, 16, 16, 35, 64,
-+   36, 36, 36, 36,150, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
-+   41,151, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,129,
-+  152,152,152,152,152,152,152,152, 36, 36, 36, 36, 36, 36,145, 61,
-+    2,  2,  2,153,112,  2,  2,  2,  6,154,155,129,129,129,129,129,
-+  129,129,112,153,112,  2,109,156,  2,  2,  2,  2,134,129,129,112,
-+    2,157,  8,  8, 60,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36,158,
-+    2,  2,  3,  2,  4,  5,  6,  2, 16, 16, 16, 16, 16, 17, 18,111,
-+  112,  4,  2, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 40, 20,159, 53, 20, 26,  8,125, 61,
-+   61, 61, 61, 61,160, 59, 61, 61,  2,  2,  2, 87, 27, 27, 27, 27,
-+   27, 27, 27, 81, 61, 61, 61, 61, 92, 92,124, 27, 81, 61, 61, 61,
-+   61, 61, 61, 61, 61, 27, 61, 61, 61, 61, 61, 61, 61, 61, 47, 43,
-+  161,161,161,161,161,161,161,161,162, 27, 27, 27, 27, 27, 27, 27,
-+   27, 27, 27, 27, 27, 27, 84, 36,133, 36, 36, 36, 36, 92, 92, 92,
-+   36, 36, 36, 36, 36, 36, 36, 58,163, 92, 92, 92, 92, 92, 92, 92,
-+   36, 36, 36, 58, 27, 27, 27, 27, 36, 36, 36, 70,140, 27, 27, 27,
-+   36, 36, 36,164, 27, 27, 27, 27, 36, 36, 36, 36, 36,164, 27, 27,
-+   36, 36, 36, 27, 27, 27, 27, 30, 36, 36, 36, 36, 36, 36, 27, 36,
-+   63, 43, 43, 43, 43, 43, 43, 43, 36, 36, 36, 36, 43, 43, 43, 43,
-+   36, 36, 36, 36, 36, 36,164, 30, 36, 36, 36, 36, 36, 36,164, 27,
-+   36, 36, 36, 36, 71, 36, 36, 36, 36, 36, 63, 43, 43,162, 27, 27,
-+   36, 36, 36, 36, 58,  2,  2,  2, 36, 36, 36, 36, 27, 27, 27, 27,
-+   16, 16, 16, 16, 16, 27, 27, 27, 36, 36, 43, 43, 43, 43, 43, 43,
-+   27, 27, 27, 84, 36, 36, 36, 36,162, 27, 30,  2,  2,  2,  2,  2,
-+   76, 78, 36, 36, 36, 36, 36, 36, 43, 43, 43, 57,  2,  2,  2,  2,
-+    2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,165, 75, 76, 43, 74, 76, 57, 72,  2,
-+    2,  2,  2,  2,  2,  2, 72, 59, 36, 36, 36, 63, 43, 43, 76, 43,
-+   43, 43, 43,  7,  7,  7,  7,  7,  2,  2, 79, 75, 75, 75, 75, 75,
-+   36, 63,  2, 36, 36, 36, 36, 36, 36, 79, 75, 43, 43, 43, 43, 74,
-+   78, 36, 58,  2, 56, 43, 57,  2,  7,  7,  7,  7,  7, 58, 58,  2,
-+   87, 27, 27, 27, 27, 27, 27, 27, 36, 36, 36, 36, 36, 36, 75, 76,
-+   43, 75, 74, 43,  2,  2,  2, 43, 36, 36, 36, 36, 36, 36, 36, 63,
-+   74, 75, 75, 75, 75, 75, 75, 75, 36, 36, 36, 79, 75, 75, 78, 36,
-+   36, 75, 75, 43, 43, 43, 43, 43, 36, 36, 79, 75, 43, 43, 43, 43,
-+   75, 43, 74, 64, 36, 58,  2,  2,  7,  7,  7,  7,  7, 82,  2, 64,
-+   75, 76, 43, 43, 74, 74, 75, 76, 74, 43, 36, 65, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 36, 36, 79, 75, 43, 43, 43, 75, 75, 43, 76,
-+   57,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 43, 43,
-+   75, 76, 43, 43, 43, 74, 76, 76, 57,  2, 36, 36, 36, 36, 36, 36,
-+   36, 36, 36, 36, 36, 63, 76, 75, 43, 43, 43, 76, 36, 36, 36, 36,
-+   75, 43, 43, 76, 43, 43, 43, 43,  7,  7,  7,  7,  7, 27,  2, 86,
-+   43, 43, 43, 43, 76, 57,  2,  2, 27, 27, 27, 27, 27, 27, 27, 84,
-+   79, 75, 43, 43, 43, 43, 75, 75, 64, 65, 75, 75, 75, 75, 75, 75,
-+   75, 75, 75, 75, 75, 75, 75, 75, 63, 43, 43, 43, 43, 64, 36, 36,
-+   36, 63, 43, 43, 74, 63, 43, 57,  2,  2,  2, 56, 43, 43, 43, 43,
-+   63, 43, 43, 74, 76, 43, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43,
-+   43, 43, 43, 74, 43,  2, 65,  2, 43, 43, 43, 43, 43, 43, 43, 76,
-+   58,  2,  2,  2,  2,  2,  2,  2,  2, 36, 36, 36, 36, 36, 36, 36,
-+   43, 43, 43, 43, 74, 43, 43, 43, 74, 43, 76, 43, 43, 43, 43, 43,
-+   43, 43, 43, 63, 43, 43, 43, 43, 36, 36, 36, 36, 36, 75, 75, 75,
-+   43, 74, 76, 76, 36, 36, 36, 36, 36, 63, 74,146,  2,  2,  2,  2,
-+   27, 27, 81, 61, 61, 61, 53, 20,145, 61, 61, 61, 61, 61, 61, 61,
-+   61, 61, 61, 61, 61, 61, 61, 21, 43, 43, 57,  2,  2,  2,  2,  2,
-+   43, 43, 43, 57,  2,  2, 61, 61, 40, 40, 86, 61, 61, 61, 61, 61,
-+    7,  7,  7,  7,  7,166, 27, 27, 27, 84, 36, 36, 36, 36, 36, 36,
-+   27, 27, 27, 30,  2,  2,  2,  2, 79, 75, 75, 75, 75, 75, 75, 75,
-+   75, 75, 75, 75, 75, 75, 75, 76, 43, 67, 40, 40, 40, 40, 40, 40,
-+   40, 77, 40, 40, 40, 40, 40, 40, 36, 36, 36, 36, 36, 36, 47, 57,
-+   61, 61,167, 76, 43, 61,167, 75, 75,168, 59, 59, 59, 73, 43, 43,
-+   43, 69, 47, 43, 43, 43, 61, 61, 61, 61, 61, 61, 61, 43, 43, 61,
-+   61, 43, 69, 61, 61, 61, 61, 61, 11, 11, 11, 11, 11, 16, 16, 16,
-+   16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
-+   11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
-+   11, 11, 11, 16, 16, 16, 16, 16, 31, 16, 16, 16, 16, 16, 16, 16,
-+   16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11, 11, 11,
-+   11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11,
-+   11, 11, 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33,
-+   16, 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31,
-+   16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16,
-+   16, 33, 16, 16, 16, 32, 16,  7, 43, 43, 43, 69, 61, 47, 43, 43,
-+   43, 43, 43, 43, 43, 43, 69, 61, 61, 61, 47, 61, 61, 61, 61, 61,
-+   61, 61, 69, 21,  2,  2,  2,  2,  2,  2,  2,  2,  2, 56, 43, 43,
-+   43, 43, 43, 67, 40, 40, 40, 40,  7,  7,  7,  7,  7,  7,  7, 70,
-+   36, 36, 36, 36, 36, 36, 43, 43,  7,  7,  7,  7,  7,  7,  7,169,
-+   16, 16, 43, 43, 43, 67, 40, 40, 27, 27, 27, 27, 27, 27,140, 27,
-+  170, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,140,
-+   61, 61, 61, 61, 61, 25, 41, 41,  0,  0, 29, 21, 21, 21, 23, 21,
-+   22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21,  9,  9,  9,
-+    9, 22, 21, 18, 24, 16, 24,  5,  5,  5,  5, 22, 25, 18, 25,  0,
-+   23, 23, 26, 21, 24, 26,  7, 20, 25,  1, 26, 24, 26, 25, 15, 15,
-+   24, 15,  7, 19, 15, 21,  9, 25,  9,  5,  5, 25,  5,  9,  5,  7,
-+    7,  7,  9,  8,  8,  5,  7,  5,  6,  6, 24, 24,  6, 24, 12, 12,
-+    6,  5,  9, 21, 25,  9, 26, 12, 11, 11,  9,  6,  5, 21, 17, 17,
-+   17, 26, 26, 23, 23, 12, 17, 12, 21, 12, 12, 21,  7, 21,  1,  1,
-+   21, 23, 26, 26,  6,  7,  7, 12, 12,  7, 21,  7, 12,  1, 12,  6,
-+    6, 12, 12, 26,  7, 26, 26,  7, 21,  1,  1, 12, 12, 10, 10, 10,
-+   10, 12, 21,  6, 10,  7,  7, 10, 23,  7, 15, 26, 13, 21, 13,  7,
-+   15,  7, 12, 23, 21, 26, 21, 15, 17,  7, 29,  7,  7, 22, 18, 18,
-+   14, 14, 14,  7, 17, 21,  7,  6,  5,  6,  8,  8,  8, 24,  5, 24,
-+    9, 24, 29, 29, 29,  1, 20, 19, 22, 20, 27, 28,  1, 29, 21, 20,
-+   19, 21, 21, 16, 16, 21, 25, 22, 18, 21, 21, 29, 15,  6, 18,  6,
-+   12, 11, 11, 12,  9, 26, 26,  9, 26,  5,  5, 26, 14,  9,  5, 14,
-+   14, 15, 25, 26, 26, 22, 18, 26, 18, 25, 18, 22,  5, 12, 22, 21,
-+   26,  6,  7, 14, 17, 22, 26, 14, 17,  6, 14,  6, 12, 24, 24,  6,
-+   26, 15,  6, 21, 11, 21, 24,  9,  9,  7, 23, 26, 10, 21,  6, 10,
-+    4,  4,  3,  3,  7, 25, 24,  7, 22, 22, 21, 22, 17, 16, 16, 22,
-+   16, 16, 25, 17,  7,  1, 25, 24, 26,  1,  2,  2, 12, 15, 21, 14,
-+    7, 15, 13, 12, 13, 15, 26, 10, 10,  1, 13, 23, 23, 15,  0,  1,
-+    2,  3,  4,  5,  6,  7,  8,  9,  9, 10, 11,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9, 12, 13,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 14, 15, 16,  9,
-+   17, 18, 19, 20, 21, 22,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9, 23,  9,  9,  9,  9,  9,  9,  9,
-+    9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 24,  9,  9,
-+    9,  9, 25,  9,  9,  9, 26,  9, 27,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  1,  2,  0,  0,  0,  0,  3,  0,  0,  0,
-+    4,  5,  6,  7,  0,  8,  9, 10,  0, 11, 12, 13,  0, 14, 15, 16,
-+   15, 17, 15, 18, 15, 18, 15, 18,  0, 18,  0, 19, 15, 18, 20, 18,
-+    0, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,  0, 31,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0, 32,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 33,  0,  0, 34,  0,  0, 35,  0, 36,  0,
-+    0,  0, 37, 38, 39,  0, 40, 41, 42, 43, 44,  0,  0, 45,  0,  0,
-+    0, 46,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 47,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 48,  0, 49,
-+    0, 50,  0,  0,  0,  0,  0,  0,  0,  0, 51,  0, 52,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0, 53, 54, 55,  0,  0,  0,  0, 56,  0,  0, 57, 58, 59,
-+   60, 61,  0,  0, 62, 63,  0,  0,  0, 64,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0, 65,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 66,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0, 67,  0,  0,  0, 68,  0, 69,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 70,  0,  0, 71,  0,  0,  0,  0,  0,  0,  0,  0, 72,  0,
-+    0,  0,  0,  0,  0,  0,  0, 73,  0,  0,  0, 74, 75,  0, 76, 60,
-+    0, 77, 78,  0,  0, 79, 80, 81,  0,  0,  0, 82,  0, 83,  0,  0,
-+   49, 84, 49,  0, 85,  0, 86,  0,  0,  0, 75,  0,  0,  0,  0,  0,
-+    0, 87, 88, 89, 90,  0,  0,  0,  0,  0, 49,  0,  0,  0,  0, 91,
-+   92,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0, 93, 94,  0,  0,  0,  0,  0, 95,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 96,
-+   97,  0,  0, 98,  0,  0,  0,  0,  0,  0, 99,  0,  0,  0, 94,  0,
-+    0,  0,  0,  0,  0,100,  0,  0,  0,  0,  0,  0,  0,101,  0,102,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,
-+    3,  4,  5,  6,  7,  0,  8,  0,  0,  0,  0,  9, 10, 11, 12,  0,
-+    0,  0,  0, 13,  0,  0, 14, 15,  0, 16,  0, 17, 18,  0,  0, 19,
-+    0, 20, 21,  0,  0,  0,  0,  0, 22, 23,  0, 24, 25,  0,  0, 26,
-+    0,  0,  0, 27, 28, 29,  0,  0,  0, 30, 31, 32,  0,  0, 31,  0,
-+    0, 33, 31,  0,  0,  0, 31, 34,  0,  0,  0,  0,  0, 35, 36,  0,
-+    0,  0,  0,  0,  0, 37, 38,  0,  0,  0,  0,  0,  0, 39, 40,  0,
-+    0,  0,  0, 41,  0, 42,  0,  0,  0, 43, 44,  0,  0,  0, 45,  0,
-+    0,  0,  0,  0,  0, 46, 47,  0,  0,  0,  0, 48,  0,  0,  0, 49,
-+    0, 49,  0, 50,  0,  0,  0,  0, 51,  0,  0,  0,  0, 52,  0, 53,
-+    0,  0,  0,  0, 54, 55,  0,  0,  0, 56,  0,  0,  0, 57, 49,  0,
-+   58, 59,  0,  0, 60,  0,  0,  0, 61, 62,  0,  0,  0, 63,  0, 64,
-+   65, 66, 67, 68,  1, 69,  0, 70, 71, 72,  0,  0, 73, 74,  0,  0,
-+    0, 75,  0,  0,  1,  1,  0,  0, 76,  0,  0, 77,  0,  0,  0,  0,
-+   73, 78,  0, 79,  0,  0,  0,  0,  0, 74, 80,  0,  0,  0, 49,  0,
-+    1, 74,  0,  0, 81,  0,  0, 82,  0,  0,  0,  0,  0, 83, 54,  0,
-+    0,  0,  0,  0,  0, 84, 85,  0,  0, 80,  0,  0, 31,  0,  0, 86,
-+    0,  0,  0,  0, 87,  0,  0,  0,  0, 47,  0,  0, 88,  0,  0,  0,
-+    0, 89, 90,  0,  0, 91,  0,  0, 92,  0,  0,  0, 93,  0, 94, 88,
-+    0,  0, 80,  0,  0, 75,  0,  0,  0, 95, 96,  0,  0, 97, 98,  0,
-+    0,  0,  0,  0,  0, 99,  0,  0,100,  0,  0,  0,  0,101, 31,  0,
-+  102,103,104, 33,  0,  0,105,  0,  0,  0,106,  0,  0,  0,  0,  0,
-+    0,107,  0,  0,108,  0,  0,  0, 54,  0,  0,  0,  0, 49,109,  0,
-+    0,  0,  0,110,  0,  0,111,  0,  0,  0,  0,109,  0,  0,  0,  0,
-+    0,112,  0,  0,  0,113,  0,114,  0,  0,  0,  0,115,116,117,  0,
-+  118,  0,119,  0,  0,  0,120,121,122,  0,  0,  0,123,  0,  0,124,
-+    0,  0,125,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  2,
-+    3,  4,  5,  6,  7,  4,  4,  8,  9, 10,  1, 11, 12, 13, 14, 15,
-+   16, 17, 18,  1,  1,  1, 19,  1,  0,  0, 20, 21, 22,  1, 23,  4,
-+   21, 24, 25, 26, 27, 28, 29, 30,  0,  0,  1,  1, 31,  0,  0,  0,
-+   32, 33, 34, 35,  1, 36, 37,  0,  0,  0,  0, 38,  1, 39, 14, 39,
-+   40, 41, 42,  0,  0,  0, 43, 36, 44, 45, 21, 45, 46,  0,  0,  0,
-+   19,  1, 21,  0,  0, 47,  0, 38, 48,  1,  1, 49, 49, 50,  0,  0,
-+   51,  0, 52,  1,  1,  1, 53, 21, 43, 54, 55, 21, 35,  1,  0,  0,
-+    0, 56,  0,  0,  0, 57, 58, 59,  0,  0,  0,  0,  0, 60,  0, 61,
-+    0,  0,  0,  0, 62, 63,  0,  0, 64,  0,  0,  0, 65,  0,  0,  0,
-+   66,  0,  0,  0, 67,  0,  0,  0, 68,  0,  0,  0, 69,  0,  0, 70,
-+   71,  0, 72, 73, 74, 75, 76, 77,  0,  0,  0, 78,  0,  0,  0, 79,
-+   80,  0,  0,  0,  0, 47,  0,  0,  0, 49,  0, 63,  0,  0, 64,  0,
-+    0, 81,  0,  0, 82,  0,  0,  0, 83,  0,  0, 19, 84,  0, 63,  0,
-+    0,  0,  0, 49,  1, 85,  1, 54, 15, 41,  0, 56,  0,  0,  0,  0,
-+   19, 10,  1,  0,  0,  0,  0,  0, 86,  0,  0, 87,  0,  0, 86,  0,
-+    0,  0,  0, 79,  0,  0, 88,  9, 12,  4, 89,  8, 90, 47,  0, 59,
-+   50,  0, 21,  1, 21, 91, 92,  1,  1,  1,  1, 93, 94, 95, 96,  1,
-+   97, 59, 81, 98, 99,  4, 59,  0,  0,  0,  0,  0,  0, 19, 50,  0,
-+    0,  0,  0,  0,  0, 62,  0,  0,100,101,  0,  0,102,  0,  0,  1,
-+    1, 50,  0,  0,  0, 38,  0, 64,  0,  0,  0,  0, 52, 69, 62,  0,
-+    0,  0, 79,  0,  0,  0,103,104, 59, 38, 81,  0,  0,  0,  0,  0,
-+    0,105,  1, 14,  4, 12, 84,  0,  0,  0,  0, 38, 88,  0,  0,  0,
-+    0,106,  0,  0,107, 62,  0,108,  0,  0,  0,  1,  0,  0,  0,109,
-+   14, 54,  0,  0,110,  0, 88,  0,  0,  0, 62, 63,  0,  0, 63,  0,
-+   87,  0,  0,110,  0,  0,  0,  0,111,  0,  0,  0, 79, 56,  0, 38,
-+    1, 59,  1, 59,  0,  0, 64, 87,  0,  0,112,  0,  0,  0, 56,  0,
-+    0,  0,  0,112,  0,  0,  0,  0, 62,  0,  0, 62,  0,  0,  0,  0,
-+   57,  0, 87,113,  0,  0,  8, 90,  0,  0,  1, 88,  0,  0,  0,  0,
-+    0,114,  0,115,116,117,118,  0, 52,  4,119, 49, 23,  0,  0,  0,
-+   38, 50, 38, 59,  0,  0,  1, 88,  1,  1,  1,  1, 39,  1, 48,103,
-+   88,  0,  0,  0,  0,  1,  4,119,  0,  0,  0,  1,120,  0,  0,  0,
-+    0,  0,230,230,230,230,230,232,220,220,220,220,232,216,220,220,
-+  220,220,220,202,202,220,220,220,220,202,202,220,220,220,  1,  1,
-+    1,  1,  1,220,220,220,220,230,230,230,230,240,230,220,220,220,
-+  230,230,230,220,220,  0,230,230,230,220,220,220,220,230,232,220,
-+  220,230,233,234,234,233,234,234,233,230,  0,  0,  0,230,  0,220,
-+  230,230,230,230,220,230,230,230,222,220,230,230,220,220,230,222,
-+  228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22,
-+    0, 23,  0, 24, 25,  0,230,220,  0, 18, 30, 31, 32,  0,  0,  0,
-+    0, 27, 28, 29, 30, 31, 32, 33, 34,230,230,220,220,230,220,230,
-+  230,220, 35,  0,  0,  0,  0,  0,230,230,230,  0,  0,230,230,  0,
-+  220,230,230,220,  0,  0,  0, 36,  0,  0,230,220,230,230,220,220,
-+  230,220,220,230,220,230,220,230,230,  0,  0,220,  0,  0,230,230,
-+    0,230,  0,230,230,230,230,230,  0,  0,  0,220,220,220,  0,  0,
-+    0,220,230,230,  0,220,230,220,220,220, 27, 28, 29,230,  7,  0,
-+    0,  0,  0,  9,  0,  0,  0,230,220,230,230,  0,  0,  0,  0,  0,
-+  230,  0,  0, 84, 91,  0,  0,  0,  0,  9,  9,  0,  0,  0,  0,  0,
-+    9,  0,103,103,  9,  0,107,107,107,107,118,118,  9,  0,122,122,
-+  122,122,220,220,  0,  0,  0,220,  0,220,  0,216,  0,  0,  0,129,
-+  130,  0,132,  0,  0,  0,  0,  0,130,130,130,130,  0,  0,130,  0,
-+  230,230,  9,  0,230,230,  0,  0,220,  0,  0,  0,  0,  7,  0,  9,
-+    9,  0,  0,230,  0,  0,  0,228,  0,  0,  0,222,230,220,220,  0,
-+    0,  0,230,  0,  0,220,  0,  0,  9,  9,  0,  0,  7,  0,230,230,
-+  230,  0,230,  0,  1,  1,  1,  0,  0,  0,230,234,214,220,202,230,
-+  230,230,230,230,232,228,228,220,  0,230,233,220,230,220,230,230,
-+    1,  1,  1,  1,  1,230,  0,  1,  1,230,220,230,  1,  1,  0,  0,
-+  218,228,232,222,224,224,  0,  8,  8,  0,230,  0,230,230,220,  0,
-+    0,230,  0,  0, 26,  0,  0,220,  0,230,230,  1,220,  0,  0,230,
-+  220,  0,  0,  0,220,220,  0,  9,  7,  0,  0,  7,  9,  0,  0,  0,
-+    9,  7,  9,  9,  0,  0,  0,  0,  1,  0,  0,216,216,  1,  1,  1,
-+    0,  0,  0,226,216,216,216,216,216,  0,220,220,220,  0,230,230,
-+    7,  0, 16, 17, 17, 33, 17, 49, 17, 17, 84, 97,135,145, 26, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
-+   17,177,  0,  1,  2,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,
-+    3,  3,  3,  3,  3,  3,  4,  3,  3,  3,  3,  3,  5,  3,  3,  3,
-+    3,  3,  6,  7,  8,  3,  3,  3,  3,  3,  9, 10, 11, 12, 13,  3,
-+    3,  3,  3,  3,  3,  3,  3, 14,  3, 15,  3,  3,  3,  3,  3,  3,
-+   16, 17, 18, 19, 20, 21,  3,  3,  3, 22, 23,  3,  3,  3,  3,  3,
-+    3,  3, 24,  3,  3,  3,  3,  3,  3,  3,  3, 25,  3,  3, 26, 27,
-+    0,  1,  0,  0,  0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,
-+    0,  3,  0,  0,  0,  0,  0,  4,  0,  5,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  6,  0,  0,  0,  7,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  8,  9,  0,  0,  0,  0,  0,
-+    0,  9,  0,  9,  0,  0,  0,  0,  0,  0,  0, 10, 11, 12, 13,  0,
-+    0, 14, 15, 16,  6,  0, 17, 18, 19, 19, 19, 20, 21, 22, 23, 24,
-+   19, 25,  0, 26, 27, 19, 19, 28, 29, 30,  0, 31,  0,  0,  0,  8,
-+    0,  0,  0,  0,  0,  0,  0, 19, 28,  0, 32, 33,  9, 34, 35, 19,
-+    0,  0, 36, 37, 38, 39, 40, 19,  0, 41, 42, 43, 44, 31,  0,  1,
-+   45, 42,  0,  0,  0,  0,  0, 32, 14, 14,  0,  0,  0,  0, 14,  0,
-+    0, 46, 47, 47, 47, 47, 48, 49, 47, 47, 47, 47, 50, 51, 52, 53,
-+   43, 21,  0,  0,  0,  0,  0,  0,  0, 54,  6, 55,  0, 14, 19,  1,
-+    0,  0,  0, 19, 56, 31,  0,  0,  0,  0,  0,  0,  0, 57, 14,  0,
-+    0,  0,  0,  1,  0,  2,  0,  0,  0,  3,  0,  0,  0, 58, 59,  0,
-+    0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  2,  3,  0,  4,
-+    5,  0,  0,  6,  0,  0,  0,  7,  0,  0,  0,  1,  1,  0,  0,  8,
-+    9,  0,  8,  9,  0,  0,  0,  0,  8,  9, 10, 11, 12,  0,  0,  0,
-+   13,  0,  0,  0,  0, 14, 15, 16, 17,  0,  0,  0,  1,  0,  0, 18,
-+   19,  0,  0,  0, 20,  0,  0,  0,  1,  1,  1,  1,  0,  1,  1,  1,
-+    1,  1,  1,  1,  0,  8, 21,  9,  0,  0, 22,  0,  0,  0,  0,  1,
-+    0, 23, 24, 25,  0,  0, 26,  0,  0,  0,  8, 21, 27,  0,  1,  0,
-+    0,  1,  1,  1,  1,  0,  1, 28, 29, 30,  0, 31, 32, 20,  1,  1,
-+    0,  0,  0,  8, 21,  9,  1,  4,  5,  0,  0,  0, 33,  9,  0,  1,
-+    1,  1,  0,  8, 21, 21, 21, 21, 34,  1, 35, 21, 21, 21,  9, 36,
-+    0,  0, 37, 38,  1,  0, 39,  0,  0,  0,  1,  0,  1,  0,  0,  0,
-+    0,  8, 21,  9,  1,  0,  0,  0, 40,  0,  8, 21, 21, 21, 21, 21,
-+   21, 21, 21,  9,  0,  1,  1,  1,  1,  8, 21, 21, 21,  9,  0,  0,
-+    0, 41,  0, 42, 43,  0,  0,  0,  1, 44,  0,  0,  0, 45,  8,  9,
-+    1,  0,  1,  0,  1,  1,  8, 21, 21,  9,  0,  4,  5,  8,  9,  1,
-+    0,  0,  0,  1,  2,  3,  4,  5,  6,  7,  7,  8,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  9, 10, 11, 11, 11, 11, 11, 12, 12, 12,
-+   12, 13, 14, 15, 16, 17, 18, 12, 19, 12, 20, 12, 12, 12, 12, 21,
-+   22, 22, 22, 23, 12, 12, 12, 12, 24, 25, 12, 12, 26, 27, 28, 29,
-+   30, 31,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,
-+    7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7, 32,
-+   12, 33, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
-+   12, 12, 34,  0,  0,  1,  2,  2,  2,  3,  4,  5,  6,  7,  8,  9,
-+   10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
-+   26, 27, 28, 29, 30, 31, 32, 32, 33, 33, 33, 34, 35, 35, 35, 35,
-+   35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-+    2,  2, 51, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 56, 56,
-+   56, 56, 56, 56, 57, 57, 56, 56, 56, 56, 56, 56, 58, 59, 60, 61,
-+   56, 62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 56, 62, 62, 62, 62,
-+   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
-+   62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 71,
-+   62, 62, 62, 62, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 74, 74,
-+   75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 32, 32, 32, 32,
-+   32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
-+   32, 32, 32, 32, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
-+   87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 88, 89, 89, 89, 90, 89,
-+   91, 92, 93, 94, 95, 95, 96, 97, 87, 98, 99,100,101,102,103, 87,
-+  104,104,104, 87,105,106,107,108,109,110,111,112,113,114,115, 87,
-+   89, 87,116,117,118,119,120,121,122,123,124, 87,125,126, 87,127,
-+  128,129,130, 87,131,132, 87,133,134,135, 87, 87,136,137,138,139,
-+   87,140, 87, 21,141,141,141,141,141,141,141,141,141,141,141, 87,
-+   87, 87, 87, 87,142,142,142,142,142,142,142,142,142, 87, 87, 87,
-+   87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,143,143,143,143,
-+  143, 87, 87, 87,144,144,144,144,145,146,147,147, 87, 87, 87, 87,
-+  148,148,149,150,151,151,151,151,151,151,151,151,151,151,151,151,
-+  151,151,151,151,151,151,151,151,151,151, 87, 87, 87, 87, 87, 87,
-+   87, 87, 87, 87,152,153,154,155,155,155, 87, 87, 87, 87, 87, 87,
-+   87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,156,157, 87, 87,
-+   87, 87, 87, 87, 56, 56,158,159, 51, 56, 56, 87, 56, 56, 56, 56,
-+   56, 56, 56, 56,160,160,160,160,160,160, 87, 87, 87, 87, 87, 87,
-+   87, 87, 87, 87,161, 87,162, 87, 87,163, 87, 87, 87, 87, 87, 87,
-+   87, 87, 87, 87,164,164,165, 87, 87, 87, 87, 87, 56, 56, 56, 87,
-+   89, 89, 87, 87, 56, 56, 56, 56,166, 87, 56, 56, 56, 56, 56, 56,
-+   56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 87, 87, 87, 87, 87, 87,
-+   87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87,
-+   87, 87, 87, 87, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, 87, 87,
-+   87, 87, 87, 87, 56, 87,167,167,  0,  1,  2,  2,  0,  1,  2,  2,
-+    2,  3,  4,  5,  0,  0,  0,  0,  1,  2,  1,  2,  0,  0,  3,  3,
-+    4,  5,  4,  5,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  6,
-+    0,  0,  7,  0,  8,  8,  8,  8,  8,  8,  8,  9, 10, 11, 11, 11,
-+   11, 11, 12, 11, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13,
-+   13, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16, 17, 18, 19, 19,
-+   19, 19, 19, 19, 20, 21, 22, 22, 23, 24, 22, 25, 22, 22, 22, 22,
-+   22, 26, 22, 22, 27, 27, 27, 27, 27, 22, 22, 22, 28, 28, 28, 28,
-+   29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 27, 27, 22, 22, 22, 22,
-+   22, 22, 32, 22, 33, 33, 33, 33, 33, 34, 35, 33, 36, 36, 36, 36,
-+   36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38,
-+   38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40,
-+   40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42,
-+   42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44,
-+   44, 44, 44, 44, 45, 45, 45, 46, 45, 45, 45, 45, 47, 47, 47, 47,
-+   47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
-+   48, 49, 48, 48, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51,
-+   51, 51, 51, 52, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54,
-+   54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56,
-+   56, 56, 56, 56, 57, 57, 58, 58, 58, 58, 59, 58, 60, 60, 61, 62,
-+   63, 63, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 66, 67, 67, 67,
-+   67, 67, 67, 67, 67, 67, 67, 56, 56, 56, 56, 56, 68, 68, 68, 68,
-+   68, 69, 69, 69, 70, 70, 70, 70, 70, 70, 65, 65, 71, 71, 72, 72,
-+   72, 72, 72, 72, 72, 72, 72,  8,  8,  8,  8,  8, 73, 73, 73, 73,
-+   73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 76,
-+   76, 77, 77, 77, 13, 51, 51, 51, 74, 78, 79, 80,  4,  4, 81,  4,
-+    4, 82, 83, 84,  4,  4,  4, 85,  8,  8,  8,  8, 11, 11, 11, 11,
-+   11, 11, 11, 11, 86,  0,  0,  0,  0,  0,  0, 87,  0,  4,  0,  0,
-+    0,  8,  8,  8,  0,  0, 88, 89, 90,  0,  4,  4,  6,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 91, 91, 91, 91,
-+   91, 91, 91, 91, 92, 92, 92, 92, 92, 92,  4,  4, 93, 93, 93, 93,
-+   93, 93, 93, 93, 51, 51, 51, 94, 94, 94, 94, 94, 54, 54, 54, 54,
-+   54, 54, 13, 13, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
-+   95, 95, 95,  0, 96,  0, 97, 98, 99,100,100,100,100,101,102,103,
-+  103,103,103,104,105,105,105,106, 53, 53, 53, 53, 53,  0,105,105,
-+    0,  0,  0,103, 53, 53,  0,  0,  0,  0, 53,107,  0,  0,  0,  0,
-+    0,103,103,108,103,103,103,103,103,109,  0,  0, 95, 95, 95, 95,
-+    0,  0,  0,  0,110,110,110,110,110,110,110,110,110,110,110,110,
-+  110,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112,
-+   13, 13, 13, 13, 13, 13,113,113,113,113,113,113,  0,  0,114,  4,
-+    4,  4,  4,  4,115,  4,  4,  4,  4,  4,  4,  4,116,116,116,  0,
-+  117,117,117,117,118,118,118,118,118,118, 33, 33,119,119,120,121,
-+  121,121, 53, 53,122,122,122,122,123,122, 50, 50,124,124,124,124,
-+  124,124, 50, 50,125,125,125,125,125,125,126,126, 54, 54, 54,  4,
-+    4,127,128, 55, 55, 55, 55, 55,126,126,126,126,129,129,129,129,
-+  129,129,129,129,  4,130, 19, 19, 19, 22, 22, 22, 22, 22, 22, 22,
-+   22, 22, 22, 22, 22, 22, 22,131,  0, 22, 22, 22,  8,  0,132,  0,
-+    0,  0,  0, 22, 22, 22, 22, 22, 22, 22, 22,133,  0,  0,  1,  2,
-+    1,  2,134,102,103,135, 53, 53, 53, 53,  0,  0,136,136,136,136,
-+  136,136,136,136,  0,  0,  0,  0, 11, 11, 11, 11, 11,  0, 11, 11,
-+   11,  0,  0,137,138,138,139,139,139,139,140,  0,141,141,141,142,
-+  142,143,143,143,144,144,145,145,145,145,145,145,146,146,146,146,
-+  146,147,147,147,148,148,148,149,149,149,149,149,150,150,150,151,
-+  151,151,151,151,152,152,152,152,152,152,152,152,153,153,153,153,
-+  154,154,155,155,156,156,156,156,156,156,157,157,158,158,159,159,
-+  159,159,159,159,160,160,161,161,161,161,161,161,162,162,162,162,
-+  162,162,163,163,164,164,164,164,165,165,165,165,166,166,166,166,
-+  167,167,168,168,169,169,169,169,169,169,169,169,170,170,170,170,
-+  170,170,170,170,171,171,171,171,171,171,171,171,172,172,172,172,
-+  172,172,172,172,173,173,173,174,174,174,174,174,175,175,175,175,
-+  175,175,175,175,176,176,176,176,176,176,176,176,177,177,177,177,
-+  177,178,178,178,179,179,179,179,179,180,180,180,181,181,181,181,
-+  181,181,182, 44,183,183,183,183,183,183,183,183,184,184,184,185,
-+  185,185,185,185,186,186,186,187,186,186,186,186,188,188,188,188,
-+  188,188,188,188,189,189,189,189,189,189,189,189,190,190,190,190,
-+  190,190,190,190,191,191,191,191,191,191, 67, 67,192,192,192,192,
-+  192,192,192,192,193,193,193,193,193,193,193,193,194,194,194,194,
-+  194,194,194,194,195,195,195,195,195,195,195,195,196,196,196,196,
-+  196,196,196,196,197,197,197,197,197,198,198,198,198,198,198,198,
-+  199,199,199,199,200,200,200,200,200,200,200,201,201,201,201,201,
-+  201,201,201,201,202,202,202,202,202,202,203,203,203,203,203,203,
-+  203,203,203,203,204,204,204,204,204,204,204,204,205,205,205,205,
-+  205,205,205,205,206,206,206,206,206,206,206,206,207,207,207,207,
-+  207,207,207,207,113,113,113,113,113,113,113,113,113,113,113,113,
-+  208,208,208,208,209,209,209,209,209,209,209,209,210,210,210,210,
-+  210,210,210,210,211,211,211,211,211,211,211,211,212,212,212,212,
-+  212,212,212,212,212,212,212,212,212,212,213,  0,214,214,214,214,
-+  214,214,214,214,215,100,100,100,100,100,100,100,100,100,100,100,
-+  100,100,100,100,100,100,100,100,100,100,216,217,217,217,217,217,
-+  217,217,217,217,218,218,218,218,218,218,218,218,218,218,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,219,220,221,  0,222,  0,
-+    0,  0,  0,  0,223,223,223,223,223,223,223,223, 92, 92, 92, 92,
-+   92, 92, 92, 92,224,224,224,224,224,224,224,224,225,225,225,225,
-+  225,225,225,225,226,226,226,226,226,226,226,226,227,227,227,227,
-+  227,227,227,227,228,  0,  0,  0,  0,  0,  0,  0,  8,  8,  8,  8,
-+    8,  8,  8,  8,  0,  0,  0,  0,  1,  2,  2,  2,  2,  2,  3,  0,
-+    0,  0,  4,  0,  2,  2,  2,  2,  2,  3,  2,  2,  2,  2,  5,  0,
-+    2,  5,  6,  0,  7,  7,  7,  7,  8,  9,  8, 10,  8, 11,  8,  8,
-+    8,  8,  8,  8, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14,
-+   16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 17, 19, 20, 20, 20,
-+   20, 20, 20, 20, 21, 22, 21, 23, 21, 21, 24, 24, 21, 21, 21, 21,
-+   23, 21, 25,  7,  7, 26, 21, 21, 27, 21, 21, 21, 21, 21, 21, 22,
-+   28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,
-+   32, 32, 32, 32, 33, 21, 21, 21, 34, 34, 34, 34, 35, 36, 34, 34,
-+   34, 37, 34, 34, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40,
-+   41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44,
-+   45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 48,
-+   49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 52, 50, 53, 53, 53, 53,
-+   54, 54, 54, 54, 54, 54, 55, 54, 56, 56, 56, 56, 57, 57, 57, 57,
-+   58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 61,
-+   61, 61, 62, 63, 64, 64, 64, 64, 65, 65, 65, 65, 65, 66,  0,  0,
-+   67, 67, 67, 67, 68, 68, 68, 68, 69, 69, 69, 69, 70, 71, 72, 72,
-+   72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75,
-+   76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79,
-+   80, 80, 80, 80, 81, 81, 81, 81, 82, 82, 82, 82, 83,  7,  7,  7,
-+   84,  7, 85, 86,  0, 85, 87,  0,  2, 88, 89,  2,  2,  2,  2, 90,
-+   91, 88, 92,  2,  2,  2, 93,  2,  2,  2,  2, 94,  0,  0,  0, 87,
-+    1,  0,  0, 95,  0, 96, 97,  0,  4,  0,  0,  0,  0,  0,  0,  4,
-+   98, 98, 98, 98, 99, 99, 99, 99, 13, 13, 13, 13,100,100,100,100,
-+  101,101,101,101,  0,102,  0,  0,103,101,104,105,  0,  0,101,  0,
-+  106,107,107,107,107,107,107,107,107,107,108,106,109,110,110,110,
-+  110,110,110,110,110,110,111,109,112,112,112,112,113, 56, 56, 56,
-+   56, 56, 56,114,110,110,110,111,110,110,  0,  0,115,115,115,115,
-+  116,116,116,116,117,117,117,117,118,118,118,118, 97,  2,  2,  2,
-+    2,  2, 95,  2,119,119,119,119,120,120,120,120,121,121,121,121,
-+  122,122,122,122,122,122,122,123,124,124,124,124,125,125,125,125,
-+  125,125,125,126,127,127,127,127,128,128,128,128,129,129,129,129,
-+    2,  2,  3,  2,  2,130,  2,  2,131,131,131,131,132, 17, 17, 19,
-+   21, 21, 21,133,  7,  7,  7,134, 21, 21, 21, 24,  0,135,110,110,
-+  110,110,110,136,137,137,137,137,  0,  0,  0,138,139,139,139,139,
-+  140,140,140,140, 85,  0,  0,  0,141,141,141,141,142,142,142,142,
-+  143,143,143,143,144,144,144,144,145,145,145,145,146,146,146,146,
-+  147,147,147,147,148,148,148,148,149,149,149,149,150,150,150,150,
-+  151,151,151,151,152,152,152,152,153,153,153,153,154,154,154,154,
-+  155,155,155,155,156,156,156,156,157,157,157,157,158,158,158,158,
-+  159,159,159,159,160,160,160,160,161,161,161,161,162,162,162,162,
-+  163,163,163,163,164,164,164,164,165,165,165,165,166,166,166,166,
-+  167,167,167,167,168,168,168,168,169,169,169,169,170,170,170,170,
-+  171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,174,
-+  175,175,175,175,176,176,176,176,177,177,177,177,178,178,178,178,
-+  179,179,179,179,180,180,180,180,181,181,181,181,182, 46, 46, 46,
-+  183,183,183,183,184,184,184,184,185,185,185,185,186,186,186,186,
-+  186,186,187,186,188,188,188,188,189,189,189,189,190,190,190,190,
-+  191,191,191,191,192,192,192,192,193,193,193,193,194,194,194,194,
-+  195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198,
-+  199,199,199,199,200,200,200,200,201,201,201,201,202,202,202,202,
-+  203,203,203,203,204,204,204,204,205,205,205,205,206,206,206,206,
-+  207,207,207,207,208,208,208,208,209,209,209,209,210,210,210,210,
-+  211,211,211,211,212,212,212,212,213,  0,  0,  0,214,214,214,214,
-+  215,107,107,107,107,110,110,110,216,216,216,216,217,217,217,217,
-+    0,218, 87,  0,  0,  0,218,  7, 83,138,  7,  0,  0,  0,219, 87,
-+  220,220,220,220,221,221,221,221,222,222,222,222,223,223,223,223,
-+  224,224,224,224,225,  0,  0,  0,  0,  0,  0,  0,  0, 19, 19, 19,
-+   19, 19, 19, 19, 19, 19, 19,  0,  0,  0, 19,  0, 19,  0,  0,  0,
-+    0,  0, 26, 26,  1,  1,  1,  1,  9,  9,  9,  9,  0,  9,  9,  9,
-+    9,  9,  0,  9,  9,  0,  9,  0,  9,  9, 55, 55, 55, 55, 55, 55,
-+    6,  6,  6,  6,  6,  1,  1,  6,  6,  4,  4,  4,  4,  4,  4,  4,
-+    4,  0,  4,  4,  4, 14, 14, 14, 14, 14, 14, 14,  3,  3,  3,  3,
-+    3,  0,  3,  3,  0,  3,  3,  3,  3,  3,  3,  0,  3,  3,  3,  1,
-+    1,  1,  3,  3,  1,  3,  3,  3, 37, 37, 37, 37, 38, 38, 38, 38,
-+   64, 64, 64, 64, 90, 90, 90, 90, 95, 95, 95, 95,  3,  3,  0,  3,
-+    7,  7,  7,  7,  7,  1,  1,  1,  1,  7,  7,  7,  0,  0,  7,  7,
-+    5,  5,  5,  5, 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21,
-+   22, 22, 22, 22, 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20,
-+   36, 36, 36, 36, 24, 24, 24, 24, 24, 24, 24,  0, 18, 18, 18, 18,
-+   25, 25, 25, 25, 25,  0,  0,  0,  0, 25, 25, 25, 33, 33, 33, 33,
-+    8,  8,  8,  8,  8,  8,  8,  0, 12, 12, 12, 12, 30, 30, 30, 30,
-+   29, 29, 29, 29, 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35,
-+   35, 35, 35,  0,  0,  0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44,
-+   44,  0,  0,  0, 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31,
-+   32, 32,  0,  0, 32,  0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48,
-+   52, 52, 52, 52, 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91,
-+   62, 62, 62, 62, 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70,
-+   73, 73, 73, 73,  1,  1,  1,  0,  1,  0,  1,  1,  1,  0,  0,  0,
-+    0,  1,  0,  0,  1,  1,  0,  0, 19, 19,  9,  9,  9,  9,  9,  6,
-+   19,  9,  9,  9,  9,  9, 19, 19,  9,  9,  9, 19,  6, 19, 19, 19,
-+   19, 19, 19,  9,  0,  0,  0, 19,  0,  0,  9,  0,  0,  0, 19, 19,
-+   27, 27, 27, 27, 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13,
-+    0, 13,  0, 13,  0, 13, 13, 13, 13, 13,  1,  1,  1,  1, 12, 12,
-+    0, 15, 15, 15, 15, 15, 15, 15, 15,  1,  1,  0,  0, 17, 17, 17,
-+   17, 17, 17, 17, 17, 17, 17,  0, 26, 26, 26, 26, 26, 12, 12, 12,
-+   12, 12, 12,  0, 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77,
-+   79, 79, 79, 79, 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75,
-+   69, 69, 69, 69, 69, 69,  0, 69, 74, 74, 74, 74, 84, 84, 84, 84,
-+   84, 84, 84,  0, 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87,
-+   19,  9, 19, 19,  2,  2,  2,  2, 19, 19, 19,  4,  3,  3,  0,  0,
-+    1,  1,  6,  6,  0,  0, 17, 17, 17, 17,  0,  0, 49, 49, 49, 49,
-+    0,  1,  1,  1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42,
-+   41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59,
-+   40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,
-+  106,106,106,106,104,104,104,104,110,110,110,110, 47, 47, 47, 47,
-+   81, 81, 81, 81,120,120,120,120,116,116,116,116,128,128,128,128,
-+   66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, 97, 97, 97, 97,
-+   57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117,112,112,112,112,
-+   78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,122,122,122,122,
-+   89, 89, 89, 89,130,130,130,130,144,144,144,144,147,147,147,147,
-+  148,148,148,148,149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,
-+  101,101,101,101, 96, 96, 96, 96,111,111,111,111,100,100,100,100,
-+  100, 36, 36, 36,108,108,108,108,129,129,129,129,109,109,109,109,
-+  107,107,107,107,107,107,107,  1,137,137,137,137,124,124,124,124,
-+  123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126,
-+  142,142,142,142,125,125,125,125,150,150,150,150,141,141,141,141,
-+  140,140,140,140,121,121,121,121,133,133,133,133,134,134,134,134,
-+  138,138,138,138,143,143,143,143,145,145,145,145, 63, 63, 63, 63,
-+   80, 80, 80, 80,127,127,127,127,115,115,115,115,103,103,103,103,
-+  119,119,119,119,146,146,146,146, 99, 99, 99, 99,136,139,  0,  0,
-+  136,136,136,136, 17, 15, 15, 15,139,139,139,139,105,105,105,105,
-+    0,  0,  0,  1,  0,  0,  1,  1,131,131,131,131,151,151,151,151,
-+  152,152,152,152,113,113,113,113,132,132,132,132, 15,  0,  0,  0,
-+   16, 50, 84,118, 88, 89, 90, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 91,
-+   85, 85,220, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 94, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
-+   85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 15,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
-+    5,  6,  7,  8,  9, 10, 11, 12,  0,  0, 13, 14, 15, 16, 17, 18,
-+   19, 20, 21, 22,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0, 23,  0,  0, 24, 25, 26, 27, 28, 29, 30,  0,  0,
-+   31, 32,  0, 33,  0, 34,  0, 35,  0,  0,  0,  0, 36, 37, 38, 39,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0, 41, 42,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0, 43, 44,  0, 45,  0,  0,  0,  0,  0,  0, 46, 47,  0,  0,
-+    0,  0,  0, 48,  0, 49,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0, 50, 51,  0,  0,  0, 52,  0,  0, 53,  0,  0,  0,
-+    0,  0,  0,  0, 54,  0,  0,  0,  0,  0,  0,  0, 55,  0,  0,  0,
-+    0,  0,  0,  0, 56,  0,  0,  0,  0,  0,  0,  0,  0, 57,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0, 58, 59, 60, 61, 62, 63, 64, 65,  0,  0,  0,  0,
-+    0,  0, 66,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   67, 68,  0, 69, 70,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+   71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
-+   87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,
-+  103,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,104,  0,  0,  0,  0,  0,  0,105,106,  0,107,  0,  0,  0,
-+  108,  0,109,  0,110,  0,111,112,113,  0,114,  0,  0,  0,115,  0,
-+    0,  0,116,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,117,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,118,119,120,121,  0,122,123,124,125,126,  0,127,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
-+  144,145,146,147,148,149,150,151,152,153,154,155,156,157,  0,  0,
-+    0,158,159,160,161,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,162,163,  0,  0,  0,  0,  0,
-+    0,  0,164,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,165,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,166,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,167,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,168,169,  0,  0,  0,  0,170,171,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+  172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,
-+  188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,
-+  204,205,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,
-+};
-+static const uint16_t
-+_hb_ucd_u16[4800] =
-+{
-+     0,   0,   1,   2,   3,   4,   5,   6,   0,   0,   7,   8,   9,  10,  11,  12,
-+    13,  13,  13,  14,  15,  13,  13,  16,  17,  18,  19,  20,  21,  22,  13,  23,
-+    13,  13,  13,  24,  25,  11,  11,  11,  11,  26,  11,  27,  28,  29,  30,  31,
-+    32,  32,  32,  32,  32,  32,  32,  33,  34,  35,  36,  11,  37,  38,  13,  39,
-+     9,   9,   9,  11,  11,  11,  13,  13,  40,  13,  13,  13,  41,  13,  13,  13,
-+    13,  13,  13,  35,   9,  42,  11,  11,  43,  44,  32,  45,  46,  47,  47,  48,
-+    49,  50,  47,  47,  51,  32,  52,  53,  47,  47,  47,  47,  47,  54,  55,  56,
-+    57,  58,  47,  32,  59,  47,  47,  47,  47,  47,  60,  53,  61,  47,  62,  63,
-+    47,  64,  65,  66,  47,  67,  47,  47,  47,  47,  47,  47,  47,  68,  69,  32,
-+    70,  47,  47,  71,  72,  73,  74,  75,  76,  47,  47,  77,  78,  79,  80,  81,
-+    82,  47,  47,  83,  84,  85,  86,  87,  82,  47,  47,  77,  88,  47,  80,  89,
-+    90,  47,  47,  91,  92,  93,  80,  94,  95,  47,  47,  96,  97,  98,  99, 100,
-+   101,  47,  47, 102, 103, 104,  80, 105, 106,  47,  47,  91, 107, 108,  80, 109,
-+    90,  47,  47, 110, 111, 112,  80, 113, 114,  47,  47,  47, 115, 116,  99, 117,
-+    47,  47,  47, 118, 119, 120,  66,  66,  47,  47,  47, 121, 122, 123,  47,  47,
-+   124, 125, 126, 127,  47,  47,  47, 128, 129,  32,  32, 130, 131, 132,  66,  66,
-+    47,  47, 133, 134, 120, 135, 136, 137, 138, 139,   9,   9,   9,  11,  11, 140,
-+    47,  47,  47,  47,  47,  47,  47,  47,  47,  47,  47,  47,  47, 141, 142, 143,
-+    47, 144,   9,   9,   9,   9,   9, 145, 146,  47,  47,  47,  47,  47,  47,  47,
-+    47,  47,  47,  47,  47,  47, 147,  47, 148, 149,  47,  47,  47,  47, 150, 151,
-+    47, 152,  47, 153,  47, 152,  47, 152,  47,  47,  47, 154, 155, 156, 157, 143,
-+   158, 157,  47,  47, 159,  47,  47,  47, 160,  47, 161,  47,  47,  47,  47,  47,
-+    47,  47, 162, 163, 164,  47,  47,  47,  47,  47,  47,  47,  47, 165, 144, 144,
-+    47, 166,  47,  47,  47, 167, 168, 169, 157, 157, 170, 171, 172, 172, 172, 172,
-+   173,  47,  47, 174, 175, 120, 176, 177, 178,  47, 179,  61,  47,  47, 180, 181,
-+    47,  47, 182, 183, 184,  61,  47, 185,  11,   9,   9,   9,  66, 186, 187, 188,
-+    11,  11, 189,  27,  27,  27, 190, 191,  11, 192,  27,  27,  32,  32,  32,  32,
-+    13,  13,  13,  13,  13,  13,  13,  13,  13, 193,  13,  13,  13,  13,  13,  13,
-+   194, 194, 194, 194, 194, 195, 194,  11, 196, 196, 196, 197, 198, 199, 199, 198,
-+   200, 201, 202, 203, 204, 205, 206, 207, 208,  27, 209, 209, 209, 210, 211,  32,
-+   212, 213, 214, 215, 216, 143, 217, 217, 218, 219, 220, 144, 221, 222, 144, 223,
-+   224, 224, 224, 224, 224, 224, 224, 224, 225, 144, 226, 144, 144, 144, 144, 227,
-+   144, 228, 224, 229, 144, 230, 231, 144, 144, 144, 144, 144, 144, 144, 143, 143,
-+   143, 232, 144, 144, 144, 144, 233, 143, 144, 144, 144, 144, 144, 144, 144, 144,
-+   144, 144, 144, 234, 235, 144, 144, 236, 144, 144, 144, 144, 144, 144, 237, 144,
-+   144, 144, 144, 144, 144, 144, 238, 239, 143, 240, 144, 144, 241, 224, 242, 224,
-+   243, 244, 224, 224, 224, 245, 224, 246, 144, 144, 144, 224, 247, 144, 144, 144,
-+     9,   9,   9,  11,  11,  11, 248, 249,  13,  13,  13,  13,  13,  13, 250, 251,
-+    11,  11,  11,  47,  47,  47, 252, 253,  47,  47,  47,  47,  47,  47,  32,  32,
-+   254, 255, 256, 257, 258,  66,  66,  66, 259, 260, 261, 262, 263,  47,  47,  47,
-+    47, 264, 146,  47,  47,  47,  47, 265,  47, 266,  47,  47, 144, 144, 144,  47,
-+   144, 144, 267, 144, 268, 269, 144, 144, 267, 144, 144, 269, 144, 144, 144, 144,
-+    47,  47,  47,  47, 144, 144, 144, 144,  47, 270,  47,  47,  47,  47,  47,  47,
-+    47, 144, 144, 144, 144,  47,  47, 185, 271,  47,  61,  47,  13,  13, 272, 273,
-+    13, 274,  47,  47,  47,  47, 275, 276,  31, 277, 278, 279,  13,  13,  13, 280,
-+   281, 282, 283, 284, 285,   9,   9, 286, 287,  47, 288, 289,  47,  47,  47, 290,
-+   291,  47,  47, 292, 293, 157,  32, 294,  61,  47, 295,  47, 296, 297,  47,  47,
-+    70,  47,  47, 298, 299, 300, 301,  61,  47,  47, 302, 303, 304, 305,  47, 306,
-+    47,  47,  47, 307,  58, 308, 309, 310,  47,  47,  47,  11,  11, 311,  11,  11,
-+    11,  11,  11,  11,  47,  47, 312, 157, 313, 313, 313, 313, 313, 313, 313, 313,
-+   314, 314, 314, 314, 314, 314, 314, 314,  11, 315, 316,  47,  47,  47,  47,  47,
-+    47,  47,  47, 317,  31, 318,  47,  47,  47,  47,  47, 319, 320,  47,  47,  47,
-+    47,  47,  47,  47,  47,  47,  47, 321,  32, 322,  32, 323, 324, 325, 326,  47,
-+    47,  47,  47,  47,  47,  47,  47, 327, 328,   2,   3,   4,   5, 329, 330, 331,
-+    47, 332,  47,  47,  47,  47, 333, 334, 335, 143, 143, 336, 217, 217, 217, 337,
-+   338, 144, 144, 144, 144, 144, 144, 339, 340, 340, 340, 340, 340, 340, 340, 340,
-+    47,  47,  47,  47,  47,  47, 341, 143,  47,  47, 342,  47, 343,  47,  47,  60,
-+    47, 344,  47,  47,  47, 345, 217, 217,   9,   9, 145,  11,  11,  47,  47,  47,
-+    47,  47, 157,   9,   9, 145,  11,  11,  47,  47,  47,  47,  47,  47, 344,  66,
-+    47,  47,  47,  47,  47, 346,  47, 347,  47,  47, 348, 143, 143, 143,  47, 349,
-+    47, 350,  47, 344,  66,  66,  66,  66,  47,  47,  47, 351, 143, 143, 143, 143,
-+   352,  47,  47, 353, 143,  66,  47, 354,  47, 355, 143, 143, 356,  47, 357,  66,
-+    47,  47,  47, 358,  47, 359,  47, 359,  47, 358, 142, 143, 143, 143, 143, 143,
-+     9,   9,   9,   9,  11,  11,  11, 360,  47,  47, 361, 157, 157, 157, 157, 157,
-+   143, 143, 143, 143, 143, 143, 143, 143,  47, 355, 362,  47,  60, 363,  66,  66,
-+   364,  47,  47, 353, 365, 366, 367, 368, 178,  47,  47, 369, 370,  47,  47, 157,
-+    95,  47, 371, 372, 373,  47,  47, 374, 178,  47,  47, 375, 376, 377, 378, 143,
-+    47,  47, 379, 380,  32,  32,  32,  32,  47,  47, 358,  47,  47, 381, 169, 157,
-+    90,  47,  47, 110, 382, 383, 384,  32,  47,  47,  47, 385, 386, 387,  47,  47,
-+    47,  47,  47, 388, 389, 157, 157, 157,  47,  47, 390, 391, 392, 393,  32,  32,
-+    47,  47,  47, 394, 395, 157,  66,  66,  47,  47, 396, 397, 157, 157, 157, 157,
-+    47, 141, 398, 399, 144, 144, 144, 144,  47,  47, 379, 400,  66,  66,  66,  66,
-+     9,   9,   9,   9,  11,  11, 126, 401,  47,  47,  47,  47,  47, 402, 403, 404,
-+   405,  47,  47, 406, 407, 408,  47,  47, 409, 410,  66,  66,  47,  47,  47,  47,
-+    47,  47, 390, 411, 412, 126, 143, 413,  47, 152, 414, 415,  32,  32,  32,  32,
-+    47,  47,  47, 352, 416, 157,  47,  47, 417, 418, 157, 157, 157, 157, 157, 157,
-+    47,  47,  47,  47,  47,  47,  47, 419, 143, 143, 143, 143, 143, 420, 421, 422,
-+   217, 217, 217, 217, 217, 217, 217,  66,  47,  47,  47, 206, 206, 206, 206, 206,
-+    47,  47,  47,  47,  47,  47, 300,  66,  47,  47,  47,  47,  47,  47,  47, 423,
-+    47,  47,  47, 424, 425, 426, 427,  47,   9,   9,   9,   9,   9,   9,  11,  11,
-+   143, 428,  66,  66,  66,  66,  66,  66,  47,  47,  47,  47, 381, 429, 404, 404,
-+   430, 431,  27,  27,  27,  27, 432,  27,  47, 433, 206, 206, 206, 206, 206, 206,
-+   144, 144, 144, 144, 144, 144, 434, 435, 436, 144, 437, 144, 144, 144, 144, 144,
-+   144, 144, 144, 144, 438, 144, 144, 144,   9, 439,  11, 440, 441,  11, 194,   9,
-+   442, 443,   9, 444,  11,   9, 439,  11, 440, 441,  11, 194,   9, 442, 443,   9,
-+   444,  11,   9, 439,  11, 440, 441,  11, 194,   9, 442, 443,   9, 444,  11,   9,
-+   439,  11, 194,   9, 445, 446, 447, 448,  11, 449,   9, 450, 451, 452, 453,  11,
-+   454,   9, 455,  11, 456, 157, 157, 157,  32,  32,  32, 457,  32,  32, 458, 459,
-+   460, 461,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,  32,
-+    47,  47,  47, 462, 463, 144, 144, 144,  47,  47,  47,  47,  47,  47, 464, 465,
-+    47,  47,  47,  47, 348,  32,  32,  32,   9,   9, 442,  11, 466, 300,  66,  66,
-+   143, 143, 467, 468, 143, 143, 143, 143, 143, 143, 469, 143, 143, 143, 143, 143,
-+    47,  47,  47,  47,  47,  47,  47, 224, 143, 144, 144, 144, 144, 144, 144, 144,
-+   144, 144, 144, 144, 144, 144, 144, 470, 206, 206, 206, 206, 206, 206, 206, 206,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   939, 940, 941, 942, 946, 948,   0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
-+     0,1033,1040,1041,1042,1043,1047,   0,   0,1080,1081,1082,1086,1110,   0,   0,
-+  1124,1125,1126,1127,1131,1133,   0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
-+     0,1219,1226,1227,1228,1229,1233,   0,   0,1267,1268,1269,1273,1298,   0,1303,
-+   943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
-+     0,   0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
-+   991,1176, 993,1178, 994,1179,   0,   0,1004,1190,1005,1191,1006,1192,1014,1199,
-+  1007,   0,   0,   0,1016,1201,1020,1206,   0,1022,1208,1025,1211,1023,1209,   0,
-+     0,   0,   0,1032,1218,1037,1223,1035,1221,   0,   0,   0,1044,1230,1045,1231,
-+  1049,1235,   0,   0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
-+  1069,1255,1077,1264,1074,1261,   0,   0,1083,1270,1084,1271,1085,1272,1088,1275,
-+  1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310,   0,
-+  1053,1239,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1093,
-+  1280,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 949,1134,1010,
-+  1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366,   0,1320,1347,
-+  1418,1419,1323,1350,   0,   0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
-+  1202,   0,   0,   0, 987,1172,   0,   0,1031,1217,1321,1348,1322,1349,1338,1365,
-+   950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
-+  1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263,   0,   0, 997,1182,
-+     0,   0,   0,   0,   0,   0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
-+  1422,1423,1113,1301,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     8,   9,   0,  10,1425,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   0,
-+     0,   0,   0,   0,   0,1314,1427,   5,1434,1438,1443,   0,1450,   0,1455,1461,
-+  1514,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1446,1458,1468,1476,1480,1486,
-+  1517,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1489,1503,1494,1500,1508,   0,
-+     0,   0,   0,1520,1521,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1526,1528,   0,1525,   0,   0,   0,1522,   0,   0,   0,   0,1536,1532,1539,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1534,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1556,   0,   0,   0,   0,   0,   0,
-+  1548,1550,   0,1547,   0,   0,   0,1567,   0,   0,   0,   0,1558,1554,1561,   0,
-+     0,   0,   0,   0,   0,   0,1568,1569,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,1529,1551,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1523,1545,1524,1546,   0,   0,1527,1549,   0,   0,1570,1571,1530,1552,1531,1553,
-+     0,   0,1533,1555,1535,1557,1537,1559,   0,   0,1572,1573,1544,1566,1538,1560,
-+  1540,1562,1541,1563,1542,1564,   0,   0,1543,1565,   0,   0,   0,   0,   0,   0,
-+     0,   0,1606,1607,1609,1608,1610,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+  1613,   0,1611,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1612,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1620,   0,   0,   0,   0,   0,   0,
-+     0,1623,   0,   0,1624,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1614,1615,1616,1617,1618,1619,1621,1622,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1628,1629,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1625,1626,   0,1627,
-+     0,   0,   0,1634,   0,   0,1635,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1630,1631,1632,   0,   0,1633,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1639,   0,   0,1638,1640,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1636,1637,   0,   0,
-+     0,   0,   0,   0,1641,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1642,1644,1643,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,1645,   0,   0,   0,   0,   0,   0,   0,
-+  1646,   0,   0,   0,   0,   0,   0,1648,1649,   0,1647,1650,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1651,1653,1652,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1654,   0,1655,1657,1656,   0,
-+     0,   0,   0,1659,   0,   0,   0,   0,   0,   0,   0,   0,   0,1660,   0,   0,
-+     0,   0,1661,   0,   0,   0,   0,1662,   0,   0,   0,   0,1663,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1658,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1664,   0,1665,1673,   0,1674,   0,   0,   0,   0,   0,   0,   0,
-+     0,1666,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,1668,   0,   0,   0,   0,   0,   0,   0,   0,   0,1669,   0,   0,
-+     0,   0,1670,   0,   0,   0,   0,1671,   0,   0,   0,   0,1672,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,1667,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,1675,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,1676,   0,1677,   0,1678,   0,1679,   0,1680,   0,
-+     0,   0,1681,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1682,   0,1683,   0,   0,
-+  1684,1685,   0,1686,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
-+   966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
-+   989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
-+  1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
-+  1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
-+  1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
-+  1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
-+  1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
-+  1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
-+  1119,1308,1122,1311,1123,1312,1186,1260,1293,1305,   0,1394,   0,   0,   0,   0,
-+   952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
-+  1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
-+  1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
-+  1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
-+  1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
-+  1409,1414,1109,1297,1117,1306,1116,1304,1112,1300,   0,   0,   0,   0,   0,   0,
-+  1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
-+  1477,1478,1729,1731,1730,1732,   0,   0,1435,1436,1733,1735,1734,1736,   0,   0,
-+  1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
-+  1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
-+  1495,1496,1777,1779,1778,1780,   0,   0,1451,1452,1781,1783,1782,1784,   0,   0,
-+  1504,1505,1785,1788,1786,1789,1787,1790,   0,1459,   0,1791,   0,1792,   0,1793,
-+  1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
-+  1467,  21,1475,  22,1479,  23,1485,  24,1493,  27,1499,  28,1507,  29,   0,   0,
-+  1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
-+  1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
-+  1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
-+  1470,1469,1822,1474,1465,   0,1473,1825,1429,1428,1426,  12,1432,   0,  26,   0,
-+     0,1315,1823,1484,1466,   0,1483,1829,1433,  13,1437,  14,1441,1826,1827,1828,
-+  1488,1487,1513,  19,   0,   0,1492,1515,1445,1444,1442,  15,   0,1831,1832,1833,
-+  1502,1501,1516,  25,1497,1498,1506,1518,1457,1456,1454,  17,1453,1313,  11,   3,
-+     0,   0,1824,1512,1519,   0,1511,1830,1449,  16,1460,  18,1464,   4,   0,   0,
-+    30,  31,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,  20,   0,   0,   0,   2,   6,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1834,1835,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1836,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1837,1839,1838,
-+     0,   0,   0,   0,1840,   0,   0,   0,   0,1841,   0,   0,1842,   0,   0,   0,
-+     0,   0,   0,   0,1843,   0,1844,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,1845,   0,   0,1846,   0,   0,1847,   0,1848,   0,   0,   0,   0,   0,   0,
-+   937,   0,1850,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1849, 936, 938,
-+  1851,1852,   0,   0,1853,1854,   0,   0,1855,1856,   0,   0,   0,   0,   0,   0,
-+  1857,1858,   0,   0,1861,1862,   0,   0,1863,1864,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1867,1868,1869,1870,
-+  1859,1860,1865,1866,   0,   0,   0,   0,   0,   0,1871,1872,1873,1874,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,  32,  33,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1875,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1877,   0,1878,   0,
-+  1879,   0,1880,   0,1881,   0,1882,   0,1883,   0,1884,   0,1885,   0,1886,   0,
-+  1887,   0,1888,   0,   0,1889,   0,1890,   0,1891,   0,   0,   0,   0,   0,   0,
-+  1892,1893,   0,1894,1895,   0,1896,1897,   0,1898,1899,   0,1900,1901,   0,   0,
-+     0,   0,   0,   0,1876,   0,   0,   0,   0,   0,   0,   0,   0,   0,1902,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1904,   0,1905,   0,
-+  1906,   0,1907,   0,1908,   0,1909,   0,1910,   0,1911,   0,1912,   0,1913,   0,
-+  1914,   0,1915,   0,   0,1916,   0,1917,   0,1918,   0,   0,   0,   0,   0,   0,
-+  1919,1920,   0,1921,1922,   0,1923,1924,   0,1925,1926,   0,1927,1928,   0,   0,
-+     0,   0,   0,   0,1903,   0,   0,1929,1930,1931,1932,   0,   0,   0,1933,   0,
-+   710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
-+   663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
-+   810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
-+   368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
-+   811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
-+   594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
-+   313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
-+   424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
-+   193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
-+   337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
-+   683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
-+   608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
-+   479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
-+   791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
-+   377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
-+   659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
-+   153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210,   0,   0,
-+   227,   0, 379,   0,   0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604,   0,
-+   661,   0, 703,   0,   0, 735, 743,   0,   0,   0, 793, 794, 795, 808, 741, 773,
-+   118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
-+   335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
-+   549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
-+   690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623,   0,   0,
-+   102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
-+   250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
-+   370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
-+   493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
-+   591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
-+   709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
-+   847, 857,  55,  65,  66, 883, 892, 916, 822, 824,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1586,   0,1605,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1602,1603,1934,1935,1574,1575,
-+  1576,1577,1579,1580,1581,1583,1584,   0,1585,1587,1588,1589,1591,   0,1592,   0,
-+  1593,1594,   0,1595,1596,   0,1598,1599,1600,1601,1604,1582,1578,1590,1597,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1936,   0,1937,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1938,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1939,1940,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1941,1942,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1944,1943,   0,1945,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1946,1947,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1948,1949,
-+  1950,1951,1952,1953,1954,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,1955,1956,1957,1959,1958,
-+  1960,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-+   106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125,  34, 830, 130, 131,
-+   132, 137, 827,  35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152,  37,
-+   157, 158, 159, 160,  38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
-+   181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
-+   197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
-+   153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
-+   836, 837, 247, 248, 249, 246, 251,  39,  40, 253, 255, 255, 838, 257, 258, 259,
-+   261, 839, 262, 263, 301, 264,  41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
-+   278, 281, 282,  42, 283, 284, 285, 286,  43, 843,  44, 289, 290, 291, 293, 934,
-+   298, 845, 845, 621, 300, 300,  45, 852, 894, 302, 304,  46, 306, 309, 310, 312,
-+   316,  48,  47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
-+   335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
-+   358, 356,  49, 363, 365, 367, 364,  50, 369, 371, 851, 376, 386, 378,  53, 381,
-+    52,  51, 140, 141, 387, 382, 614,  78, 388, 389, 390, 394, 392, 856,  54, 399,
-+   396, 402, 404, 858, 405, 401, 407,  55, 408, 409, 410, 413, 859, 415,  56, 417,
-+   860, 418,  57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
-+   437, 441, 438, 439, 442, 443, 864, 436, 449, 450,  58, 454, 453, 865, 447, 460,
-+   866, 867, 461, 466, 465, 464,  59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
-+   483, 485, 486, 871, 488, 489, 872, 873, 495, 497,  60, 498,  61,  61, 504, 505,
-+   507, 508, 511,  62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878,  63,  64,
-+   528, 880, 879, 881, 882, 530, 531, 531, 533,  66, 534,  67,  68, 884, 536, 538,
-+   541,  69, 885, 549, 886, 887, 556, 559,  70, 561, 562, 563, 888, 889, 889, 567,
-+    71, 890, 570, 571,  72, 891, 577,  73, 581, 579, 582, 893, 587,  74, 590, 592,
-+   596,  75, 895, 896,  76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
-+   853,  77, 615, 616,  79, 617, 252, 902, 903, 854, 855, 621, 622, 731,  80, 627,
-+   626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
-+   638, 643, 644, 645, 905, 907, 906,  81, 653, 654, 656, 911, 657, 908,  82,  83,
-+   909, 910,  84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675,  85,
-+   677, 678,  86, 681, 682, 912, 685, 686,  87, 689,  36, 913, 914,  88,  89, 696,
-+   702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
-+   918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762,  90,
-+   764, 922,  91, 775, 279, 780, 923, 925,  92,  93, 785, 926,  94, 927, 787, 787,
-+   789, 928, 792,  95, 796, 797, 798, 800,  96, 929, 802, 804, 806,  97,  98, 807,
-+   930,  99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935,   0,   0,
-+};
-+static const int16_t
-+_hb_ucd_i16[92] =
-+{
-+      0,    0,    1,   -1,    2,    0,   -2,    0,    0,    2,    0,   -2,    0,   16,    0,  -16,
-+      0,    1,   -1,    0,    3,    3,    3,   -3,   -3,   -3,    0, 2016,    0, 2527, 1923, 1914,
-+   1918,    0, 2250,    0,    0,  138,    0,    7,   -7,    0,   -1,    1, 1824,    0, 2104,    0,
-+   2108, 2106,    0, 2106, 1316,    0,   -1, -138,    8,    8,    8,    0,    7,    7,   -8,   -8,
-+     -8,   -7,-1316,    1,   -1,    3,   -3,    1,    0,-1914,-1918,    0,    0,-1923,-1824,    0,
-+      0,-2016,-2104,    0,    0,-2106,-2108,-2106,-2250,    0,-2527,    0,
-+};
-+
-+static inline uint_fast8_t
-+_hb_ucd_gc (unsigned u)
-+{
-+  return u<1114112u?_hb_ucd_u8[4840+(((_hb_ucd_u8[1072+(((_hb_ucd_u16[((_hb_ucd_u8[272+(((_hb_ucd_u8[u>>1>>3>>3>>5])<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
-+}
-+static inline uint_fast8_t
-+_hb_ucd_ccc (unsigned u)
-+{
-+  return u<125259u?_hb_ucd_u8[6670+(((_hb_ucd_u8[6166+(((_hb_ucd_u8[5754+(((_hb_ucd_u8[5306+(((_hb_ucd_u8[5182+(u>>2>>2>>2>>4)])<<4)+((u>>2>>2>>2)&15u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
-+}
-+static inline unsigned
-+_hb_ucd_b4 (const uint8_t* a, unsigned i)
-+{
-+  return (a[i>>1]>>((i&1u)<<2))&15u;
-+}
-+static inline int_fast16_t
-+_hb_ucd_bmg (unsigned u)
-+{
-+  return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7538+(((_hb_ucd_u8[7314+(((_hb_ucd_u8[7218+(((_hb_ucd_b4(7154+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
-+}
-+static inline uint_fast8_t
-+_hb_ucd_sc (unsigned u)
-+{
-+  return u<918016u?_hb_ucd_u8[11048+(((_hb_ucd_u8[10132+(((_hb_ucd_u8[8788+(((_hb_ucd_u8[8228+(((_hb_ucd_u8[7778+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
-+}
-+static inline uint_fast16_t
-+_hb_ucd_dm (unsigned u)
-+{
-+  return u<195102u?_hb_ucd_u16[1504+(((_hb_ucd_u8[12048+(((_hb_ucd_b4(11952+_hb_ucd_u8,u>>4>>6))<<6)+((u>>4)&63u))])<<4)+((u)&15u))]:0;
- }
- 
- #endif
- 
- 
- #endif /* HB_UCD_TABLE_HH */
- 
- /* == End of generated table == */
-diff --git a/gfx/harfbuzz/src/hb-ucd.cc b/gfx/harfbuzz/src/hb-ucd.cc
---- a/gfx/harfbuzz/src/hb-ucd.cc
-+++ b/gfx/harfbuzz/src/hb-ucd.cc
-@@ -109,59 +109,96 @@ static inline bool
- static int
- _cmp_pair (const void *_key, const void *_item)
- {
-   uint64_t& a = * (uint64_t*) _key;
-   uint64_t b = (* (uint64_t*) _item) & HB_CODEPOINT_ENCODE3(0x1FFFFFu, 0x1FFFFFu, 0);
- 
-   return a < b ? -1 : a > b ? +1 : 0;
- }
-+static int
-+_cmp_pair_11_7_14 (const void *_key, const void *_item)
-+{
-+  uint32_t& a = * (uint32_t*) _key;
-+  uint32_t b = (* (uint32_t*) _item) & HB_CODEPOINT_ENCODE3_11_7_14(0x1FFFFFu, 0x1FFFFFu, 0);
-+
-+  return a < b ? -1 : a > b ? +1 : 0;
-+}
- 
- static hb_bool_t
- hb_ucd_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
- 		hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab,
- 		void *user_data HB_UNUSED)
- {
-   if (_hb_ucd_compose_hangul (a, b, ab)) return true;
- 
--  uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
--  uint64_t *v = (uint64_t*) hb_bsearch (&k, _hb_ucd_dm2_map,
--					ARRAY_LENGTH (_hb_ucd_dm2_map),
--					sizeof (*_hb_ucd_dm2_map),
--					_cmp_pair);
--  if (likely (!v)) return false;
-+  hb_codepoint_t u = 0;
- 
--  hb_codepoint_t u = HB_CODEPOINT_DECODE3_3 (*v);
-+  if ((a & 0xFFFFF800u) == 0x0000u && (b & 0xFFFFFF80) == 0x0300u)
-+  {
-+    uint32_t k = HB_CODEPOINT_ENCODE3_11_7_14 (a, b, 0);
-+    uint32_t *v = (uint32_t*) hb_bsearch (&k, _hb_ucd_dm2_u32_map,
-+					  ARRAY_LENGTH (_hb_ucd_dm2_u32_map),
-+					  sizeof (*_hb_ucd_dm2_u32_map),
-+					  _cmp_pair_11_7_14);
-+    if (likely (!v)) return false;
-+    u = HB_CODEPOINT_DECODE3_11_7_14_3 (*v);
-+  }
-+  else
-+  {
-+    uint64_t k = HB_CODEPOINT_ENCODE3 (a, b, 0);
-+    uint64_t *v = (uint64_t*) hb_bsearch (&k, _hb_ucd_dm2_u64_map,
-+					  ARRAY_LENGTH (_hb_ucd_dm2_u64_map),
-+					  sizeof (*_hb_ucd_dm2_u64_map),
-+					  _cmp_pair);
-+    if (likely (!v)) return false;
-+    u = HB_CODEPOINT_DECODE3_3 (*v);
-+  }
-+
-   if (unlikely (!u)) return false;
--
-   *ab = u;
-   return true;
- }
- 
- static hb_bool_t
- hb_ucd_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
- 		  hb_codepoint_t ab, hb_codepoint_t *a, hb_codepoint_t *b,
- 		  void *user_data HB_UNUSED)
- {
-   if (_hb_ucd_decompose_hangul (ab, a, b)) return true;
- 
-   unsigned i = _hb_ucd_dm (ab);
- 
-   if (likely (!i)) return false;
-   i--;
- 
--  if (i < ARRAY_LENGTH (_hb_ucd_dm1_map))
-+  if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map))
-   {
--    *a = _hb_ucd_dm1_map[i];
-+    if (i < ARRAY_LENGTH (_hb_ucd_dm1_p0_map))
-+      *a = _hb_ucd_dm1_p0_map[i];
-+    else
-+    {
-+      i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map);
-+      *a = 0x20000 | _hb_ucd_dm1_p2_map[i];
-+    }
-     *b = 0;
-     return true;
-   }
--  i -= ARRAY_LENGTH (_hb_ucd_dm1_map);
-+  i -= ARRAY_LENGTH (_hb_ucd_dm1_p0_map) + ARRAY_LENGTH (_hb_ucd_dm1_p2_map);
- 
--  uint64_t v = _hb_ucd_dm2_map[i];
-+  if (i < ARRAY_LENGTH (_hb_ucd_dm2_u32_map))
-+  {
-+    uint32_t v = _hb_ucd_dm2_u32_map[i];
-+    *a = HB_CODEPOINT_DECODE3_11_7_14_1 (v);
-+    *b = HB_CODEPOINT_DECODE3_11_7_14_2 (v);
-+    return true;
-+  }
-+  i -= ARRAY_LENGTH (_hb_ucd_dm2_u32_map);
-+
-+  uint64_t v = _hb_ucd_dm2_u64_map[i];
-   *a = HB_CODEPOINT_DECODE3_1 (v);
-   *b = HB_CODEPOINT_DECODE3_2 (v);
-   return true;
- }
- 
- 
- #if HB_USE_ATEXIT
- static void free_static_ucd_funcs ();
-diff --git a/gfx/harfbuzz/src/hb-unicode.hh b/gfx/harfbuzz/src/hb-unicode.hh
---- a/gfx/harfbuzz/src/hb-unicode.hh
-+++ b/gfx/harfbuzz/src/hb-unicode.hh
-@@ -321,21 +321,21 @@ DECLARE_NULL_INSTANCE (hb_unicode_funcs_
- 
- /* Syriac */
- #define HB_MODIFIED_COMBINING_CLASS_CCC36 36 /* superscript alaph */
- 
- /* Telugu
-  *
-  * Modify Telugu length marks (ccc=84, ccc=91).
-  * These are the only matras in the main Indic scripts range that have
-- * a non-zero ccc.  That makes them reorder with the Halant that is
-- * ccc=9.  Just zero them, we don't need them in our Indic shaper.
-+ * a non-zero ccc.  That makes them reorder with the Halant (ccc=9).
-+ * Assign 5 and 6, which are otherwise unassigned.
-  */
--#define HB_MODIFIED_COMBINING_CLASS_CCC84 0 /* length mark */
--#define HB_MODIFIED_COMBINING_CLASS_CCC91 0 /* ai length mark */
-+#define HB_MODIFIED_COMBINING_CLASS_CCC84 5 /* length mark */
-+#define HB_MODIFIED_COMBINING_CLASS_CCC91 6 /* ai length mark */
- 
- /* Thai
-  *
-  * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9).
-  * Assign 3, which is unassigned otherwise.
-  * Uniscribe does this reordering too.
-  */
- #define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */
-diff --git a/gfx/harfbuzz/src/hb-uniscribe.cc b/gfx/harfbuzz/src/hb-uniscribe.cc
---- a/gfx/harfbuzz/src/hb-uniscribe.cc
-+++ b/gfx/harfbuzz/src/hb-uniscribe.cc
-@@ -20,22 +20,29 @@
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  *
-  * Google Author(s): Behdad Esfahbod
-  */
- 
- #include "hb.hh"
-+
-+#ifdef HAVE_UNISCRIBE
-+
- #include "hb-shaper-impl.hh"
- 
- #include <windows.h>
- #include <usp10.h>
- #include <rpc.h>
- 
-+#ifndef E_NOT_SUFFICIENT_BUFFER
-+#define E_NOT_SUFFICIENT_BUFFER HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER)
-+#endif
-+
- #include "hb-uniscribe.h"
- 
- #include "hb-open-file.hh"
- #include "hb-ot-name-table.hh"
- #include "hb-ot-layout.h"
- 
- 
- /**
-@@ -712,17 +719,17 @@ hb_bool_t
-       range->props.potfRecords = (OPENTYPE_FEATURE_RECORD *) feature_records + reinterpret_cast<uintptr_t> (range->props.potfRecords);
-     }
-   }
- 
- #define FAIL(...) \
-   HB_STMT_START { \
-     DEBUG_MSG (UNISCRIBE, nullptr, __VA_ARGS__); \
-     return false; \
--  } HB_STMT_END;
-+  } HB_STMT_END
- 
-   HRESULT hr;
- 
- retry:
- 
-   unsigned int scratch_size;
-   hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
- 
-@@ -1014,8 +1021,9 @@ retry:
- 
-   buffer->unsafe_to_break_all ();
- 
-   /* Wow, done! */
-   return true;
- }
- 
- 
-+#endif
-diff --git a/gfx/harfbuzz/src/hb-version.h b/gfx/harfbuzz/src/hb-version.h
---- a/gfx/harfbuzz/src/hb-version.h
-+++ b/gfx/harfbuzz/src/hb-version.h
-@@ -33,19 +33,19 @@
- 
- #include "hb-common.h"
- 
- HB_BEGIN_DECLS
- 
- 
- #define HB_VERSION_MAJOR 2
- #define HB_VERSION_MINOR 5
--#define HB_VERSION_MICRO 1
-+#define HB_VERSION_MICRO 3
- 
--#define HB_VERSION_STRING "2.5.1"
-+#define HB_VERSION_STRING "2.5.3"
- 
- #define HB_VERSION_ATLEAST(major,minor,micro) \
- 	((major)*10000+(minor)*100+(micro) <= \
- 	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
- 
- 
- HB_EXTERN void
- hb_version (unsigned int *major,
-diff --git a/gfx/harfbuzz/src/hb.hh b/gfx/harfbuzz/src/hb.hh
---- a/gfx/harfbuzz/src/hb.hh
-+++ b/gfx/harfbuzz/src/hb.hh
-@@ -61,17 +61,17 @@
- #endif
- 
- /* Error.  Should never happen. */
- #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR
- #pragma GCC diagnostic error   "-Wc++11-narrowing"
- #pragma GCC diagnostic error   "-Wcast-align"
- #pragma GCC diagnostic error   "-Wcast-function-type"
- #pragma GCC diagnostic error   "-Wdelete-non-virtual-dtor"
--#pragma GCC diagnostic error   "-Wdouble-promotion"
-+#pragma GCC diagnostic error   "-Wembedded-directive"
- #pragma GCC diagnostic error   "-Wextra-semi-stmt"
- #pragma GCC diagnostic error   "-Wformat-security"
- #pragma GCC diagnostic error   "-Wimplicit-function-declaration"
- #pragma GCC diagnostic error   "-Winit-self"
- #pragma GCC diagnostic error   "-Winjected-class-name"
- #pragma GCC diagnostic error   "-Wmissing-braces"
- #pragma GCC diagnostic error   "-Wmissing-declarations"
- #pragma GCC diagnostic error   "-Wmissing-prototypes"
-@@ -94,16 +94,17 @@
- #pragma GCC diagnostic error   "-Wwrite-strings"
- #endif
- 
- /* Warning.  To be investigated if happens. */
- #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING
- #pragma GCC diagnostic warning "-Wbuiltin-macro-redefined"
- #pragma GCC diagnostic warning "-Wdeprecated"
- #pragma GCC diagnostic warning "-Wdisabled-optimization"
-+#pragma GCC diagnostic warning "-Wdouble-promotion"
- #pragma GCC diagnostic warning "-Wformat=2"
- #pragma GCC diagnostic warning "-Wignored-pragma-optimize"
- #pragma GCC diagnostic warning "-Wlogical-op"
- #pragma GCC diagnostic warning "-Wmaybe-uninitialized"
- #pragma GCC diagnostic warning "-Wmissing-format-attribute"
- #pragma GCC diagnostic warning "-Wundef"
- #endif
- 
-@@ -178,18 +179,25 @@
- #include <stddef.h>
- #include <string.h>
- #include <assert.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdarg.h>
- 
- #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__)
-+#ifdef __MINGW32_VERSION
-+#ifndef WIN32_LEAN_AND_MEAN
-+#define WIN32_LEAN_AND_MEAN 1
-+#endif
-+#include <windows.h>
-+#else
- #include <intrin.h>
- #endif
-+#endif
- 
- #define HB_PASTE1(a,b) a##b
- #define HB_PASTE(a,b) HB_PASTE1(a,b)
- 
- 
- /* Compile-time custom allocator support. */
- 
- #if defined(hb_malloc_impl) \
-@@ -199,24 +207,16 @@
- extern "C" void* hb_malloc_impl(size_t size);
- extern "C" void* hb_calloc_impl(size_t nmemb, size_t size);
- extern "C" void* hb_realloc_impl(void *ptr, size_t size);
- extern "C" void  hb_free_impl(void *ptr);
- #define malloc hb_malloc_impl
- #define calloc hb_calloc_impl
- #define realloc hb_realloc_impl
- #define free hb_free_impl
--
--#ifdef hb_memalign_impl
--extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
--#define posix_memalign hb_memalign_impl
--#else
--#undef HAVE_POSIX_MEMALIGN
--#endif
--
- #endif
- 
- 
- /*
-  * Compiler attributes
-  */
- 
- #if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__)
-@@ -347,17 +347,17 @@ extern "C" int hb_memalign_impl(void **m
- 
- #  if defined(_WIN32_WCE)
-      /* Some things not defined on Windows CE. */
- #    define vsnprintf _vsnprintf
- #    ifndef HB_NO_GETENV
- #      define HB_NO_GETENV
- #    endif
- #    if _WIN32_WCE < 0x800
--#      define setlocale(Category, Locale) "C"
-+#      define HB_NO_SETLOCALE
- static int errno = 0; /* Use something better? */
- #    endif
- #  elif defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
- #    ifndef HB_NO_GETENV
- #      define HB_NO_GETENV
- #    endif
- #  endif
- #  if defined(_MSC_VER) && _MSC_VER < 1900
-@@ -431,48 +431,16 @@ static_assert ((sizeof (hb_var_int_t) ==
-   TypeName(const TypeName&) = delete; \
-   void operator=(const TypeName&) = delete
- #define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \
-   TypeName() = delete; \
-   TypeName(const TypeName&) = delete; \
-   void operator=(const TypeName&) = delete
- 
- 
--/*
-- * Compiler-assisted vectorization parameters.
-- */
--
--/*
-- * Disable vectorization for now.  To correctly use them, we should
-- * use posix_memalign() to allocate in hb_vector_t.  Otherwise, can
-- * cause misaligned access.
-- *
-- * https://bugs.chromium.org/p/chromium/issues/detail?id=860184
-- */
--#ifndef HB_VECTOR_SIZE
--#  define HB_VECTOR_SIZE 0
--#endif
--
--/* The `vector_size' attribute was introduced in gcc 3.1. */
--#ifndef HB_VECTOR_SIZE
--#  if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
--#    define HB_VECTOR_SIZE 128
--#  else
--#    define HB_VECTOR_SIZE 0
--#  endif
--#endif
--static_assert (0 == (HB_VECTOR_SIZE & (HB_VECTOR_SIZE - 1)), "HB_VECTOR_SIZE is not power of 2.");
--static_assert (0 == (HB_VECTOR_SIZE % 64), "HB_VECTOR_SIZE is not multiple of 64.");
--#if HB_VECTOR_SIZE
--typedef uint64_t hb_vector_size_impl_t __attribute__((vector_size (HB_VECTOR_SIZE / 8)));
--#else
--typedef uint64_t hb_vector_size_impl_t;
--#endif
--
--
- /* Flags */
- 
- /* Enable bitwise ops on enums marked as flags_t */
- /* To my surprise, looks like the function resolver is happy to silently cast
-  * one enum to another...  So this doesn't provide the type-checking that I
-  * originally had in mind... :(.
-  *
-  * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163
-@@ -503,56 +471,16 @@ typedef uint64_t hb_vector_size_impl_t;
- #define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x)))
- #define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0)
- 
- 
- /* Size signifying variable-sized array */
- #define VAR 1
- 
- 
--/* fallback for round() */
--static inline double
--_hb_round (double x)
--{
--  if (x >= 0)
--    return floor (x + 0.5);
--  else
--    return ceil (x - 0.5);
--}
--#if !defined (HAVE_ROUND) && !defined (HAVE_DECL_ROUND)
--#define round(x) _hb_round(x)
--#endif
--
--
--/* fallback for posix_memalign() */
--static inline int
--_hb_memalign(void **memptr, size_t alignment, size_t size)
--{
--  if (unlikely (0 != (alignment & (alignment - 1)) ||
--		!alignment ||
--		0 != (alignment & (sizeof (void *) - 1))))
--    return EINVAL;
--
--  char *p = (char *) malloc (size + alignment - 1);
--  if (unlikely (!p))
--    return ENOMEM;
--
--  size_t off = (size_t) p & (alignment - 1);
--  if (off)
--    p += alignment - off;
--
--  *memptr = (void *) p;
--
--  return 0;
--}
--#if !defined(posix_memalign) && !defined(HAVE_POSIX_MEMALIGN)
--#define posix_memalign _hb_memalign
--#endif
--
--
- /*
-  * Big-endian integers.  Here because fundamental.
-  */
- 
- template <typename Type, int Bytes> struct BEInt;
- 
- template <typename Type>
- struct BEInt<Type, 1>
-diff --git a/gfx/harfbuzz/src/main.cc b/gfx/harfbuzz/src/main.cc
---- a/gfx/harfbuzz/src/main.cc
-+++ b/gfx/harfbuzz/src/main.cc
-@@ -33,16 +33,20 @@
- #include <glib.h>
- #endif
- #include <stdlib.h>
- #include <stdio.h>
- 
- 
- using namespace OT;
- 
-+#ifdef HB_NO_OPEN
-+#define hb_blob_create_from_file(x)  hb_blob_get_empty ()
-+#endif
-+
- int
- main (int argc, char **argv)
- {
-   if (argc != 2) {
-     fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
-     exit (1);
-   }
- 
-diff --git a/gfx/harfbuzz/src/moz.build b/gfx/harfbuzz/src/moz.build
---- a/gfx/harfbuzz/src/moz.build
-+++ b/gfx/harfbuzz/src/moz.build
-@@ -96,14 +96,15 @@ if CONFIG['CC_TYPE'] == 'clang-cl':
-     CXXFLAGS += ['-Wno-unused-variable']
- 
- FINAL_LIBRARY = 'gkmedias'
- 
- DEFINES['PACKAGE_VERSION'] = '"moz"'
- DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
- DEFINES['HAVE_OT'] = 1
- DEFINES['HAVE_ROUND'] = 1
-+DEFINES['HB_NO_FALLBACK_SHAPE'] = True
- DEFINES['HB_NO_MT'] = True
- DEFINES['HB_NO_UCD'] = True
- DEFINES['HB_NO_UNICODE_FUNCS'] = True
- # Cancel the effect of the -DDEBUG macro if present,
- # because harfbuzz uses that name for its own purposes
- DEFINES['DEBUG'] = False
-diff --git a/gfx/harfbuzz/src/test-buffer-serialize.cc b/gfx/harfbuzz/src/test-buffer-serialize.cc
---- a/gfx/harfbuzz/src/test-buffer-serialize.cc
-+++ b/gfx/harfbuzz/src/test-buffer-serialize.cc
-@@ -29,19 +29,27 @@
- #include "hb.h"
- #include "hb-ot.h"
- #ifdef HAVE_FREETYPE
- #include "hb-ft.h"
- #endif
- 
- #include <stdio.h>
- 
-+#ifdef HB_NO_OPEN
-+#define hb_blob_create_from_file(x)  hb_blob_get_empty ()
-+#endif
-+
- int
- main (int argc, char **argv)
- {
-+  bool ret = true;
-+
-+#ifndef HB_NO_BUFFER_SERIALIZE
-+
-   if (argc != 2) {
-     fprintf (stderr, "usage: %s font-file\n", argv[0]);
-     exit (1);
-   }
- 
-   hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
-   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
-   hb_blob_destroy (blob);
-@@ -54,17 +62,16 @@ main (int argc, char **argv)
-   hb_ot_font_set_funcs (font);
- #ifdef HAVE_FREETYPE
-   //hb_ft_font_set_funcs (font);
- #endif
- 
-   hb_buffer_t *buf;
-   buf = hb_buffer_create ();
- 
--  bool ret = true;
-   char line[BUFSIZ], out[BUFSIZ];
-   while (fgets (line, sizeof(line), stdin) != nullptr)
-   {
-     hb_buffer_clear_contents (buf);
- 
-     const char *p = line;
-     while (hb_buffer_deserialize_glyphs (buf,
- 					 p, -1, &p,
-@@ -80,10 +87,12 @@ main (int argc, char **argv)
- 				HB_BUFFER_SERIALIZE_FLAG_DEFAULT);
-     puts (out);
-   }
- 
-   hb_buffer_destroy (buf);
- 
-   hb_font_destroy (font);
- 
-+#endif
-+
-   return !ret;
- }
-diff --git a/gfx/harfbuzz/src/test-gpos-size-params.cc b/gfx/harfbuzz/src/test-gpos-size-params.cc
---- a/gfx/harfbuzz/src/test-gpos-size-params.cc
-+++ b/gfx/harfbuzz/src/test-gpos-size-params.cc
-@@ -26,29 +26,38 @@
- 
- #include "hb.hh"
- 
- #include "hb.h"
- #include "hb-ot.h"
- 
- #include <stdio.h>
- 
-+#ifdef HB_NO_OPEN
-+#define hb_blob_create_from_file(x)  hb_blob_get_empty ()
-+#endif
-+
- int
- main (int argc, char **argv)
- {
-   if (argc != 2) {
-     fprintf (stderr, "usage: %s font-file\n", argv[0]);
-     exit (1);
-   }
- 
-   /* Create the face */
-   hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
-   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
-   hb_blob_destroy (blob);
-   blob = nullptr;
- 
-+  bool ret = true;
-+
-+#ifndef HB_NO_LAYOUT_FEATURE_PARAMS
-   unsigned int p[5];
--  bool ret = hb_ot_layout_get_size_params (face, p, p+1, (p+2), p+3, p+4);
-+  ret = hb_ot_layout_get_size_params (face, p, p+1, (p+2), p+3, p+4);
-+  printf ("%g %u %u %g %g\n", p[0]/10., p[1], p[2], p[3]/10., p[4]/10.);
-+#endif
- 
--  printf ("%g %u %u %g %g\n", p[0]/10., p[1], p[2], p[3]/10., p[4]/10.);
-+  hb_face_destroy (face);
- 
-   return !ret;
- }
-diff --git a/gfx/harfbuzz/src/test-gsub-would-substitute.cc b/gfx/harfbuzz/src/test-gsub-would-substitute.cc
---- a/gfx/harfbuzz/src/test-gsub-would-substitute.cc
-+++ b/gfx/harfbuzz/src/test-gsub-would-substitute.cc
-@@ -30,16 +30,20 @@
- #include "hb-ot.h"
- 
- #include <stdio.h>
- 
- #ifdef HAVE_FREETYPE
- #include "hb-ft.h"
- #endif
- 
-+#ifdef HB_NO_OPEN
-+#define hb_blob_create_from_file(x)  hb_blob_get_empty ()
-+#endif
-+
- int
- main (int argc, char **argv)
- {
-   if (argc != 4 && argc != 5) {
-     fprintf (stderr, "usage: %s font-file lookup-index first-glyph [second-glyph]\n", argv[0]);
-     exit (1);
-   }
- 
-diff --git a/gfx/harfbuzz/src/test-ot-color.cc b/gfx/harfbuzz/src/test-ot-color.cc
---- a/gfx/harfbuzz/src/test-ot-color.cc
-+++ b/gfx/harfbuzz/src/test-ot-color.cc
-@@ -18,26 +18,34 @@
-  *
-  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
-  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
-  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
-  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-  */
- 
--#include "hb.h"
-+#include "hb.hh"
-+
-+#include <cairo.h>
-+
-+#ifdef HB_NO_OPEN
-+#define hb_blob_create_from_file(x)  hb_blob_get_empty ()
-+#endif
-+
-+#if !defined(HB_NO_COLOR) && defined(CAIRO_HAS_SVG_SURFACE)
-+
- #include "hb-ot.h"
- 
- #include "hb-ft.h"
- 
- #include <ft2build.h>
- #include FT_FREETYPE_H
- #include FT_GLYPH_H
- 
--#include <cairo.h>
- #include <cairo-ft.h>
- #include <cairo-svg.h>
- 
- #include <stdlib.h>
- #include <stdio.h>
- 
- static void
- svg_dump (hb_face_t *face, unsigned int face_index)
-@@ -128,17 +136,17 @@ png_dump (hb_face_t *face, unsigned int 
- static void
- layered_glyph_dump (hb_face_t *face, cairo_font_face_t *cairo_face, unsigned int face_index)
- {
-   unsigned int upem = hb_face_get_upem (face);
- 
-   unsigned glyph_count = hb_face_get_glyph_count (face);
-   for (hb_codepoint_t gid = 0; gid < glyph_count; ++gid)
-   {
--    unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, NULL, NULL);
-+    unsigned int num_layers = hb_ot_color_glyph_get_layers (face, gid, 0, nullptr, nullptr);
-     if (!num_layers)
-       continue;
- 
-     hb_ot_color_layer_t *layers = (hb_ot_color_layer_t*) malloc (num_layers * sizeof (hb_ot_color_layer_t));
- 
-     hb_ot_color_glyph_get_layers (face, gid, 0, &num_layers, layers);
-     if (num_layers)
-     {
-@@ -164,17 +172,17 @@ layered_glyph_dump (hb_face_t *face, cai
-       extents.height += extents.height / 10;
-       extents.x_bearing -= extents.width / 20;
-       extents.y_bearing -= extents.height / 20;
- 
-       // Render
-       unsigned int palette_count = hb_ot_color_palette_get_count (face);
-       for (unsigned int palette = 0; palette < palette_count; palette++)
-       {
--	unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, NULL, NULL);
-+	unsigned int num_colors = hb_ot_color_palette_get_colors (face, palette, 0, nullptr, nullptr);
- 	if (!num_colors)
- 	  continue;
- 
- 	hb_color_t *colors = (hb_color_t*) calloc (num_colors, sizeof (hb_color_t));
- 	hb_ot_color_palette_get_colors (face, palette, 0, &num_colors, colors);
- 	if (num_colors)
- 	{
- 	  char output_path[255];
-@@ -266,24 +274,24 @@ main (int argc, char **argv)
-     fprintf (stderr, "usage: %s font-file.ttf\n"
- 		     "run it like `rm -rf out && mkdir out && %s font-file.ttf`\n",
- 		     argv[0], argv[0]);
-     exit (1);
-   }
- 
- 
-   FILE *font_name_file = fopen ("out/.dumped_font_name", "r");
--  if (font_name_file != NULL)
-+  if (font_name_file != nullptr)
-   {
-     fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n");
-     exit (1);
-   }
- 
-   font_name_file = fopen ("out/.dumped_font_name", "w");
--  if (font_name_file == NULL)
-+  if (font_name_file == nullptr)
-   {
-     fprintf (stderr, "./out is not accessible as a folder, create it please\n");
-     exit (1);
-   }
-   fwrite (argv[1], 1, strlen (argv[1]), font_name_file);
-   fclose (font_name_file);
- 
-   hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
-@@ -329,8 +337,12 @@ main (int argc, char **argv)
-     hb_font_destroy (font);
-     hb_face_destroy (face);
-     }
- 
-   hb_blob_destroy (blob);
- 
-   return 0;
- }
-+
-+#else
-+int main (int argc, char **argv) { return 0; }
-+#endif
-diff --git a/gfx/harfbuzz/src/test-ot-name.cc b/gfx/harfbuzz/src/test-ot-name.cc
---- a/gfx/harfbuzz/src/test-ot-name.cc
-+++ b/gfx/harfbuzz/src/test-ot-name.cc
-@@ -25,30 +25,36 @@
-  */
- 
- #include "hb.hh"
- #include "hb-ot.h"
- 
- #include <stdlib.h>
- #include <stdio.h>
- 
-+#ifdef HB_NO_OPEN
-+#define hb_blob_create_from_file(x)  hb_blob_get_empty ()
-+#endif
-+
- int
- main (int argc, char **argv)
- {
-   if (argc != 2) {
-     fprintf (stderr, "usage: %s font-file\n", argv[0]);
-     exit (1);
-   }
- 
-   hb_blob_t *blob = hb_blob_create_from_file (argv[1]);
-   hb_face_t *face = hb_face_create (blob, 0 /* first face */);
-   hb_blob_destroy (blob);
-   blob = nullptr;
- 
--  unsigned int count;
-+  unsigned int count = 0;
-+
-+#ifndef HB_NO_NAME
-   const hb_ot_name_entry_t *entries = hb_ot_name_list_names (face, &count);
- 
-   for (unsigned int i = 0; i < count; i++)
-   {
-     printf ("%u	%s	",
- 	    entries[i].name_id,
- 	    hb_language_to_string (entries[i].language));
- 
-@@ -57,13 +63,14 @@ main (int argc, char **argv)
-     hb_ot_name_get_utf8 (face,
- 			 entries[i].name_id,
- 			 entries[i].language,
- 			 &buf_size,
- 			 buf);
- 
-     printf ("%s\n", buf);
-   }
-+#endif
- 
-   hb_face_destroy (face);
- 
-   return count ? 0 : 1;
- }
-diff --git a/gfx/harfbuzz/src/test.cc b/gfx/harfbuzz/src/test.cc
---- a/gfx/harfbuzz/src/test.cc
-+++ b/gfx/harfbuzz/src/test.cc
-@@ -29,16 +29,20 @@
- #include "hb.h"
- 
- #include <stdio.h>
- 
- #ifdef HAVE_FREETYPE
- #include "hb-ft.h"
- #endif
- 
-+#ifdef HB_NO_OPEN
-+#define hb_blob_create_from_file(x)  hb_blob_get_empty ()
-+#endif
-+
- int
- main (int argc, char **argv)
- {
-   if (argc != 2) {
-     fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
-     exit (1);
-   }
- 
-diff --git a/gfx/harfbuzz/update.sh b/gfx/harfbuzz/update.sh
---- a/gfx/harfbuzz/update.sh
-+++ b/gfx/harfbuzz/update.sh
-@@ -1,16 +1,16 @@
- #!/bin/sh
- 
- # Script to update the mozilla in-tree copy of the HarfBuzz library.
- # Run this within the /gfx/harfbuzz directory of the source tree.
- 
- MY_TEMP_DIR=`mktemp -d -t harfbuzz_update.XXXXXX` || exit 1
- 
--VERSION=2.5.1
-+VERSION=2.5.3
- 
- git clone https://github.com/harfbuzz/harfbuzz ${MY_TEMP_DIR}/harfbuzz
- git -C ${MY_TEMP_DIR}/harfbuzz checkout ${VERSION}
- 
- COMMIT=$(git -C ${MY_TEMP_DIR}/harfbuzz rev-parse HEAD)
- perl -p -i -e "s/(\d+\.)(\d+\.)(\d+)/${VERSION}/" README-mozilla;
- perl -p -i -e "s/\[commit [0-9a-f]{40}\]/[commit ${COMMIT}]/" README-mozilla;
- 

+ 0 - 2355
frg/work-js/mozilla-release/patches/mozilla-central_489301.patch

@@ -1,2355 +0,0 @@
-# HG changeset patch
-# User Mike Hommey <mh+mozilla@glandium.org>
-# Date 1566390342 0
-#      Wed Aug 21 12:25:42 2019 +0000
-# Node ID 51bf6a97396d96ddb82fa91c2cf9bd9f5bc9ae06
-# Parent  3148126492b506f3bf55475aa381fbd77ac7b8f9
-Bug 1575420 - Replace MOZ_WIDGET_TOOLKIT value of "gtk3" with "gtk". r=froydnj
-
-Differential Revision: https://phabricator.services.mozilla.com/D42765
-
-diff --git a/accessible/aom/moz.build b/accessible/aom/moz.build
---- a/accessible/aom/moz.build
-+++ b/accessible/aom/moz.build
-@@ -12,17 +12,17 @@ UNIFIED_SOURCES += [
-     'AccessibleNode.cpp',
- ]
- 
- LOCAL_INCLUDES += [
-     '/accessible/base',
-     '/accessible/generic',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     LOCAL_INCLUDES += [
-         '/accessible/atk',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     LOCAL_INCLUDES += [
-         '/accessible/windows/ia2',
-         '/accessible/windows/msaa',
-     ]
-diff --git a/accessible/atk/moz.build b/accessible/atk/moz.build
---- a/accessible/atk/moz.build
-+++ b/accessible/atk/moz.build
-@@ -41,17 +41,17 @@ LOCAL_INCLUDES += [
-     '/accessible/ipc/other',
-     '/accessible/xpcom',
-     '/accessible/xul',
-     '/other-licenses/atk-1.0',
- ]
- 
- FINAL_LIBRARY = 'xul'
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CFLAGS += CONFIG['TK_CFLAGS']
-     CXXFLAGS += CONFIG['TK_CFLAGS']
- 
- if CONFIG['MOZ_ENABLE_DBUS']:
-     CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
- 
- include('/ipc/chromium/chromium-config.mozbuild')
- 
-diff --git a/accessible/base/moz.build b/accessible/base/moz.build
---- a/accessible/base/moz.build
-+++ b/accessible/base/moz.build
-@@ -85,17 +85,17 @@ LOCAL_INCLUDES += [
-     '/ipc/chromium/src',
-     '/layout/generic',
-     '/layout/style',
-     '/layout/svg',
-     '/layout/xul',
-     '/layout/xul/tree/',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     LOCAL_INCLUDES += [
-         '/accessible/atk',
-     ]
-     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     LOCAL_INCLUDES += [
-         '/accessible/windows/ia2',
-         '/accessible/windows/msaa',
-diff --git a/accessible/generic/moz.build b/accessible/generic/moz.build
---- a/accessible/generic/moz.build
-+++ b/accessible/generic/moz.build
-@@ -42,17 +42,17 @@ if CONFIG['OS_ARCH'] == 'WINNT':
-     LOCAL_INCLUDES += [
-         '/accessible/ipc/win',
-     ]
- else:
-     LOCAL_INCLUDES += [
-         '/accessible/ipc/other',
-     ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     LOCAL_INCLUDES += [
-         '/accessible/atk',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     LOCAL_INCLUDES += [
-         '/accessible/windows/ia2',
-         '/accessible/windows/msaa',
-     ]
-diff --git a/accessible/html/moz.build b/accessible/html/moz.build
---- a/accessible/html/moz.build
-+++ b/accessible/html/moz.build
-@@ -20,17 +20,17 @@ LOCAL_INCLUDES += [
-     '/accessible/generic',
-     '/accessible/xpcom',
-     '/layout/forms',
-     '/layout/generic',
-     '/layout/tables',
-     '/layout/xul',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     LOCAL_INCLUDES += [
-         '/accessible/atk',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     LOCAL_INCLUDES += [
-         '/accessible/windows/ia2',
-         '/accessible/windows/msaa',
-     ]
-diff --git a/accessible/ipc/moz.build b/accessible/ipc/moz.build
---- a/accessible/ipc/moz.build
-+++ b/accessible/ipc/moz.build
-@@ -11,17 +11,17 @@ if CONFIG['OS_ARCH'] == 'WINNT':
-         '/accessible/windows/ia2',
-         '/accessible/windows/msaa',
-     ]
- else:
-     DIRS += ['other']
-     LOCAL_INCLUDES += [
-         '/accessible/ipc/other',
-     ]
--    if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-         LOCAL_INCLUDES += [
-             '/accessible/atk',
-         ]
-     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-         LOCAL_INCLUDES += [
-             '/accessible/mac',
-         ]
-     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-diff --git a/accessible/ipc/other/moz.build b/accessible/ipc/other/moz.build
---- a/accessible/ipc/other/moz.build
-+++ b/accessible/ipc/other/moz.build
-@@ -20,17 +20,17 @@ if CONFIG['ACCESSIBILITY']:
-     ]
- 
-     LOCAL_INCLUDES += [
-         '../../base',
-         '../../generic',
-         '../../xpcom',
-     ]
- 
--    if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-         LOCAL_INCLUDES += [
-             '/accessible/atk',
-         ]
-     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-         LOCAL_INCLUDES += [
-             '/accessible/mac',
-         ]
-     elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-diff --git a/accessible/moz.build b/accessible/moz.build
---- a/accessible/moz.build
-+++ b/accessible/moz.build
-@@ -1,17 +1,17 @@
- # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
- # vim: set filetype=python:
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- 
- toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
- 
--if 'gtk' in toolkit:
-+if toolkit == 'gtk':
-     DIRS += ['atk']
- elif toolkit == 'windows':
-     DIRS += ['windows']
- elif toolkit == 'cocoa':
-     DIRS += ['mac']
- elif toolkit == 'android':
-     DIRS += ['android']
- else:
-diff --git a/accessible/xpcom/moz.build b/accessible/xpcom/moz.build
---- a/accessible/xpcom/moz.build
-+++ b/accessible/xpcom/moz.build
-@@ -30,17 +30,17 @@ EXPORTS += [
-     'xpcAccessibilityService.h',
- ]
- 
- LOCAL_INCLUDES += [
-     '/accessible/base',
-     '/accessible/generic',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     LOCAL_INCLUDES += [
-         '/accessible/atk',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     LOCAL_INCLUDES += [
-         '/accessible/windows/msaa',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-diff --git a/accessible/xul/moz.build b/accessible/xul/moz.build
---- a/accessible/xul/moz.build
-+++ b/accessible/xul/moz.build
-@@ -24,17 +24,17 @@ LOCAL_INCLUDES += [
-     '/accessible/xpcom',
-     '/dom/base',
-     '/dom/xul',
-     '/layout/generic',
-     '/layout/xul',
-     '/layout/xul/tree',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     LOCAL_INCLUDES += [
-         '/accessible/atk',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     LOCAL_INCLUDES += [
-         '/accessible/windows/ia2',
-         '/accessible/windows/msaa',
-     ]
-diff --git a/browser/base/content/browser-tabsintitlebar.js b/browser/base/content/browser-tabsintitlebar.js
---- a/browser/base/content/browser-tabsintitlebar.js
-+++ b/browser/base/content/browser-tabsintitlebar.js
-@@ -31,17 +31,17 @@ var TabsInTitlebar;
- 
-     get systemSupported() {
-       let isSupported = false;
-       switch (AppConstants.MOZ_WIDGET_TOOLKIT) {
-         case "windows":
-         case "cocoa":
-           isSupported = true;
-           break;
--        case "gtk3":
-+        case "gtk":
-           isSupported = window.matchMedia("(-moz-gtk-csd-available)").matches;
-           break;
-       }
-       delete this.systemSupported;
-       return (this.systemSupported = isSupported);
-     },
- 
-     get enabled() {
-diff --git a/browser/base/content/test/contextMenu/browser.ini b/browser/base/content/test/contextMenu/browser.ini
---- a/browser/base/content/test/contextMenu/browser.ini
-+++ b/browser/base/content/test/contextMenu/browser.ini
-@@ -18,11 +18,11 @@ skip-if = true # Bug 1424433, disable du
- support-files =
-   test_contextmenu_iframe.html
- [browser_utilityOverlay.js]
- skip-if = os == "linux" || os == "mac" #Bug 1444631
- [browser_utilityOverlayPrincipal.js]
- [browser_contextmenu_childprocess.js]
- [browser_contextmenu.js]
- tags = fullscreen clipboard
--skip-if = toolkit == "gtk3" || verify || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1531590
-+skip-if = toolkit == "gtk" || verify || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1531590
- [browser_contextmenu_input.js]
--skip-if = toolkit == "gtk3" || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1533161
-+skip-if = toolkit == "gtk" || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1533161
-diff --git a/browser/base/content/test/plugins/browser-rs-blocklist.ini b/browser/base/content/test/plugins/browser-rs-blocklist.ini
---- a/browser/base/content/test/plugins/browser-rs-blocklist.ini
-+++ b/browser/base/content/test/plugins/browser-rs-blocklist.ini
-@@ -34,17 +34,17 @@ support-files =
-   plugin_two_types.html
-   plugin_unknown.html
-   plugin_zoom.html
- 
- [browser_bug743421.js]
- [browser_bug812562.js]
- [browser_clearplugindata.js]
- [browser_CTP_context_menu.js]
--skip-if = fission || toolkit == "gtk3"   # fails intermittently on Linux (bug 909342)
-+skip-if = fission || toolkit == "gtk"   # fails intermittently on Linux (bug 909342)
- [browser_CTP_crashreporting.js]
- skip-if = !crashreporter || verify || os == 'win' # bug 1442837
- [browser_CTP_drag_drop.js]
- [browser_CTP_hide_overlay.js]
- [browser_CTP_iframe.js]
- skip-if = os == 'win' && !debug # Bug 1519868
- [browser_CTP_nonplugins.js]
- skip-if = verify
-diff --git a/browser/base/content/test/plugins/browser.ini b/browser/base/content/test/plugins/browser.ini
---- a/browser/base/content/test/plugins/browser.ini
-+++ b/browser/base/content/test/plugins/browser.ini
-@@ -52,17 +52,17 @@ fail-if = fission
- [browser_bug787619.js]
- [browser_bug797677.js]
- [browser_bug812562.js]
- tags = blocklist
- [browser_bug818118.js]
- [browser_clearplugindata.js]
- tags = blocklist
- [browser_CTP_context_menu.js]
--skip-if = fission || toolkit == "gtk3"   # fails intermittently on Linux (bug 909342)
-+skip-if = fission || toolkit == "gtk"   # fails intermittently on Linux (bug 909342)
- tags = blocklist
- [browser_CTP_crashreporting.js]
- skip-if = !crashreporter || verify || os == 'win' # bug 1442837
- tags = blocklist
- [browser_CTP_drag_drop.js]
- tags = blocklist
- [browser_CTP_favorfallback.js]
- [browser_CTP_hide_overlay.js]
-diff --git a/browser/base/moz.build b/browser/base/moz.build
---- a/browser/base/moz.build
-+++ b/browser/base/moz.build
-@@ -59,15 +59,15 @@ BROWSER_CHROME_MANIFESTS += [
-     'content/test/webrtc/browser.ini',
- ]
- 
- DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
- DEFINES['MOZ_APP_VERSION_DISPLAY'] = CONFIG['MOZ_APP_VERSION_DISPLAY']
- 
- DEFINES['APP_LICENSE_BLOCK'] = '%s/content/overrides/app-license.html' % SRCDIR
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk', 'cocoa'):
-     DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk'):
-     DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
- 
- JAR_MANIFESTS += ['jar.mn']
-diff --git a/browser/branding/branding-common.mozbuild b/browser/branding/branding-common.mozbuild
---- a/browser/branding/branding-common.mozbuild
-+++ b/browser/branding/branding-common.mozbuild
-@@ -18,16 +18,16 @@ def FirefoxBranding():
-     if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-         FINAL_TARGET_FILES['..'] += [
-             'firefox.VisualElementsManifest.xml',
-         ]
-         FINAL_TARGET_FILES.VisualElements += [
-             'VisualElements_150.png',
-             'VisualElements_70.png',
-         ]
--    elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+    elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-         FINAL_TARGET_FILES.chrome.icons.default += [
-             'default128.png',
-             'default16.png',
-             'default32.png',
-             'default48.png',
-             'default64.png',
-         ]
-diff --git a/browser/components/build/components.conf b/browser/components/build/components.conf
---- a/browser/components/build/components.conf
-+++ b/browser/components/build/components.conf
-@@ -16,17 +16,17 @@ Classes = [
- 
- TOOLKIT = buildconfig.substs['MOZ_WIDGET_TOOLKIT']
- 
- shell_service_contracts = [
-     '@mozilla.org/browser/shell-service;1',
-     '@mozilla.org/toolkit/shell-service;1',
- ]
- 
--if TOOLKIT == 'gtk3':
-+if TOOLKIT == 'gtk':
-     Classes += [
-         {
-             'cid': '{63c7b9f4-0cc8-43f8-b666-0a661655cb73}',
-             'contract_ids': shell_service_contracts,
-             'type': 'nsGNOMEShellService',
-             'headers': ['/browser/components/shell/nsGNOMEShellService.h'],
-             'init_method': 'Init',
-         },
-diff --git a/browser/components/preferences/in-content/moz.build b/browser/components/preferences/in-content/moz.build
---- a/browser/components/preferences/in-content/moz.build
-+++ b/browser/components/preferences/in-content/moz.build
-@@ -2,12 +2,12 @@
- # vim: set filetype=python:
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- 
- for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
-     DEFINES[var] = CONFIG[var]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk', 'cocoa'):
-     DEFINES['HAVE_SHELL_SERVICE'] = 1
- 
- JAR_MANIFESTS += ['jar.mn']
-diff --git a/browser/components/preferences/moz.build b/browser/components/preferences/moz.build
---- a/browser/components/preferences/moz.build
-+++ b/browser/components/preferences/moz.build
-@@ -11,15 +11,15 @@ DIRS += [
- BROWSER_CHROME_MANIFESTS += [
-     'in-content/tests/browser.ini',
-     'in-content/tests/siteData/browser.ini'
- ]
- 
- for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
-     DEFINES[var] = CONFIG[var]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk', 'cocoa'):
-     DEFINES['HAVE_SHELL_SERVICE'] = 1
- 
- JAR_MANIFESTS += ['jar.mn']
- 
- with Files('**'):
-     BUG_COMPONENT = ('Firefox', 'Preferences')
-diff --git a/browser/components/shell/moz.build b/browser/components/shell/moz.build
---- a/browser/components/shell/moz.build
-+++ b/browser/components/shell/moz.build
-@@ -21,17 +21,17 @@ XPIDL_SOURCES += [
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-     XPIDL_SOURCES += [
-         'nsIMacShellService.idl',
-     ]
- 
-     SOURCES += [
-         'nsMacShellService.cpp',
-     ]
--elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     XPIDL_SOURCES += [
-         'nsIGNOMEShellService.idl',
-     ]
- 
-     SOURCES += [
-         'nsGNOMEShellService.cpp',
-     ]
- elif CONFIG['OS_ARCH'] == 'WINNT':
-diff --git a/browser/installer/Makefile.in b/browser/installer/Makefile.in
---- a/browser/installer/Makefile.in
-+++ b/browser/installer/Makefile.in
-@@ -28,21 +28,18 @@ DEFINES += -DMOZ_APP_NAME=$(MOZ_APP_NAME
- 
- ifdef MOZ_DEBUG
- DEFINES += -DMOZ_DEBUG=1
- endif
- ifdef MOZ_LAYOUT_DEBUGGER
- DEFINES += -DMOZ_LAYOUT_DEBUGGER=1
- endif
- 
--ifneq (,$(filter gtk%,$(MOZ_WIDGET_TOOLKIT)))
-+ifeq ($(MOZ_WIDGET_TOOLKIT),gtk)
- DEFINES += -DMOZ_GTK=1
--ifeq ($(MOZ_WIDGET_TOOLKIT),gtk3)
--DEFINES += -DMOZ_GTK3=1
--endif
- endif
- 
- ifdef MOZ_SYSTEM_NSPR
- DEFINES += -DMOZ_SYSTEM_NSPR=1
- endif
- 
- ifdef MOZ_SYSTEM_NSS
- DEFINES += -DMOZ_SYSTEM_NSS=1
-diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
---- a/browser/installer/package-manifest.in
-+++ b/browser/installer/package-manifest.in
-@@ -93,17 +93,17 @@
- @BINPATH@/@MSVC_C_RUNTIME_DLL@
- @BINPATH@/@MSVC_CXX_RUNTIME_DLL@
- #endif
- #if MOZ_PACKAGE_WIN_UCRT_DLLS
- @BINPATH@/api-ms-win-*.dll
- @BINPATH@/ucrtbase.dll
- #endif
- #endif
--#ifdef MOZ_GTK3
-+#ifdef MOZ_GTK
- @BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
- @BINPATH@/gtk2/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
- #ifdef MOZ_WAYLAND
- @BINPATH@/@DLL_PREFIX@mozwayland@DLL_SUFFIX@
- #endif
- #endif
- 
- ; We don't have a complete view of which dlls to expect when doing an artifact
-diff --git a/browser/themes/moz.build b/browser/themes/moz.build
---- a/browser/themes/moz.build
-+++ b/browser/themes/moz.build
-@@ -6,17 +6,17 @@
- 
- with Files("**"):
-     BUG_COMPONENT = ("Firefox", "Theme")
- 
- toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
- 
- if toolkit == 'cocoa':
-     DIRS += ['osx']
--elif toolkit == 'gtk3':
-+elif toolkit == 'gtk':
-     DIRS += ['linux']
- else:
-     DIRS += ['windows']
- 
- DIRS += [
-     'addons/dark',
-     'addons/light',
- ]
-diff --git a/chrome/moz.build b/chrome/moz.build
---- a/chrome/moz.build
-+++ b/chrome/moz.build
-@@ -35,13 +35,13 @@ FINAL_LIBRARY = 'xul'
- LOCAL_INCLUDES += [
-     '!/xpcom',
-     '/dom/base',
-     '/netwerk/base',
-     '/netwerk/protocol/res',
-     '/xpcom/components'
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['TK_CFLAGS']
- 
- with Files("**"):
-     BUG_COMPONENT = ("Toolkit", "Startup and Profile System")
-diff --git a/config/recurse.mk b/config/recurse.mk
---- a/config/recurse.mk
-+++ b/config/recurse.mk
-@@ -183,15 +183,15 @@ dom/bindings/export: layout/style/export
- 
- ifdef ENABLE_CLANG_PLUGIN
- $(filter-out config/host build/unix/stdc++compat/% build/clang-plugin/%,$(compile_targets)): build/clang-plugin/host build/clang-plugin/tests/target-objects
- build/clang-plugin/tests/target-objects: build/clang-plugin/host
- endif
- 
- # Interdependencies that moz.build world don't know about yet for compilation.
- # Note some others are hardcoded or "guessed" in recursivemake.py and emitter.py
--ifeq ($(MOZ_WIDGET_TOOLKIT),gtk3)
-+ifeq ($(MOZ_WIDGET_TOOLKIT),gtk)
- toolkit/library/target: widget/gtk/mozgtk/gtk3/target
- endif
- endif
- # Most things are built during compile (target/host), but some things happen during export
- # Those need to depend on config/export for system wrappers.
- $(addprefix build/unix/stdc++compat/,target host) build/clang-plugin/host: config/export
-diff --git a/dom/geolocation/moz.build b/dom/geolocation/moz.build
---- a/dom/geolocation/moz.build
-+++ b/dom/geolocation/moz.build
-@@ -41,14 +41,14 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'andr
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-     LOCAL_INCLUDES += [
-         '/dom/system/mac',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     LOCAL_INCLUDES += [
-         '/dom/system/windows',
-     ]
--elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     if CONFIG['MOZ_GPSD']:
-         LOCAL_INCLUDES += [
-             '/dom/system/linux',
-         ]
-         DEFINES['MOZ_GPSD'] = True
-diff --git a/dom/ipc/tests/mochitest.ini b/dom/ipc/tests/mochitest.ini
---- a/dom/ipc/tests/mochitest.ini
-+++ b/dom/ipc/tests/mochitest.ini
-@@ -10,17 +10,17 @@ skip-if = e10s
- skip-if = e10s
- [test_bug1086684.html]
- # This test is only supposed to run in the main process
- skip-if = e10s || toolkit == 'android'
- [test_cpow_cookies.html]
- [test_child_docshell.html]
- skip-if = toolkit == 'cocoa' # cocoa: disabled due to hangs, see changeset 6852e7c47edf
- [test_CrashService_crash.html]
--skip-if = !(crashreporter && !e10s && (toolkit == 'gtk3' || toolkit == 'cocoa' || toolkit == 'windows'))
-+skip-if = !(crashreporter && !e10s && (toolkit == 'gtk' || toolkit == 'cocoa' || toolkit == 'windows'))
- [test_temporaryfile_stream.html]
- skip-if = !e10s || toolkit == 'android' || (os == "win" && processor == "aarch64") # Bug 1525959, aarch64 due to 1531150
- support-files =
-   blob_verify.sjs
-   !/dom/canvas/test/captureStream_common.js
- [test_Preallocated.html]
- skip-if = !e10s || toolkit == 'android' # Bug 1525959
- [test_force_oop_iframe.html]
-diff --git a/dom/moz.build b/dom/moz.build
---- a/dom/moz.build
-+++ b/dom/moz.build
-@@ -114,12 +114,12 @@ if CONFIG['OS_ARCH'] == 'WINNT':
- 
- DIRS += ['presentation']
- 
- TEST_DIRS += [
-     'tests',
-     'imptests',
- ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk3', 'cocoa', 'windows'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk', 'cocoa', 'windows'):
-     TEST_DIRS += ['plugins/test']
- 
- SPHINX_TREES['dom'] = 'docs'
-diff --git a/dom/plugins/ipc/moz.build b/dom/plugins/ipc/moz.build
---- a/dom/plugins/ipc/moz.build
-+++ b/dom/plugins/ipc/moz.build
-@@ -135,17 +135,17 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_
-     LOCAL_INCLUDES += [
-         '/security/sandbox/chromium',
-         '/security/sandbox/chromium-shim',
-         '/security/sandbox/win/src/sandboxpermissions',
-     ]
- 
- DEFINES['FORCE_PR_LOG'] = True
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gtk':
-     CXXFLAGS += CONFIG['TK_CFLAGS']
- else:
-     # Force build against gtk+2 for struct offsets and such.
-     CXXFLAGS += CONFIG['MOZ_GTK2_CFLAGS']
- 
- CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
- 
- if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
-diff --git a/dom/plugins/test/mochitest/mochitest.ini b/dom/plugins/test/mochitest/mochitest.ini
---- a/dom/plugins/test/mochitest/mochitest.ini
-+++ b/dom/plugins/test/mochitest/mochitest.ini
-@@ -66,19 +66,19 @@ reason = Plugins are not supported on Wi
- skip-if = verify || (processor == 'aarch64' && os == 'win') # aarch64 due to 1541241
- [test_cocoa_focus.html]
- skip-if = toolkit != "cocoa" || e10s # Bug 1194534
- support-files = cocoa_focus.html
- [test_cocoa_window_focus.html]
- skip-if = toolkit != "cocoa" # Bug 1194534
- support-files = cocoa_window_focus.html
- [test_copyText.html]
--skip-if = toolkit != "gtk3"
-+skip-if = toolkit != "gtk"
- [test_crash_nested_loop.html]
--skip-if = toolkit != "gtk3"
-+skip-if = toolkit != "gtk"
- [test_crashing.html]
- skip-if = !crashreporter
- [test_crashing2.html]
- skip-if = (!crashreporter) || true # Bug 566049
- [test_CrashService_crash.html]
- skip-if = !crashreporter || e10s
- [test_CrashService_hang.html]
- skip-if = !crashreporter || e10s
-@@ -144,11 +144,11 @@ skip-if = e10s # Bug 1090576
- skip-if = toolkit == "cocoa"
- [test_windowed_invalidate.html]
- skip-if = os != "win" || webrender # win/webrender bug 1296400
- [test_windowless_flash.html]
- skip-if = !(os == "win" && processor == "x86_64") || verify
- [test_windowless_ime.html]
- skip-if = os != "win" || (os == "win" && processor == "aarch64") # aarch64 due to 1536350
- [test_x11_error_crash.html]
--skip-if = !crashreporter || e10s || toolkit != "gtk3"
-+skip-if = !crashreporter || e10s || toolkit != "gtk"
- [test_zero_opacity.html]
- skip-if = os == "win" && webrender # win/webrender bug 1296400
-diff --git a/dom/plugins/test/moz.build b/dom/plugins/test/moz.build
---- a/dom/plugins/test/moz.build
-+++ b/dom/plugins/test/moz.build
-@@ -3,13 +3,13 @@
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- 
- DIRS += ['testplugin']
- 
- XPCSHELL_TESTS_MANIFESTS += ['unit/xpcshell.ini']
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk3', 'cocoa', 'windows'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk', 'cocoa', 'windows'):
-     MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini']
-     MOCHITEST_CHROME_MANIFESTS += ['mochitest/chrome.ini']
-     BROWSER_CHROME_MANIFESTS += ['mochitest/browser.ini']
- 
-diff --git a/dom/plugins/test/testplugin/testplugin.mozbuild b/dom/plugins/test/testplugin/testplugin.mozbuild
---- a/dom/plugins/test/testplugin/testplugin.mozbuild
-+++ b/dom/plugins/test/testplugin/testplugin.mozbuild
-@@ -13,17 +13,17 @@ UNIFIED_SOURCES += [
-     '%s/nptest_name.cpp' % relative_path,
- ]
- 
- toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
- if toolkit == 'cocoa':
-     UNIFIED_SOURCES += [
-         'nptest_macosx.mm'
-     ]
--elif toolkit == 'gtk3':
-+elif toolkit == 'gtk':
-     UNIFIED_SOURCES += [
-         'nptest_gtk2.cpp',
-     ]
- elif toolkit == 'windows':
-     UNIFIED_SOURCES += [
-         'nptest_windows.cpp',
-     ]
-     OS_LIBS += [
-@@ -42,17 +42,17 @@ NO_PGO = True
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     RCFILE  = 'nptest.rc'
-     RESFILE = 'nptest.res'
-     DEFFILE = 'nptest.def'
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' and CONFIG['TARGET_CPU'] == 'x86_64':
-     OS_LIBS += ['-framework Carbon']
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['MOZ_GTK2_CFLAGS']
-     CFLAGS += CONFIG['MOZ_GTK2_CFLAGS']
-     OS_LIBS += CONFIG['MOZ_GTK2_LIBS']
-     OS_LIBS += CONFIG['XLDFLAGS']
-     OS_LIBS += CONFIG['XLIBS']
-     OS_LIBS += CONFIG['XEXT_LIBS']
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-diff --git a/dom/system/moz.build b/dom/system/moz.build
---- a/dom/system/moz.build
-+++ b/dom/system/moz.build
-@@ -44,17 +44,17 @@ with Files("tests/*1197901*"):
- toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
- 
- if toolkit == 'windows':
-     DIRS += ['windows']
- elif toolkit == 'cocoa':
-     DIRS += ['mac']
- elif toolkit == 'android':
-     DIRS += ['android']
--elif toolkit == 'gtk3':
-+elif toolkit == 'gtk':
-     DIRS += ['linux']
- 
- if toolkit != 'cocoa':
-     EXPORTS += [
-         'nsOSPermissionRequest.h',
-     ]
- 
- XPIDL_SOURCES += [
-diff --git a/dom/xbl/builtin/moz.build b/dom/xbl/builtin/moz.build
---- a/dom/xbl/builtin/moz.build
-+++ b/dom/xbl/builtin/moz.build
-@@ -5,17 +5,17 @@
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- 
- if CONFIG['OS_ARCH'] == 'WINNT':
-     DIRS += ['win']
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-     DIRS += ['mac']
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-     DIRS += ['android']
--elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     DIRS += ['unix']
- else:
-     DIRS += ['emacs']
- 
- EXPORTS.mozilla += ['ShortcutKeys.h']
- 
- SOURCES += ['ShortcutKeys.cpp']
- 
-diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build
---- a/gfx/2d/moz.build
-+++ b/gfx/2d/moz.build
-@@ -97,26 +97,26 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wi
-     ]
-     DEFINES['WIN32'] = True
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'windows':
-     SOURCES += [
-         'JobScheduler_posix.cpp',
-     ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk3'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk'):
-     EXPORTS.mozilla.gfx += [
-         'UnscaledFontFreeType.h',
-     ]
-     SOURCES += [
-         'NativeFontResourceFreeType.cpp',
-         'UnscaledFontFreeType.cpp',
-     ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     SOURCES += [
-         'ScaledFontFontconfig.cpp',
-     ]
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-     SOURCES += [
-         'ScaledFontFreeType.cpp',
-     ]
-@@ -235,22 +235,22 @@ if CONFIG['CPU_ARCH'] == 'aarch64' or CO
- 
- include('/ipc/chromium/chromium-config.mozbuild')
- 
- FINAL_LIBRARY = 'xul'
- 
- for var in ('USE_CAIRO', 'MOZ2D_HAS_MOZ_CAIRO'):
-     DEFINES[var] = True
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk3'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk'):
-     DEFINES['MOZ_ENABLE_FREETYPE'] = True
- 
- CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk3'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk'):
-     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
- 
- LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
- 
- if CONFIG['MOZ_ENABLE_SKIA']:
-     LOCAL_INCLUDES += [
-         '/gfx/skia/skia/include/private',
-         '/gfx/skia/skia/src/core',
-diff --git a/gfx/cairo/cairo/src/moz.build b/gfx/cairo/cairo/src/moz.build
---- a/gfx/cairo/cairo/src/moz.build
-+++ b/gfx/cairo/cairo/src/moz.build
-@@ -65,17 +65,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] in {'c
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'beos':
-     EXPORTS.cairo += [
-         'cairo-beos.h',
-     ]
-     SOURCES += [
-         'cairo-beos-surface.cpp',
-     ]
--elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     EXPORTS.cairo += [
-         'cairo-ps.h',
-     ]
-     SOURCES += [
-         'cairo-ps-surface.c',
-     ]
- 
- if CONFIG['MOZ_X11']:
-diff --git a/gfx/gl/moz.build b/gfx/gl/moz.build
---- a/gfx/gl/moz.build
-+++ b/gfx/gl/moz.build
-@@ -7,17 +7,17 @@
- gl_provider = 'Null'
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     gl_provider = 'WGL'
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-     gl_provider = 'CGL'
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
-     gl_provider = 'EAGL'
--elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     if CONFIG['MOZ_EGL_XRENDER_COMPOSITE']:
-         gl_provider = 'EGL'
-     else:
-         gl_provider = 'GLX'
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-     gl_provider = 'EGL'
- 
- if CONFIG['MOZ_GL_PROVIDER']:
-diff --git a/gfx/harfbuzz/src/moz.build b/gfx/harfbuzz/src/moz.build
---- a/gfx/harfbuzz/src/moz.build
-+++ b/gfx/harfbuzz/src/moz.build
-@@ -78,17 +78,17 @@ UNIFIED_SOURCES += [
-     'hb-static.cc',
-     'hb-subset-cff-common.cc',
-     'hb-subset-cff1.cc',
-     'hb-subset-cff2.cc',
-     'hb-unicode.cc',
-     'hb-warning.cc',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     EXPORTS.harfbuzz += [
-         'hb-glib.h',
-     ]
-     UNIFIED_SOURCES += [
-         'hb-glib.cc',
-     ]
-     CXXFLAGS += CONFIG['GLIB_CFLAGS']
- 
-diff --git a/gfx/skia/generate_mozbuild.py b/gfx/skia/generate_mozbuild.py
---- a/gfx/skia/generate_mozbuild.py
-+++ b/gfx/skia/generate_mozbuild.py
-@@ -112,21 +112,21 @@ if CONFIG['CC_TYPE'] == 'gcc':
- if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'):
-     CXXFLAGS += [
-         '-Wno-implicit-fallthrough',
-         '-Wno-inconsistent-missing-override',
-         '-Wno-macro-redefined',
-         '-Wno-unused-private-field',
-     ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk3', 'android'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk', 'android'):
-     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
-     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
- 
- if CONFIG['MOZ_ENABLE_SKIA_PDF_SFNTLY']:
-     LOCAL_INCLUDES += CONFIG['SFNTLY_INCLUDES']
- """
- 
- import json
- 
-@@ -396,17 +396,17 @@ def write_mozbuild(sources):
-   write_sources(f, sources['pdf'], 4)
- 
-   f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':\n")
-   write_sources(f, sources['android'], 4)
- 
-   f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):\n")
-   write_sources(f, sources['mac'], 4)
- 
--  f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':\n")
-+  f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':\n")
-   write_sources(f, sources['linux'], 4)
- 
-   f.write("if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':\n")
-   write_list(f, "SOURCES", sources['win'], 4)
- 
-   f.write("if CONFIG['INTEL_ARCHITECTURE']:\n")
-   write_sources(f, sources['intel'], 4)
-   write_cflags(f, sources['intel'], opt_whitelist, 'skia_opt_flags', 4)
-diff --git a/gfx/skia/moz.build b/gfx/skia/moz.build
---- a/gfx/skia/moz.build
-+++ b/gfx/skia/moz.build
-@@ -362,17 +362,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('coc
-         'skia/src/ports/SkDebug_stdio.cpp',
-         'skia/src/ports/SkOSFile_posix.cpp',
-         'skia/src/ports/SkOSLibrary_posix.cpp',
-         'skia/src/ports/SkTLS_pthread.cpp',
-     ]
-     SOURCES += [
-         'skia/src/ports/SkFontHost_mac.cpp',
-     ]
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     UNIFIED_SOURCES += [
-         'skia/src/ports/SkDebug_stdio.cpp',
-         'skia/src/ports/SkOSFile_posix.cpp',
-         'skia/src/ports/SkOSLibrary_posix.cpp',
-         'skia/src/ports/SkTLS_pthread.cpp',
-     ]
-     SOURCES += [
-         'skia/src/ports/SkFontHost_cairo.cpp',
-@@ -488,17 +488,17 @@ if CONFIG['CC_TYPE'] == 'gcc':
- if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'):
-     CXXFLAGS += [
-         '-Wno-implicit-fallthrough',
-         '-Wno-inconsistent-missing-override',
-         '-Wno-macro-redefined',
-         '-Wno-unused-private-field',
-     ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk3', 'android'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk', 'android'):
-     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
-     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
- 
- if CONFIG['MOZ_ENABLE_SKIA_PDF_SFNTLY']:
-     LOCAL_INCLUDES += CONFIG['SFNTLY_INCLUDES']
-diff --git a/gfx/src/moz.build b/gfx/src/moz.build
---- a/gfx/src/moz.build
-+++ b/gfx/src/moz.build
-@@ -87,10 +87,10 @@ LOCAL_INCLUDES += [
-     '/dom/ipc',  # for ContentChild.h
- ]
- 
- FINAL_LIBRARY = 'xul'
- 
- CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
- CXXFLAGS += CONFIG['TK_CFLAGS']
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
-diff --git a/gfx/thebes/moz.build b/gfx/thebes/moz.build
---- a/gfx/thebes/moz.build
-+++ b/gfx/thebes/moz.build
-@@ -104,17 +104,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
-     SOURCES += [
-         'gfxCoreTextShaper.cpp',
-         'gfxMacFont.cpp',
-         'gfxPlatformMac.cpp',
-         'gfxQuartzNativeDrawing.cpp',
-         'gfxQuartzSurface.cpp',
-         'PrintTargetCG.mm',
-     ]
--elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     EXPORTS += [
-         'gfxFT2FontBase.h',
-         'gfxGdkNativeRenderer.h',
-         'gfxPlatformGtk.h',
-     ]
-     EXPORTS.mozilla.gfx += [
-         'PrintTargetPDF.h',
-         'PrintTargetPS.h',
-@@ -255,33 +255,33 @@ include('/ipc/chromium/chromium-config.m
- 
- FINAL_LIBRARY = 'xul'
- 
- LOCAL_INCLUDES += [
-     '/dom/base',
-     '/dom/xml',
- ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk3'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk'):
-     DEFINES['MOZ_ENABLE_FREETYPE'] = True
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     for var in ('MOZ_ENABLE_D3D10_LAYER',):
-         if CONFIG[var]:
-             DEFINES[var] = True
- 
- CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
- CXXFLAGS += CONFIG['TK_CFLAGS']
- CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
- CFLAGS += CONFIG['TK_CFLAGS']
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android'):
-     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
- 
- if CONFIG['MOZ_WAYLAND']:
-     CXXFLAGS += CONFIG['MOZ_WAYLAND_CFLAGS']
- 
- LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
- 
- DEFINES['GRAPHITE2_STATIC'] = True
-diff --git a/gfx/webrender_bindings/moz.build b/gfx/webrender_bindings/moz.build
---- a/gfx/webrender_bindings/moz.build
-+++ b/gfx/webrender_bindings/moz.build
-@@ -73,17 +73,17 @@ if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
- if CONFIG['MOZ_WAYLAND']:
-     EXPORTS.mozilla.webrender += [
-         'RenderCompositorEGL.h',
-     ]
-     SOURCES += [
-         'RenderCompositorEGL.cpp',
-     ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk3'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk'):
-     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
-     CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS']
- 
- if CONFIG['COMPILE_ENVIRONMENT']:
-     GENERATED_FILES += [
-         'webrender_ffi_generated.h',
-     ]
- 
-diff --git a/image/decoders/icon/moz.build b/image/decoders/icon/moz.build
---- a/image/decoders/icon/moz.build
-+++ b/image/decoders/icon/moz.build
-@@ -18,17 +18,17 @@ FINAL_LIBRARY = 'xul'
- include('/ipc/chromium/chromium-config.mozbuild')
- 
- EXPORTS += [
-   'nsIconURI.h',
- ]
- 
- platform = None
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     platform = 'gtk'
- 
- if CONFIG['OS_ARCH'] == 'WINNT':
-     platform = 'win'
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-     platform = 'mac'
- 
-diff --git a/image/decoders/moz.build b/image/decoders/moz.build
---- a/image/decoders/moz.build
-+++ b/image/decoders/moz.build
-@@ -3,17 +3,17 @@
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- 
- toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
- 
- # The Icon Channel stuff really shouldn't live in decoders/icon, but we'll
- # fix that another time.
--if 'gtk' in toolkit:
-+if toolkit == 'gtk':
-     DIRS += ['icon/gtk', 'icon']
- 
- if CONFIG['OS_ARCH'] == 'WINNT':
-     DIRS += ['icon/win', 'icon']
- 
- if toolkit == 'cocoa':
-     DIRS += ['icon/mac', 'icon']
- elif toolkit == 'android':
-diff --git a/intl/locale/moz.build b/intl/locale/moz.build
---- a/intl/locale/moz.build
-+++ b/intl/locale/moz.build
-@@ -7,17 +7,17 @@
- XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
- 
- toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
- 
- if toolkit == 'windows':
-     DIRS += ['windows']
- elif toolkit == 'cocoa':
-     DIRS += ['mac']
--elif 'gtk' in toolkit:
-+elif toolkit == 'gtk':
-     DIRS += ['gtk']
- elif toolkit == 'android':
-     DIRS += ['android']
- 
- XPIDL_SOURCES += [
-     'mozILocaleService.idl',
-     'mozIOSPreferences.idl',
-     'nsICollation.idl',
-diff --git a/intl/lwbrk/moz.build b/intl/lwbrk/moz.build
---- a/intl/lwbrk/moz.build
-+++ b/intl/lwbrk/moz.build
-@@ -11,17 +11,17 @@ EXPORTS.mozilla.intl += [
-     'WordBreaker.h',
- ]
- 
- UNIFIED_SOURCES += [
-     'LineBreaker.cpp',
-     'WordBreaker.cpp',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     SOURCES += [
-         'nsPangoBreaker.cpp',
-     ]
-     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     SOURCES += [
-         'nsUniscribeBreaker.cpp',
-     ]
-diff --git a/ipc/chromium/moz.build b/ipc/chromium/moz.build
---- a/ipc/chromium/moz.build
-+++ b/ipc/chromium/moz.build
-@@ -100,17 +100,17 @@ if os_linux:
-     if CONFIG['OS_TARGET'] == 'Android':
-         UNIFIED_SOURCES += [
-             'src/base/message_pump_android.cc',
-         ]
-         DEFINES['ANDROID'] = True
-         DEFINES['_POSIX_MONOTONIC_CLOCK'] = 0
- 
- if os_bsd or os_linux:
--    if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-         SOURCES += [
-             'src/base/message_pump_glib.cc',
-         ]
- 
- if os_solaris:
-     SOURCES += [
-         'src/base/process_util_linux.cc',
-         'src/base/time_posix.cc',
-diff --git a/layout/base/tests/mochitest.ini b/layout/base/tests/mochitest.ini
---- a/layout/base/tests/mochitest.ini
-+++ b/layout/base/tests/mochitest.ini
-@@ -125,17 +125,17 @@ support-files = bug1078327_inner.html
- skip-if = toolkit == 'android' # We don't support pointer event on android
- support-files = bug1080360_inner.html
- [test_bug1080361.html]
- skip-if = toolkit == 'android' # We don't support pointer event on android
- support-files = bug1080361_inner.html
- [test_bug1093686.html]
- support-files = bug1093686_inner.html
- [test_bug1120705.html]
--skip-if = toolkit == 'android' || os == 'mac' || toolkit == 'gtk3' # android does not have clickable scrollbars, mac does not have scrollbar down and up buttons, gtk may or may not have scrollbar buttons depending on theme
-+skip-if = toolkit == 'android' || os == 'mac' || toolkit == 'gtk' # android does not have clickable scrollbars, mac does not have scrollbar down and up buttons, gtk may or may not have scrollbar buttons depending on theme
- [test_bug1153130.html]
- skip-if = toolkit == 'android' # We don't support pointer event on android
- support-files = bug1153130_inner.html
- [test_bug1162990.html]
- skip-if = toolkit == 'android' # We don't support pointer event on android
- support-files =
-   bug1162990_inner_1.html
-   bug1162990_inner_2.html
-diff --git a/layout/generic/moz.build b/layout/generic/moz.build
---- a/layout/generic/moz.build
-+++ b/layout/generic/moz.build
-@@ -258,13 +258,13 @@ CONTENT_ACCESSIBLE_FILES.html = [
-     'folder.png',
- ]
- 
- MOCHITEST_MANIFESTS += ['test/mochitest.ini']
- MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
- 
- CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['TK_CFLAGS']
- 
- if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
-     CXXFLAGS += ['-Wno-error=shadow']
-diff --git a/layout/generic/test/mochitest.ini b/layout/generic/test/mochitest.ini
---- a/layout/generic/test/mochitest.ini
-+++ b/layout/generic/test/mochitest.ini
-@@ -112,17 +112,17 @@ skip-if = os=='win'
- [test_invalidate_during_plugin_paint.html]
- skip-if = toolkit == 'android' || headless # Headless:Bug 1405871
- [test_intrinsic_size_on_loading.html]
- [test_movement_by_characters.html]
- [test_movement_by_words.html]
- # Disable the caret movement by word test on Linux because the shortcut keys
- # are defined in system level.  So, it depends on the environment.
- # Disable on Windows for too many intermittent failures (bug 916143).
--skip-if = (toolkit == "gtk3") || (os == "win")
-+skip-if = (toolkit == "gtk") || (os == "win")
- [test_overflow_event.html]
- [test_page_scroll_with_fixed_pos.html]
- support-files = page_scroll_with_fixed_pos_window.html
- [test_plugin_clipping.xhtml]
- skip-if = e10s
- [test_plugin_clipping2.xhtml]
- skip-if = e10s
- [test_plugin_clipping_transformed.xhtml]
-diff --git a/layout/reftests/bidi/reftest.list b/layout/reftests/bidi/reftest.list
---- a/layout/reftests/bidi/reftest.list
-+++ b/layout/reftests/bidi/reftest.list
-@@ -138,17 +138,17 @@ random-if(/^Windows\x20NT\x206\.1/.test(
- == 746987-4.html 746987-4-ref.html
- == 779003-1.html 779003-1-ref.html
- == 779003-1-dynamic.html 779003-1-ref.html
- == 817406-1.html 817406-1-ref.html
- == 817406-2.html 817406-2-ref.html
- == 817406-3.html 817406-1-ref.html
- == 817406-4.html 817406-4-ref.html
- == 847242-1.html 847242-1-ref.html
--pref(layout.css.xul-tree-pseudos.content.enabled,true) fuzzy-if(xulRuntime.widgetToolkit=="gtk3",0-1,0-11) == chrome://reftest/content/bidi/869833-1.xul chrome://reftest/content/bidi/869833-1-ref.xul
-+pref(layout.css.xul-tree-pseudos.content.enabled,true) fuzzy-if(xulRuntime.widgetToolkit=="gtk",0-1,0-11) == chrome://reftest/content/bidi/869833-1.xul chrome://reftest/content/bidi/869833-1-ref.xul
- == 922530-1.html 922530-1-ref.html
- random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 922550-1.html 922550-1-ref.html # Bug 1392106
- == 989994-1.html 989994-1-ref.html
- == 1067268-1.html 1067268-1-ref.html
- == 1069941-inline-bidi-border-1.html 1069941-inline-bidi-border-1-ref.html
- == 1069941-inline-bidi-margin-1.html 1069941-inline-bidi-margin-1-ref.html
- != chrome://reftest/content/bidi/1155359-1.xul chrome://reftest/content/bidi/1155359-1-ref.xul
- == 1157726-1.html 1157726-1-ref.html
-diff --git a/layout/reftests/scrolling/reftest.list b/layout/reftests/scrolling/reftest.list
---- a/layout/reftests/scrolling/reftest.list
-+++ b/layout/reftests/scrolling/reftest.list
-@@ -1,10 +1,10 @@
- HTTP == deferred-anchor.xhtml#d deferred-anchor-ref.xhtml#d
--fuzzy-if(xulRuntime.widgetToolkit=="gtk3",0-1,0-23) == deferred-anchor2.xhtml deferred-anchor-ref.xhtml#d # bug 1182632
-+fuzzy-if(xulRuntime.widgetToolkit=="gtk",0-1,0-23) == deferred-anchor2.xhtml deferred-anchor-ref.xhtml#d # bug 1182632
- HTTP == fixed-1.html fixed-1.html?ref
- fuzzy-if(skiaContent,0-1,0-32200) HTTP == fixed-table-1.html fixed-table-1.html?ref
- HTTP == fixed-opacity-1.html fixed-opacity-1.html?ref
- HTTP == fixed-opacity-2.html fixed-opacity-2.html?ref
- random-if(gtkWidget) fuzzy-if(Android,0-3,0-60) HTTP == fixed-text-1.html fixed-text-1.html?ref
- HTTP == fixed-text-2.html fixed-text-2.html?ref
- random-if(Android) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-12) fuzzy-if(webrender&&winWidget,0-1,0-31) == iframe-border-radius.html iframe-border-radius-ref.html # bug 760269
- random-if(Android) HTTP == image-1.html image-1.html?ref
-diff --git a/layout/reftests/xul/reftest.list b/layout/reftests/xul/reftest.list
---- a/layout/reftests/xul/reftest.list
-+++ b/layout/reftests/xul/reftest.list
-@@ -2,17 +2,17 @@
- 
- == chrome://reftest/content/xul/menuitem-key.xul chrome://reftest/content/xul/menuitem-key-ref.xul
- # these random-if(Android) are due to differences between Android Native & Xul, see bug 732569
- random-if(Android) == chrome://reftest/content/xul/menulist-shrinkwrap-1.xul chrome://reftest/content/xul/menulist-shrinkwrap-1-ref.xul
- random-if(Android) == chrome://reftest/content/xul/menulist-shrinkwrap-2.xul chrome://reftest/content/xul/menulist-shrinkwrap-2-ref.xul
- == chrome://reftest/content/xul/textbox-overflow-1.xul chrome://reftest/content/xul/textbox-overflow-1-ref.xul # for bug 749658
- # accesskeys are not normally displayed on Mac, so set a pref to enable them
- pref(ui.key.menuAccessKey,18) == chrome://reftest/content/xul/accesskey.xul chrome://reftest/content/xul/accesskey-ref.xul
--pref(layout.css.xul-tree-pseudos.content.enabled,true) fuzzy-if(xulRuntime.widgetToolkit=="gtk3",0-1,0-11) == chrome://reftest/content/xul/tree-row-outline-1.xul chrome://reftest/content/xul/tree-row-outline-1-ref.xul # win8: bug 1254832
-+pref(layout.css.xul-tree-pseudos.content.enabled,true) fuzzy-if(xulRuntime.widgetToolkit=="gtk",0-1,0-11) == chrome://reftest/content/xul/tree-row-outline-1.xul chrome://reftest/content/xul/tree-row-outline-1-ref.xul # win8: bug 1254832
- skip-if(!cocoaWidget) fails-if(webrender&&cocoaWidget) == chrome://reftest/content/xul/mac-tab-toolbar.xul chrome://reftest/content/xul/mac-tab-toolbar-ref.xul
- pref(layout.css.xul-tree-pseudos.content.enabled,true) != chrome://reftest/content/xul/tree-row-outline-1.xul chrome://reftest/content/xul/tree-row-outline-1-notref.xul
- == chrome://reftest/content/xul/text-crop.xul chrome://reftest/content/xul/text-crop-ref.xul
- random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == chrome://reftest/content/xul/text-small-caps-1.xul chrome://reftest/content/xul/text-small-caps-1-ref.xul
- fuzzy-if(skiaContent,0-1,0-60) fuzzy-if(cocoaWidget&&browserIsRemote&&!skiaContent,0-1,0-31) fuzzy-if(winWidget&&browserIsRemote&&layersGPUAccelerated,0-1,0-50) fuzzy-if(webrender,0-1,350-1050) == chrome://reftest/content/xul/inactive-fixed-bg-bug1205630.xul inactive-fixed-bg-bug1205630-ref.html
- fuzzy-if(skiaContent,0-1,0-60) fuzzy-if(cocoaWidget&&browserIsRemote&&!skiaContent,0-1,0-31) fuzzy-if(winWidget&&browserIsRemote&&layersGPUAccelerated,0-1,0-50) fuzzy-if(webrender,0-1,450-1100) == chrome://reftest/content/xul/inactive-fixed-bg-bug1272525.xul inactive-fixed-bg-bug1272525-ref.html
- 
- # Tests for XUL <image> with 'object-fit' & 'object-position':
-diff --git a/layout/tools/reftest/manifest.jsm b/layout/tools/reftest/manifest.jsm
---- a/layout/tools/reftest/manifest.jsm
-+++ b/layout/tools/reftest/manifest.jsm
-@@ -461,28 +461,28 @@ function BuildConditionSandbox(aURL) {
-     sandbox.retainedDisplayList =
-       prefs.getBoolPref("layout.display-list.retain");
- 
-     sandbox.usesOverlayScrollbars = g.windowUtils.usesOverlayScrollbars;
- 
-     // Shortcuts for widget toolkits.
-     sandbox.Android = xr.OS == "Android";
-     sandbox.cocoaWidget = xr.widgetToolkit == "cocoa";
--    sandbox.gtkWidget = xr.widgetToolkit == "gtk3";
-+    sandbox.gtkWidget = xr.widgetToolkit == "gtk";
-     sandbox.qtWidget = xr.widgetToolkit == "qt";
-     sandbox.winWidget = xr.widgetToolkit == "windows";
- 
-     sandbox.is64Bit = xr.is64Bit;
- 
-     // GeckoView is currently uniquely identified by "android + e10s" but
-     // we might want to make this condition more precise in the future.
-     sandbox.geckoview = (sandbox.Android && g.browserIsRemote);
- 
-     // Scrollbars that are semi-transparent. See bug 1169666.
--    sandbox.transparentScrollbars = xr.widgetToolkit == "gtk3";
-+    sandbox.transparentScrollbars = xr.widgetToolkit == "gtk";
- 
-     if (sandbox.Android) {
-         var sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
- 
-         // This is currently used to distinguish Android 4.0.3 (SDK version 15)
-         // and later from Android 2.x
-         sandbox.AndroidVersion = sysInfo.getPropertyAsInt32("version");
-     }
-diff --git a/netwerk/build/moz.build b/netwerk/build/moz.build
---- a/netwerk/build/moz.build
-+++ b/netwerk/build/moz.build
-@@ -34,17 +34,17 @@ LOCAL_INCLUDES += [
-     '/netwerk/protocol/res',
-     '/netwerk/protocol/viewsource',
-     '/netwerk/protocol/websocket',
-     '/netwerk/socket',
-     '/netwerk/streamconv',
-     '/netwerk/streamconv/converters',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     LOCAL_INCLUDES += [
-         '/netwerk/protocol/gio',
-     ]
- 
- 
- LOCAL_INCLUDES += [
-     '!/netwerk/dns',
-     '/modules/brotli/dec',
-diff --git a/netwerk/protocol/moz.build b/netwerk/protocol/moz.build
---- a/netwerk/protocol/moz.build
-+++ b/netwerk/protocol/moz.build
-@@ -1,10 +1,10 @@
- # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
- # vim: set filetype=python:
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- 
- DIRS += ['about', 'data', 'file', 'ftp']
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     DIRS += ['gio']
- DIRS += ['http', 'res', 'viewsource', 'websocket' ]
-diff --git a/old-configure.in b/old-configure.in
---- a/old-configure.in
-+++ b/old-configure.in
-@@ -1780,17 +1780,17 @@ dnl there are a lot of tests on MOZ_ENAB
- dnl to keep that way than testing against MOZ_WIDGET_TOOLKIT
- case "$MOZ_WIDGET_TOOLKIT" in
- gtk*)
-     MOZ_ENABLE_GTK=1
-     ;;
- esac
- 
- if test "$COMPILE_ENVIRONMENT"; then
--  if test "$MOZ_WIDGET_TOOLKIT" = gtk3; then
-+  if test "$MOZ_WIDGET_TOOLKIT" = gtk; then
-     PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 gio-unix-2.0 $GDK_PACKAGES)
-     MOZ_GTK3_CFLAGS="-I${_topsrcdir}/widget/gtk/compat-gtk3 $MOZ_GTK3_CFLAGS"
-     TK_CFLAGS=$MOZ_GTK3_CFLAGS
-     TK_LIBS=$MOZ_GTK3_LIBS
-     dnl GDK_VERSION_MIN_REQUIRED is not set here as GDK3 deprecated warnings
-     dnl are suppressed by widget/gtk/compat-gtk3/gdk/gdkversionmacros.h.
-     AC_DEFINE_UNQUOTED(GDK_VERSION_MAX_ALLOWED,$GDK_VERSION_MAX_ALLOWED)
-     GLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32
-diff --git a/python/mozbuild/mozbuild/test/test_mozinfo.py b/python/mozbuild/mozbuild/test/test_mozinfo.py
---- a/python/mozbuild/mozbuild/test/test_mozinfo.py
-+++ b/python/mozbuild/mozbuild/test/test_mozinfo.py
-@@ -55,31 +55,31 @@ class TestBuildDict(unittest.TestCase, B
-         self.assertEqual('x86', d['processor'])
-         self.assertEqual('windows', d['toolkit'])
-         self.assertEqual(32, d['bits'])
- 
-     def test_linux(self):
-         d = build_dict(self._config(dict(
-             OS_TARGET='Linux',
-             TARGET_CPU='i386',
--            MOZ_WIDGET_TOOLKIT='gtk3',
-+            MOZ_WIDGET_TOOLKIT='gtk',
-         )))
-         self.assertEqual('linux', d['os'])
-         self.assertEqual('x86', d['processor'])
--        self.assertEqual('gtk3', d['toolkit'])
-+        self.assertEqual('gtk', d['toolkit'])
-         self.assertEqual(32, d['bits'])
- 
-         d = build_dict(self._config(dict(
-             OS_TARGET='Linux',
-             TARGET_CPU='x86_64',
--            MOZ_WIDGET_TOOLKIT='gtk3',
-+            MOZ_WIDGET_TOOLKIT='gtk',
-         )))
-         self.assertEqual('linux', d['os'])
-         self.assertEqual('x86_64', d['processor'])
--        self.assertEqual('gtk3', d['toolkit'])
-+        self.assertEqual('gtk', d['toolkit'])
-         self.assertEqual(64, d['bits'])
- 
-     def test_mac(self):
-         d = build_dict(self._config(dict(
-             OS_TARGET='Darwin',
-             TARGET_CPU='i386',
-             MOZ_WIDGET_TOOLKIT='cocoa',
-         )))
-@@ -129,24 +129,24 @@ class TestBuildDict(unittest.TestCase, B
- 
-     def test_arm(self):
-         """
-         Test that all arm CPU architectures => arm.
-         """
-         d = build_dict(self._config(dict(
-             OS_TARGET='Linux',
-             TARGET_CPU='arm',
--            MOZ_WIDGET_TOOLKIT='gtk3',
-+            MOZ_WIDGET_TOOLKIT='gtk',
-         )))
-         self.assertEqual('arm', d['processor'])
- 
-         d = build_dict(self._config(dict(
-             OS_TARGET='Linux',
-             TARGET_CPU='armv7',
--            MOZ_WIDGET_TOOLKIT='gtk3',
-+            MOZ_WIDGET_TOOLKIT='gtk',
-         )))
-         self.assertEqual('arm', d['processor'])
- 
-     def test_unknown(self):
-         """
-         Test that unknown values pass through okay.
-         """
-         d = build_dict(self._config(dict(
-@@ -162,43 +162,43 @@ class TestBuildDict(unittest.TestCase, B
- 
-     def test_debug(self):
-         """
-         Test that debug values are properly detected.
-         """
-         d = build_dict(self._config(dict(
-             OS_TARGET='Linux',
-             TARGET_CPU='i386',
--            MOZ_WIDGET_TOOLKIT='gtk3',
-+            MOZ_WIDGET_TOOLKIT='gtk',
-         )))
-         self.assertEqual(False, d['debug'])
- 
-         d = build_dict(self._config(dict(
-             OS_TARGET='Linux',
-             TARGET_CPU='i386',
--            MOZ_WIDGET_TOOLKIT='gtk3',
-+            MOZ_WIDGET_TOOLKIT='gtk',
-             MOZ_DEBUG='1',
-         )))
-         self.assertEqual(True, d['debug'])
- 
-     def test_crashreporter(self):
-         """
-         Test that crashreporter values are properly detected.
-         """
-         d = build_dict(self._config(dict(
-             OS_TARGET='Linux',
-             TARGET_CPU='i386',
--            MOZ_WIDGET_TOOLKIT='gtk3',
-+            MOZ_WIDGET_TOOLKIT='gtk',
-         )))
-         self.assertEqual(False, d['crashreporter'])
- 
-         d = build_dict(self._config(dict(
-             OS_TARGET='Linux',
-             TARGET_CPU='i386',
--            MOZ_WIDGET_TOOLKIT='gtk3',
-+            MOZ_WIDGET_TOOLKIT='gtk',
-             MOZ_CRASHREPORTER='1',
-         )))
-         self.assertEqual(True, d['crashreporter'])
- 
- 
- class TestWriteMozinfo(unittest.TestCase, Base):
-     """
-     Test the write_mozinfo function.
-diff --git a/security/manager/ssl/moz.build b/security/manager/ssl/moz.build
---- a/security/manager/ssl/moz.build
-+++ b/security/manager/ssl/moz.build
-@@ -133,17 +133,17 @@ UNIFIED_SOURCES += [
-     'PublicKeyPinningService.cpp',
-     'RootCertificateTelemetryUtils.cpp',
-     'SecretDecoderRing.cpp',
-     'SharedSSLState.cpp',
-     'SSLServerCertVerification.cpp',
-     'TransportSecurityInfo.cpp',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     UNIFIED_SOURCES += [
-         'LibSecret.cpp',
-     ]
-     CFLAGS += CONFIG['GLIB_CFLAGS']
-     CXXFLAGS += CONFIG['GLIB_CFLAGS']
- 
- if CONFIG['OS_ARCH'] == 'Darwin':
-     UNIFIED_SOURCES += [
-diff --git a/security/sandbox/linux/broker/moz.build b/security/sandbox/linux/broker/moz.build
---- a/security/sandbox/linux/broker/moz.build
-+++ b/security/sandbox/linux/broker/moz.build
-@@ -25,13 +25,13 @@ LOCAL_INCLUDES += [
- include('/ipc/chromium/chromium-config.mozbuild')
- 
- # Need this for safe_sprintf.h used by SandboxLogging.h,
- # but it has to be after ipc/chromium/src.
- LOCAL_INCLUDES += [
-     '/security/sandbox/chromium',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['GLIB_CFLAGS']
-     CXXFLAGS += CONFIG['TK_CFLAGS']
- 
- FINAL_LIBRARY = 'xul'
-diff --git a/testing/mozbase/manifestparser/tests/test_testmanifest.py b/testing/mozbase/manifestparser/tests/test_testmanifest.py
---- a/testing/mozbase/manifestparser/tests/test_testmanifest.py
-+++ b/testing/mozbase/manifestparser/tests/test_testmanifest.py
-@@ -29,17 +29,17 @@ class TestTestManifest(unittest.TestCase
-                                                                    exists=False)],
-                          ['fleem', 'linuxtest'])
- 
-         # Look for existing tests.  There is only one:
-         self.assertEqual([i['name'] for i in manifest.active_tests()],
-                          ['fleem'])
- 
-         # You should be able to expect failures:
--        last = manifest.active_tests(exists=False, toolkit='gtk3')[-1]
-+        last = manifest.active_tests(exists=False, toolkit='gtk')[-1]
-         self.assertEqual(last['name'], 'linuxtest')
-         self.assertEqual(last['expected'], 'pass')
-         last = manifest.active_tests(exists=False, toolkit='cocoa')[-1]
-         self.assertEqual(last['expected'], 'fail')
- 
-     def test_missing_paths(self):
-         """
-         Test paths that don't exist raise an exception in strict mode.
-diff --git a/testing/tools/screenshot/moz.build b/testing/tools/screenshot/moz.build
---- a/testing/tools/screenshot/moz.build
-+++ b/testing/tools/screenshot/moz.build
-@@ -1,15 +1,15 @@
- # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
- # vim: set filetype=python:
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT'] and CONFIG['MOZ_X11']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk' and CONFIG['MOZ_X11']:
-     Program('screentopng')
-     SOURCES += [
-         'gdk-screenshot.cpp',
-     ]
-     CXXFLAGS += CONFIG['TK_CFLAGS']
-     LDFLAGS += CONFIG['XLDFLAGS']
-     OS_LIBS += CONFIG['TK_LIBS']
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-diff --git a/toolkit/components/remote/moz.build b/toolkit/components/remote/moz.build
---- a/toolkit/components/remote/moz.build
-+++ b/toolkit/components/remote/moz.build
-@@ -6,17 +6,17 @@
- 
- with Files('**'):
-     BUG_COMPONENT = ('Toolkit', 'Startup and Profile System')
- 
- SOURCES += [
-     'nsRemoteService.cpp',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     SOURCES += [
-         'nsGTKRemoteServer.cpp',
-         'nsUnixRemoteServer.cpp',
-         'nsXRemoteClient.cpp',
-         'nsXRemoteServer.cpp',
-         'RemoteUtils.cpp',
-     ]
-     if CONFIG['MOZ_ENABLE_DBUS']:
-diff --git a/toolkit/crashreporter/client/moz.build b/toolkit/crashreporter/client/moz.build
---- a/toolkit/crashreporter/client/moz.build
-+++ b/toolkit/crashreporter/client/moz.build
-@@ -66,17 +66,17 @@ elif CONFIG['OS_ARCH'] == 'SunOS':
-     SOURCES += [
-         'crashreporter_linux.cpp',
-         'crashreporter_unix.cpp',
-     ]
-     USE_LIBS += [
-         'breakpad_solaris_common_s',
-     ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     UNIFIED_SOURCES += [
-         'crashreporter_gtk_common.cpp',
-         'crashreporter_linux.cpp',
-         'crashreporter_unix_common.cpp'
-     ]
-     USE_LIBS += [
-         'breakpad_linux_common_s',
-     ]
-diff --git a/toolkit/library/moz.build b/toolkit/library/moz.build
---- a/toolkit/library/moz.build
-+++ b/toolkit/library/moz.build
-@@ -154,32 +154,32 @@ USE_LIBS += [
-     'zlib',
- ]
- 
- if CONFIG['USE_ICU']:
-     USE_LIBS += [
-         'icu',
-     ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     USE_LIBS += [
-         'mozgtk_stub',
-     ]
- 
- if CONFIG['MOZ_WAYLAND']:
-     USE_LIBS += [
-         'mozwayland',
-     ]
- 
- if CONFIG['MOZ_JPROF']:
-     USE_LIBS += [
-         'jprof',
-     ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT'] or \
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk' or \
-         CONFIG['MOZ_TREE_FREETYPE']:
-     USE_LIBS += [
-         'freetype',
-     ]
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-     CXXFLAGS += CONFIG['TK_CFLAGS']
- 
-@@ -277,22 +277,19 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('coc
- if CONFIG['OS_ARCH'] == 'OpenBSD':
-     OS_LIBS += [
-         'sndio',
-     ]
- 
- if CONFIG['MOZ_ENABLE_DBUS']:
-     OS_LIBS += CONFIG['MOZ_DBUS_GLIB_LIBS']
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
--    if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
--        OS_LIBS += [l for l in CONFIG['TK_LIBS']
--            if l not in ('-lgtk-3', '-lgdk-3')]
--    else:
--        OS_LIBS += CONFIG['TK_LIBS']
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-+    OS_LIBS += [l for l in CONFIG['TK_LIBS']
-+        if l not in ('-lgtk-3', '-lgdk-3')]
-     OS_LIBS += CONFIG['XLDFLAGS']
-     OS_LIBS += CONFIG['XLIBS']
-     OS_LIBS += CONFIG['XEXT_LIBS']
-     OS_LIBS += CONFIG['MOZ_PANGO_LIBS']
-     OS_LIBS += CONFIG['XT_LIBS']
-     OS_LIBS += [
-         'gthread-2.0',
-     ]
-diff --git a/toolkit/locales/moz.build b/toolkit/locales/moz.build
---- a/toolkit/locales/moz.build
-+++ b/toolkit/locales/moz.build
-@@ -5,17 +5,17 @@
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- 
- with Files('**'):
-     BUG_COMPONENT = ('Firefox Build System', 'General')
- 
- if CONFIG['MOZ_BUILD_APP'] == 'mobile/android':
-   DEFINES['MOZ_FENNEC'] = True
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-   DEFINES['MOZ_GTK'] = True
- 
- JAR_MANIFESTS += ['jar.mn']
- 
- GENERATED_FILES = [
-     'multilocale.txt',
- ]
- multilocale = GENERATED_FILES['multilocale.txt']
-diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build
---- a/toolkit/modules/moz.build
-+++ b/toolkit/modules/moz.build
-@@ -241,20 +241,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
- EXTRA_JS_MODULES.third_party.jsesc += ['third_party/jsesc/jsesc.js']
- EXTRA_JS_MODULES.sessionstore += [
-     'sessionstore/PrivacyFilter.jsm',
-     'sessionstore/PrivacyLevel.jsm',
-     'sessionstore/SessionHistory.jsm',
-     'sessionstore/Utils.jsm',
- ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk'):
-     DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk3', 'cocoa'):
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk', 'cocoa'):
-     DEFINES['HAVE_SHELL_SERVICE'] = 1
- 
- EXTRA_PP_JS_MODULES += [
-     'AppConstants.jsm',
- ]
- 
- if 'Android' != CONFIG['OS_TARGET']:
-     EXTRA_JS_MODULES += [
-diff --git a/toolkit/moz.build b/toolkit/moz.build
---- a/toolkit/moz.build
-+++ b/toolkit/moz.build
-@@ -39,17 +39,17 @@ if CONFIG['MOZ_MAINTENANCE_SERVICE']:
-     DIRS += [
-         'components/maintenanceservice'
-     ]
- 
- DIRS += ['xre']
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
-     DIRS += ['mozapps/handling']
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     DIRS += ['system/unixproxy']
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-     DIRS += ['system/osxproxy']
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
-     DIRS += ['system/windowsproxy',
-             'system/windowsDHCPClient']
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-     DIRS += ['system/androidproxy']
-diff --git a/toolkit/moz.configure b/toolkit/moz.configure
---- a/toolkit/moz.configure
-+++ b/toolkit/moz.configure
-@@ -225,37 +225,35 @@ option('--enable-default-toolkit', nargs
-        help='Select default toolkit')
- 
- @depends_if('--enable-default-toolkit')
- def full_toolkit(value):
-     return value[0]
- 
- @depends(full_toolkit)
- def toolkit(toolkit):
--    if toolkit == 'cairo-gtk3-wayland':
--        widget_toolkit = 'gtk3'
-+    if toolkit.startswith('cairo-gtk3'):
-+        widget_toolkit = 'gtk'
-     else:
-         widget_toolkit = toolkit.replace('cairo-', '')
-     return widget_toolkit
- 
- set_config('MOZ_WIDGET_TOOLKIT', toolkit)
- add_old_configure_assignment('MOZ_WIDGET_TOOLKIT', toolkit)
- 
- @depends(toolkit)
- def toolkit_define(toolkit):
--    if toolkit == 'gtk3':
--        toolkit = 'gtk'
-     if toolkit != 'windows':
-         return 'MOZ_WIDGET_%s' % toolkit.upper()
- 
- set_define(toolkit_define, True)
- 
- @depends(toolkit)
- def toolkit_gtk(toolkit):
--    return toolkit == 'gtk3'
-+    return toolkit == 'gtk'
- 
- set_config('MOZ_X11', True, when=toolkit_gtk)
- set_define('MOZ_X11', True, when=toolkit_gtk)
- add_old_configure_assignment('MOZ_X11', True, when=toolkit_gtk)
- 
- # Wayland support
- # ==============================================================
- wayland_headers = pkg_check_modules(
-@@ -309,17 +307,17 @@ def gl_provider_define(provider):
- 
- set_define(gl_provider_define, True)
- 
- 
- # PDF printing
- # ==============================================================
- @depends(toolkit)
- def pdf_printing(toolkit):
--    if toolkit in ('windows', 'gtk3', 'android'):
-+    if toolkit in ('windows', 'gtk', 'android'):
-         return True
- 
- @depends(pdf_printing)
- def pdf_surface_feature(pdf_printing):
-     if pdf_printing:
-         return '#define CAIRO_HAS_PDF_SURFACE 1'
-     else:
-         # CONFIGURE_SUBST_FILES need explicit empty values.
-@@ -331,32 +329,32 @@ set_config('PDF_SURFACE_FEATURE', pdf_su
- 
- # Event loop instrumentation
- # ==============================================================
- option(env='MOZ_INSTRUMENT_EVENT_LOOP',
-        help='Force-enable event loop instrumentation')
- 
- @depends('MOZ_INSTRUMENT_EVENT_LOOP', toolkit)
- def instrument_event_loop(value, toolkit):
--    if value or (toolkit in ('windows', 'gtk3', 'cocoa', 'android') and
-+    if value or (toolkit in ('windows', 'gtk', 'cocoa', 'android') and
-                  value.origin == 'default'):
-         return True
- 
- set_config('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
- set_define('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
- 
- 
- # Fontconfig Freetype
- # ==============================================================
- option(env='USE_FC_FREETYPE',
-        help='Force-enable the use of fontconfig freetype')
- 
- @depends('USE_FC_FREETYPE', toolkit)
- def fc_freetype(value, toolkit):
--    if value or (toolkit == 'gtk3' and
-+    if value or (toolkit == 'gtk' and
-                  value.origin == 'default'):
-         return True
- 
- add_old_configure_assignment('USE_FC_FREETYPE', fc_freetype)
- 
- # Pango
- # ==============================================================
- pkg_check_modules('MOZ_PANGO',
-@@ -756,17 +754,17 @@ def printing(value):
- set_config('NS_PRINTING', printing)
- set_define('NS_PRINTING', printing)
- set_define('NS_PRINT_PREVIEW', printing)
- 
- # Speech-dispatcher support
- # ==============================================================
- @depends(toolkit)
- def no_speechd_on_non_gtk(toolkit):
--    if toolkit != 'gtk3':
-+    if toolkit != 'gtk':
-         return False
- 
- imply_option('--enable-synth-speechd', no_speechd_on_non_gtk,
-              reason='--enable-default-toolkit')
- 
- option('--disable-synth-speechd', help='Disable speech-dispatcher support')
- 
- set_config('MOZ_SYNTH_SPEECHD',
-@@ -1746,17 +1744,17 @@ with only_when(compile_environment & tar
-                when=d3d_compiler_dll.path)
-     set_config('MOZ_D3DCOMPILER_VISTA_DLL_PATH', d3d_compiler_dll.path)
- 
- # Remoting protocol support
- # ==============================================================
- 
- @depends(toolkit)
- def has_remote(toolkit):
--    if 'gtk' in toolkit or toolkit == 'windows':
-+    if toolkit in ('gtk', 'windows'):
-         return True
- 
- set_config('MOZ_HAS_REMOTE', has_remote)
- set_define('MOZ_HAS_REMOTE', has_remote)
- 
- 
- # new XULStore implementation
- # ==============================================================
-diff --git a/toolkit/mozapps/installer/upload-files.mk b/toolkit/mozapps/installer/upload-files.mk
---- a/toolkit/mozapps/installer/upload-files.mk
-+++ b/toolkit/mozapps/installer/upload-files.mk
-@@ -7,17 +7,17 @@ ifndef MOZ_PKG_FORMAT
-         MOZ_PKG_FORMAT  = DMG
-     else
-         ifeq (WINNT,$(OS_ARCH))
-             MOZ_PKG_FORMAT  = ZIP
-         else
-             ifeq (SunOS,$(OS_ARCH))
-                 MOZ_PKG_FORMAT  = BZ2
-             else
--                ifeq (gtk3,$(MOZ_WIDGET_TOOLKIT))
-+                ifeq (gtk,$(MOZ_WIDGET_TOOLKIT))
-                     MOZ_PKG_FORMAT  = BZ2
-                 else
-                     ifeq (android,$(MOZ_WIDGET_TOOLKIT))
-                         MOZ_PKG_FORMAT = APK
-                     else
-                         MOZ_PKG_FORMAT = TGZ
-                     endif
-                 endif
-diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build
---- a/toolkit/mozapps/update/updater/moz.build
-+++ b/toolkit/mozapps/update/updater/moz.build
-@@ -60,10 +60,10 @@ elif CONFIG['MOZ_UPDATE_CHANNEL'] in ('n
- else:
-     primary_cert.inputs += ['dep1.der']
-     secondary_cert.inputs += ['dep2.der']
- 
- dep1_cert.inputs += ['dep1.der']
- dep2_cert.inputs += ['dep2.der']
- xpcshell_cert.inputs += ['xpcshellCertificate.der']
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     FINAL_TARGET_FILES.icons += ['updater.png']
-diff --git a/toolkit/mozapps/update/updater/updater-common.build b/toolkit/mozapps/update/updater/updater-common.build
---- a/toolkit/mozapps/update/updater/updater-common.build
-+++ b/toolkit/mozapps/update/updater/updater-common.build
-@@ -42,17 +42,17 @@ if CONFIG['OS_ARCH'] == 'WINNT':
- 
- USE_LIBS += [
-     'bspatch',
-     'mar',
-     'updatecommon',
-     'xz-embedded',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     have_progressui = 1
-     srcs += [
-         'progressui_gtk.cpp',
-     ]
- 
- if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-     have_progressui = 1
-     srcs += [
-@@ -95,14 +95,14 @@ DELAYLOAD_DLLS += [
-     'wsock32.dll',
- ]
- 
- if CONFIG['CC_TYPE'] == 'clang-cl':
-     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
- elif CONFIG['OS_ARCH'] == 'WINNT':
-     WIN32_EXE_LDFLAGS += ['-municode']
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['TK_CFLAGS']
-     OS_LIBS += CONFIG['TK_LIBS']
- 
- if CONFIG['CC_TYPE'] == 'gcc':
-     CXXFLAGS += ['-Wno-format-truncation']
-diff --git a/toolkit/themes/moz.build b/toolkit/themes/moz.build
---- a/toolkit/themes/moz.build
-+++ b/toolkit/themes/moz.build
-@@ -15,17 +15,17 @@
- #                         non-mac (toolkit/themes/shared/non-mac)
- # mobile                  native UIs that do not use XUL for UI
- 
- toolkit = CONFIG['MOZ_WIDGET_TOOLKIT']
- app = CONFIG['MOZ_BUILD_APP']
- 
- if toolkit == 'cocoa':
-     DIRS += ['osx']
--elif toolkit == 'gtk3':
-+elif toolkit == 'gtk':
-     DIRS += ['linux']
- elif app == 'mobile/android':
-     DIRS += ['mobile']
- else:
-     DIRS += ['windows']
- 
- with Files('**'):
-     BUG_COMPONENT = ('Toolkit', 'Themes')
-diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
---- a/toolkit/toolkit.mozbuild
-+++ b/toolkit/toolkit.mozbuild
-@@ -151,17 +151,17 @@ DIRS += [
-     '/devtools',
-     '/toolkit/library',
-     '/services',
-     '/startupcache',
-     '/js/ductwork/debugger',
-     '/other-licenses/snappy',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     DIRS += [
-         '/toolkit/system/gnome',
-     ]
- 
- if CONFIG['ENABLE_REMOTE_AGENT']:
-     DIRS += ['/remote']
- 
- if CONFIG['ENABLE_MARIONETTE']:
-diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build
---- a/toolkit/xre/moz.build
-+++ b/toolkit/xre/moz.build
-@@ -82,31 +82,31 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
-     LOCAL_INCLUDES += [
-         '../components/printingui',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'uikit':
-     UNIFIED_SOURCES += [
-         'nsNativeAppSupportDefault.cpp',
-         'UIKitDirProvider.mm',
-     ]
--elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     UNIFIED_SOURCES += [
-         'nsNativeAppSupportUnix.cpp',
-     ]
- else:
-     UNIFIED_SOURCES += [
-         'nsNativeAppSupportDefault.cpp',
-     ]
- 
- if CONFIG['MOZ_HAS_REMOTE']:
-     LOCAL_INCLUDES += [
-         '../components/remote',
-     ]
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     UNIFIED_SOURCES += [
-         'nsGDKErrorHandler.cpp',
-     ]
- 
- if CONFIG['MOZ_X11']:
-     EXPORTS += ['nsX11ErrorHandler.h']
-     UNIFIED_SOURCES += [
-         'nsX11ErrorHandler.cpp',
-@@ -240,17 +240,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
-         '/widget/cocoa',
-         '/xpcom/base',
-     ]
- 
- CXXFLAGS += CONFIG['TK_CFLAGS']
- CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
- CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
- 
- DEFINES['TOPOBJDIR'] = TOPOBJDIR
- FINAL_TARGET_PP_FILES += [
-     'platform.ini'
- ]
- 
- if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
-diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build
---- a/uriloader/exthandler/moz.build
-+++ b/uriloader/exthandler/moz.build
-@@ -81,17 +81,17 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'ui
- else:
-     # These files can't be built in unified mode because they redefine LOG.
-     SOURCES += [
-         osdir + '/nsOSHelperAppService.cpp',
-     ]
-     if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
-         CXXFLAGS += ['-Wno-error=shadow']
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     UNIFIED_SOURCES += [
-         'unix/nsGNOMERegistry.cpp',
-         'unix/nsMIMEInfoUnix.cpp',
-     ]
- elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
-     UNIFIED_SOURCES += [
-         'android/nsAndroidHandlerApp.cpp',
-         'android/nsExternalURLHandlerService.cpp',
-@@ -139,11 +139,11 @@ LOCAL_INCLUDES += [
-     '/netwerk/base',
-     '/netwerk/protocol/http',
- ]
- 
- if CONFIG['MOZ_ENABLE_DBUS']:
-     CXXFLAGS += CONFIG['TK_CFLAGS']
-     CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['TK_CFLAGS']
-     CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
-diff --git a/widget/gtk/moz.build b/widget/gtk/moz.build
---- a/widget/gtk/moz.build
-+++ b/widget/gtk/moz.build
-@@ -8,17 +8,17 @@ with Files("**"):
-     BUG_COMPONENT = ("Core", "Widget: Gtk")
- 
- with Files("*CompositorWidget*"):
-     BUG_COMPONENT = ("Core", "Graphics")
- 
- with Files("*WindowSurface*"):
-     BUG_COMPONENT = ("Core", "Graphics")
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     DIRS += ['mozgtk']
- 
- if CONFIG['MOZ_WAYLAND']:
-     DIRS += ['wayland', 'mozwayland']
- 
- EXPORTS += [
-     'mozcontainer.h',
-     'nsGTKToolkit.h',
-@@ -148,17 +148,17 @@ CFLAGS += CONFIG['MOZ_STARTUP_NOTIFICATI
- 
- # When building with GTK3, the widget code always needs to use
- # system Cairo headers, regardless of whether we are also linked
- # against and using in-tree Cairo. By not using in-tree Cairo
- # headers, we avoid picking up our renamed symbols, and instead
- # use only system Cairo symbols that GTK3 uses. This allows that
- # any Cairo objects created can be freely passed back and forth
- # between the widget code and GTK3.
--if not (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3' and CONFIG['MOZ_TREE_CAIRO']):
-+if not (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk' and CONFIG['MOZ_TREE_CAIRO']):
-     CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
- 
- CXXFLAGS += CONFIG['MOZ_STARTUP_NOTIFICATION_CFLAGS']
- 
- CFLAGS += CONFIG['TK_CFLAGS']
- CXXFLAGS += CONFIG['TK_CFLAGS']
- 
- if CONFIG['MOZ_WAYLAND']:
-diff --git a/widget/headless/moz.build b/widget/headless/moz.build
---- a/widget/headless/moz.build
-+++ b/widget/headless/moz.build
-@@ -10,18 +10,16 @@ with Files("**"):
- DIRS += ['tests']
- 
- LOCAL_INCLUDES += [
-     '/widget',
-     '/widget/headless',
- ]
- 
- widget_dir = CONFIG['MOZ_WIDGET_TOOLKIT']
--if widget_dir == 'gtk3':
--    widget_dir = 'gtk'
- 
- LOCAL_INCLUDES += [
-     '/widget/%s' % widget_dir,
- ]
- 
- UNIFIED_SOURCES += [
-     'HeadlessClipboard.cpp',
-     'HeadlessClipboardData.cpp',
-diff --git a/widget/headless/tests/xpcshell.ini b/widget/headless/tests/xpcshell.ini
---- a/widget/headless/tests/xpcshell.ini
-+++ b/widget/headless/tests/xpcshell.ini
-@@ -1,9 +1,9 @@
- [DEFAULT]
--skip-if = toolkit != "gtk3" && toolkit != "windows"
-+skip-if = toolkit != "gtk" && toolkit != "windows"
- headless = true
- 
- [test_headless_clipboard.js]
- [test_headless.js]
- support-files =
-   headless.html
-   headless_button.html
-diff --git a/widget/moz.build b/widget/moz.build
---- a/widget/moz.build
-+++ b/widget/moz.build
-@@ -78,17 +78,17 @@ TEST_DIRS += ['tests']
- DIRS += ['headless']
- 
- # Don't build the DSO under the 'build' directory as windows does.
- #
- # The DSOs get built in the toolkit dir itself.  Do this so that
- # multiple implementations of widget can be built on the same
- # source tree.
- #
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     DIRS += ['gtk']
- 
-     if CONFIG['MOZ_X11']:
-         DIRS += ['gtkxtbin']
- 
-     XPIDL_SOURCES += [
-         'nsIGtkTaskbarProgress.idl',
-         'nsITaskbarProgress.idl',
-@@ -265,27 +265,27 @@ if toolkit == 'windows':
-         'PluginWidgetProxy.cpp',
-     ]
- 
- if toolkit in ('cocoa', 'windows'):
-     UNIFIED_SOURCES += [
-         'nsBaseClipboard.cpp',
-     ]
- 
--if toolkit in {'gtk3', 'cocoa', 'windows',
-+if toolkit in {'gtk', 'cocoa', 'windows',
-                'android', 'uikit'}:
-     UNIFIED_SOURCES += [
-         'nsBaseFilePicker.cpp',
-     ]
- 
--if toolkit in ('gtk3', 'windows', 'cocoa', 'android'):
-+if toolkit in ('gtk', 'windows', 'cocoa', 'android'):
-     UNIFIED_SOURCES += [
-         'nsNativeTheme.cpp',
-     ]
--if toolkit == 'gtk3':
-+if toolkit == 'gtk':
-     XPIDL_SOURCES += [
-         'nsIApplicationChooser.idl',
-     ]
- 
- DEFINES['MOZ_CROSS_PROCESS_IME'] = True
- 
- include('/ipc/chromium/chromium-config.mozbuild')
- 
-@@ -304,35 +304,31 @@ LOCAL_INCLUDES += [
- ]
- 
- if toolkit == 'windows':
-     IPDL_SOURCES = [
-         'headless/HeadlessWidgetTypes.ipdlh',
-         'windows/PCompositorWidget.ipdl',
-         'windows/PlatformWidgetTypes.ipdlh',
-     ]
--elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT'] and CONFIG['MOZ_X11']:
-+elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk' and CONFIG['MOZ_X11']:
-     IPDL_SOURCES = [
-         'gtk/PCompositorWidget.ipdl',
-         'gtk/PlatformWidgetTypes.ipdlh',
-         'headless/HeadlessWidgetTypes.ipdlh',
-     ]
- else:
-     IPDL_SOURCES = [
-         'headless/HeadlessWidgetTypes.ipdlh',
-         'PCompositorWidget.ipdl',
-         'PlatformWidgetTypes.ipdlh',
-     ]
- 
--widget_dir = toolkit
--if widget_dir == 'gtk3':
--    widget_dir = 'gtk'
--
- LOCAL_INCLUDES += [
--    '/widget/%s' % widget_dir,
-+    '/widget/%s' % toolkit,
- ]
- FINAL_LIBRARY = 'xul'
- 
- if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
-     DEFINES['MOZ_ENABLE_D3D10_LAYER'] = True
- 
- CXXFLAGS += CONFIG['TK_CFLAGS']
- if CONFIG['MOZ_WAYLAND']:
-diff --git a/widget/tests/chrome.ini b/widget/tests/chrome.ini
---- a/widget/tests/chrome.ini
-+++ b/widget/tests/chrome.ini
-@@ -87,17 +87,17 @@ support-files = file_secure_input.html
- skip-if = toolkit != "cocoa"
- [test_native_key_bindings_mac.html]
- skip-if = toolkit != "cocoa" || verify
- [test_system_status_bar.xul]
- skip-if = toolkit != "cocoa"
- 
- [test_system_font_changes.xul]
- support-files = system_font_changes.xul
--run-if = toolkit == 'gtk3' # Currently the test works on only gtk3
-+run-if = toolkit == 'gtk' # Currently the test works on only gtk3
- 
- # Windows
- # taskbar_previews.xul
- # window_state_windows.xul
- [test_chrome_context_menus_win.xul]
- skip-if = toolkit != "windows"
- support-files = chrome_context_menus_win.xul
- [test_plugin_input_event.html]
-diff --git a/xpcom/base/moz.build b/xpcom/base/moz.build
---- a/xpcom/base/moz.build
-+++ b/xpcom/base/moz.build
-@@ -241,10 +241,10 @@ FINAL_LIBRARY = 'xul'
- LOCAL_INCLUDES += [
-     '../build',
-     '/dom/base',
-     '/mfbt',
-     '/netwerk/base',
-     '/xpcom/ds',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['TK_CFLAGS']
-diff --git a/xpcom/components/moz.build b/xpcom/components/moz.build
---- a/xpcom/components/moz.build
-+++ b/xpcom/components/moz.build
-@@ -68,15 +68,15 @@ LOCAL_INCLUDES += [
-     '../build',
-     '../ds',
-     '/chrome',
-     '/js/xpconnect/loader',
-     '/layout/build',
-     '/modules/libjar',
- ]
- 
--if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['TK_CFLAGS']
- 
- if CONFIG['MOZ_LAYOUT_DEBUGGER']:
-     DEFINES['MOZ_LAYOUT_DEBUGGER'] = True
- 
- include('/ipc/chromium/chromium-config.mozbuild')
-diff --git a/xpcom/glue/standalone/moz.build b/xpcom/glue/standalone/moz.build
---- a/xpcom/glue/standalone/moz.build
-+++ b/xpcom/glue/standalone/moz.build
-@@ -27,10 +27,10 @@ LOCAL_INCLUDES += [
-     '../../threads',
- ]
- 
- # Don't use STL wrappers here (i.e. wrapped <new>); they require mozalloc
- DisableStlWrapping()
- 
- DIST_INSTALL = True
- 
--if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
-+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk':
-     CXXFLAGS += CONFIG['GLIB_CFLAGS']

+ 0 - 323
frg/work-js/mozilla-release/patches/rebase-25318.patch

@@ -1,323 +0,0 @@
-# HG changeset patch
-# User Frank-Rainer Grahl <frgrahl@gmx.net>
-# Date 1692567806 -7200
-# Parent  a1050850ce4844982a17dee7e84f840833ffbc4a
-stuff
-
-diff --git a/js/src/irregexp/RegExpAPI.cpp b/js/src/irregexp/RegExpAPI.cpp
---- a/js/src/irregexp/RegExpAPI.cpp
-+++ b/js/src/irregexp/RegExpAPI.cpp
-@@ -1,9 +1,10 @@
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * vim: set ts=8 sts=2 et sw=2 tw=80:
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- // Copyright 2020 the V8 project authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
-@@ -605,17 +608,17 @@ bool CompilePattern(JSContext* cx, Mutab
-   data.error = AnalyzeRegExp(cx->isolate, isLatin1, data.node);
-   if (data.error != RegExpError::kNone) {
-     MOZ_ASSERT(data.error == RegExpError::kAnalysisStackOverflow);
-     ReportOverRecursed(cx);
-     return false;
-   }
- 
-   bool useNativeCode = codeKind == RegExpShared::CodeKind::Jitcode;
--  MOZ_ASSERT_IF(useNativeCode, IsNativeRegExpEnabled(cx));
-+  MOZ_ASSERT_IF(useNativeCode, IsNativeRegExpEnabled());
- 
-   switch (Assemble(cx, &compiler, &data, re, pattern, &zone, useNativeCode,
-                    isLatin1)) {
-     case AssembleResult::TooLarge:
-       JS_ReportErrorASCII(cx, "regexp too big");
-       return false;
-     case AssembleResult::OutOfMemory:
-       ReportOutOfMemory(cx);
-diff --git a/js/src/irregexp/RegExpNativeMacroAssembler.h b/js/src/irregexp/RegExpNativeMacroAssembler.h
---- a/js/src/irregexp/RegExpNativeMacroAssembler.h
-+++ b/js/src/irregexp/RegExpNativeMacroAssembler.h
-@@ -1,9 +1,10 @@
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * vim: set ts=8 sts=2 et sw=2 tw=80:
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- // Copyright 2020 the V8 project authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
-@@ -33,17 +34,17 @@ struct FrameData {
-   int32_t* matches;    // pointer to capture array
-   int32_t numMatches;  // size of capture array
- };
- 
- class SMRegExpMacroAssembler final : public NativeRegExpMacroAssembler {
-  public:
-   SMRegExpMacroAssembler(JSContext* cx, js::jit::StackMacroAssembler& masm,
-                          Zone* zone, Mode mode, uint32_t num_capture_registers);
--  virtual ~SMRegExpMacroAssembler() {}  // Nothing to do here
-+  virtual ~SMRegExpMacroAssembler() = default;
- 
-   virtual int stack_limit_slack();
-   virtual IrregexpImplementation Implementation();
- 
-   virtual bool Succeed();
-   virtual void Fail();
- 
-   virtual void AdvanceCurrentPosition(int by);
-diff --git a/js/src/irregexp/RegExpShim.cpp b/js/src/irregexp/RegExpShim.cpp
---- a/js/src/irregexp/RegExpShim.cpp
-+++ b/js/src/irregexp/RegExpShim.cpp
-@@ -1,9 +1,10 @@
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-+ * vim: set ts=8 sts=2 et sw=2 tw=80:
-  * This Source Code Form is subject to the terms of the Mozilla Public
-  * License, v. 2.0. If a copy of the MPL was not distributed with this
-  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
- // Copyright 2019 the V8 project authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- 
-diff --git a/js/src/irregexp/RegExpShim.h b/js/src/irregexp/RegExpShim.h
---- a/js/src/irregexp/RegExpShim.h
-+++ b/js/src/irregexp/RegExpShim.h
-@@ -555,17 +555,17 @@ inline int HexValue(uc32 c) {
- 
- // V8::Object ~= JS::Value
- class Object {
-  public:
-   // The default object constructor in V8 stores a nullptr,
-   // which has its low bit clear and is interpreted as Smi(0).
-   constexpr Object() : asBits_(JS::Int32Value(0).asRawBits()) {}
- 
--  Object(const JS::Value& value) { setValue(value); }
-+  Object(const JS::Value& value) : asBits_(value.asRawBits()) {}
- 
-   // Used in regexp-interpreter.cc to check the return value of
-   // isolate->stack_guard()->HandleInterrupts(). We want to handle
-   // interrupts in the caller, so we always return false from
-   // HandleInterrupts and true here.
-   inline bool IsException(Isolate*) const {
-     MOZ_ASSERT(!value().toBoolean());
-     return true;
-@@ -686,18 +686,18 @@ class ByteArray : public HeapObject {
- // manually moved out of the arena using takeOwnership.
- 
- class MOZ_STACK_CLASS HandleScope {
-  public:
-   HandleScope(Isolate* isolate);
-   ~HandleScope();
- 
-  private:
--  size_t level_;
--  size_t non_gc_level_;
-+  size_t level_ = 0;
-+  size_t non_gc_level_ = 0;
-   Isolate* isolate_;
- 
-   friend class Isolate;
- };
- 
- // Origin:
- // https://github.com/v8/v8/blob/5792f3587116503fc047d2f68c951c72dced08a5/src/handles/handles.h#L88-L171
- template <typename T>
-@@ -988,17 +988,17 @@ class JSRegExp : public HeapObject {
-     kDotAll = JS::RegExpFlag::DotAll,
-   };
-   using Flags = JS::RegExpFlags;
- 
-   static constexpr int kNoBacktrackLimit = 0;
- 
-  private:
-   js::RegExpShared* inner() const {
--    return static_cast<js::RegExpShared*>(value().toGCThing());
-+    return value().toGCThing()->as<js::RegExpShared>();
-   }
- };
- 
- class Histogram {
-  public:
-   inline void AddSample(int sample) {}
- };
- 
-@@ -1116,18 +1116,18 @@ class Isolate {
-     handleArena_.PopLastN(currLevel - prevLevel);
- 
-     size_t currUniqueLevel = uniquePtrArena_.Length();
-     uniquePtrArena_.PopLastN(currUniqueLevel - prevUniqueLevel);
-   }
-   friend class HandleScope;
- 
-   JSContext* cx_;
--  RegExpStack* regexpStack_;
--  Counters counters_;
-+  RegExpStack* regexpStack_{};
-+  Counters counters_{};
- };
- 
- // Origin:
- // https://github.com/v8/v8/blob/50dcf2af54ce27801a71c47c1be1d2c5e36b0dd6/src/execution/isolate.h#L1909-L1931
- class StackLimitCheck {
-  public:
-   StackLimitCheck(Isolate* isolate) : cx_(isolate->cx()) {}
- 
-@@ -1166,17 +1166,17 @@ class Code : public HeapObject {
-   static Code cast(Object object) {
-     Code c;
-     js::gc::Cell* jitCode = object.value().toGCThing();
-     MOZ_ASSERT(jitCode->is<js::jit::JitCode>());
-     c.setValue(JS::PrivateGCThingValue(jitCode));
-     return c;
-   }
-   js::jit::JitCode* inner() {
--    return static_cast<js::jit::JitCode*>(value().toGCThing());
-+    return value().toGCThing()->as<js::jit::JitCode>();
-   }
- };
- 
- enum class MessageTemplate { kStackOverflow };
- 
- class MessageFormatter {
-  public:
-   static const char* TemplateString(MessageTemplate index) {
-diff --git a/js/src/irregexp/imported/regexp-parser.h b/js/src/irregexp/imported/regexp-parser.h
---- a/js/src/irregexp/imported/regexp-parser.h
-+++ b/js/src/irregexp/imported/regexp-parser.h
-@@ -331,19 +331,17 @@ class V8_EXPORT_PRIVATE RegExpParser {
-   uc32 ReadNext();
-   FlatStringReader* in() { return in_; }
-   void ScanForCaptures();
- 
-   struct RegExpCaptureNameLess {
-     bool operator()(const RegExpCapture* lhs, const RegExpCapture* rhs) const {
-       DCHECK_NOT_NULL(lhs);
-       DCHECK_NOT_NULL(rhs);
--      ZoneVector<uc16> lhname = *lhs->name();
--      ZoneVector<uc16> rhname = *rhs->name();
--      return lhname < rhname;
-+      return *lhs->name() < *rhs->name();
-     }
-   };
- 
-   Isolate* isolate_;
-   Zone* zone_;
-   RegExpError error_ = RegExpError::kNone;
-   int error_pos_ = 0;
-   ZoneList<RegExpCapture*>* captures_;
-diff --git a/js/src/irregexp/util/FlagsShim.h b/js/src/irregexp/util/FlagsShim.h
---- a/js/src/irregexp/util/FlagsShim.h
-+++ b/js/src/irregexp/util/FlagsShim.h
-@@ -21,62 +21,68 @@ namespace base {
- // other enum value and passed on to a function that takes an int or unsigned
- // int.
- template <typename T, typename S = int>
- class Flags final {
-  public:
-   using flag_type = T;
-   using mask_type = S;
- 
--  Flags() : mask_(0) {}
--  Flags(flag_type flag) : mask_(static_cast<S>(flag)) {}
--  Flags(mask_type mask) : mask_(static_cast<S>(mask)) {}
-+  constexpr Flags() : mask_(0) {}
-+  constexpr Flags(flag_type flag) : mask_(static_cast<S>(flag)) {}
-+  constexpr explicit Flags(mask_type mask) : mask_(static_cast<S>(mask)) {}
- 
--  bool operator==(flag_type flag) const {
-+  constexpr bool operator==(flag_type flag) const {
-     return mask_ == static_cast<S>(flag);
-   }
--  bool operator!=(flag_type flag) const {
-+  constexpr bool operator!=(flag_type flag) const {
-     return mask_ != static_cast<S>(flag);
-   }
- 
-   Flags& operator&=(const Flags& flags) {
-     mask_ &= flags.mask_;
-     return *this;
-   }
-   Flags& operator|=(const Flags& flags) {
-     mask_ |= flags.mask_;
-     return *this;
-   }
-   Flags& operator^=(const Flags& flags) {
-     mask_ ^= flags.mask_;
-     return *this;
-   }
- 
--  Flags operator&(const Flags& flags) const {
-+  constexpr Flags operator&(const Flags& flags) const {
-     return Flags(mask_ & flags.mask_);
-   }
--  Flags operator|(const Flags& flags) const {
-+  constexpr Flags operator|(const Flags& flags) const {
-     return Flags(mask_ | flags.mask_);
-   }
--  Flags operator^(const Flags& flags) const {
-+  constexpr Flags operator^(const Flags& flags) const {
-     return Flags(mask_ ^ flags.mask_);
-   }
- 
-   Flags& operator&=(flag_type flag) { return operator&=(Flags(flag)); }
-   Flags& operator|=(flag_type flag) { return operator|=(Flags(flag)); }
-   Flags& operator^=(flag_type flag) { return operator^=(Flags(flag)); }
- 
--  Flags operator&(flag_type flag) const { return operator&(Flags(flag)); }
--  Flags operator|(flag_type flag) const { return operator|(Flags(flag)); }
--  Flags operator^(flag_type flag) const { return operator^(Flags(flag)); }
-+  constexpr Flags operator&(flag_type flag) const {
-+    return operator&(Flags(flag));
-+  }
-+  constexpr Flags operator|(flag_type flag) const {
-+    return operator|(Flags(flag));
-+  }
-+  constexpr Flags operator^(flag_type flag) const {
-+    return operator^(Flags(flag));
-+  }
- 
--  Flags operator~() const { return Flags(~mask_); }
-+  constexpr Flags operator~() const { return Flags(~mask_); }
- 
--  operator mask_type() const { return mask_; }
--  bool operator!() const { return !mask_; }
-+  constexpr operator mask_type() const { return mask_; }
-+  constexpr bool operator!() const { return !mask_; }
- 
-   Flags without(flag_type flag) { return *this & (~Flags(flag)); }
- 
-   friend size_t hash_value(const Flags& flags) { return flags.mask_; }
- 
-  private:
-   mask_type mask_;
- };
-diff --git a/js/src/irregexp/util/VectorShim.h b/js/src/irregexp/util/VectorShim.h
---- a/js/src/irregexp/util/VectorShim.h
-+++ b/js/src/irregexp/util/VectorShim.h
-@@ -43,19 +43,19 @@ void DeleteArray(T* array) {
- // A non-resizable vector containing a pointer and a length.
- // The Vector may or may not own the pointer, depending on context.
- // Origin:
- // https://github.com/v8/v8/blob/5f69bbc233c2d1baf149faf869a7901603929914/src/utils/vector.h#L20-L134
- 
- template <typename T>
- class Vector {
-  public:
--  Vector() : start_(nullptr), length_(0) {}
-+  constexpr Vector() : start_(nullptr), length_(0) {}
- 
--  Vector(T* data, size_t length) : start_(data), length_(length) {
-+  constexpr Vector(T* data, size_t length) : start_(data), length_(length) {
-     MOZ_ASSERT_IF(length != 0, data != nullptr);
-   }
- 
-   static Vector<T> New(size_t length) {
-     return Vector<T>(NewArray<T>(length), length);
-   }
- 
-   // Returns a vector using the same backing storage as this one,

+ 30 - 52
frg/work-js/mozilla-release/patches/series

@@ -3620,7 +3620,7 @@ NOBUG-20180508-hashtable-62a1.patch
 1453990-62a1.patch
 1459850-62a1.patch
 1461034-62a1.patch
-1460381-62a1.patch
+1460381-3-62a1.patch
 1459225-62a1.patch
 1455954-62a1.patch
 1460436-62a1.patch
@@ -7460,18 +7460,44 @@ TOP-NOBUG-REGEXP-44-irregexp-25318.patch
 TOP-NOBUG-REGEXP-45-final-25318.patch
 TOP-NOBUG-REGEXP-46-fixes-25318.patch
 TOP-NOBUG-REGEXP-47-fixes-25319.patch
+1401146-58a1.patch
+1464758-62a1.patch
+1466487-62a1.patch
+1466363-62a1.patch
+1466893-1-62a1.patch
+1466893-2-62a1.patch
+1441098-1-62a1.patch
+1441098-2-62a1.patch
+1441098-3-62a1.patch
+1441098-4-62a1.patch
+1468792-62a1.patch
+1471134-1-63a1.patch
+1471134-2-63a1.patch
+1471134-3-63a1.patch
+1471134-4-63a1.patch
+1471134-5-63a1.patch
+1478503-63a1.patch
+1481032-63a1.patch
+1480963-63a1.patch
+1486173-1-63a1.patch
+1486173-2-63a1.patch
+1486173-3-63a1.patch
+1485698-63a1.patch
+1488698-2-PARTIAL-biginttype-64a1.patch
+bumm-compile-error
 
 
-bumm-compile-error
 L-1462261-1-62a1.patch
 L-1462261-2-62a1.patch
 1473003-1-63a1.patch
 
 
-rebase-25318.patch
-bbb.patch
 
 new-top
+1490387-1-64a1.patch
+1490387-2-64a1.patch
+1490387-3-64a1.patch
+1492669-65a1.patch
 
 1464869-08-62a1.patch
 mozilla-esr78-push_446333.patch
@@ -7485,9 +7511,6 @@ mozilla-esr78-push_446335.patch
 
 
 ssssssssssssss
-TOP-NOBUG-REGEXP-1-Import-25318.patch
-TOP-NOBUG-REGEXP-2-buildit-25318.patch
-TOP-NOBUG-REGEXP-2-buildit-25318-rebase.patch
 
 
 
@@ -7668,7 +7691,6 @@ L-1245571-BACKOUT-amwebapi-25317.patch
 L-1579084-transportprovider-25317.patch
 
 L-1433685-68a1.patch
-L-1535226-68a1.patch
 mozilla-esr78-push_549852.patch
 a.patch
 
@@ -8077,8 +8099,6 @@ mozilla-esr60_449499.patch
 
 L-mozilla-esr60_437311.patch
 L-mozilla-esr60_437902.patch
-L-mozilla-esr78-push_472400.patch
-L-mozilla-esr78-push_472961.patch
 
 
 
@@ -8129,22 +8149,6 @@ python-3-end
 0892-Some-small-issues-to-address-buildability.patch
 0893-Make-everything-build-on-supported-compilers.patch
 0903-Comment-out-undefined-code-for-now.patch
-0910-Bug-1452982-part-1-Use-rt-mainContextFromOwnThread-i.patch
-0911-Bug-1452982-part-2-Move-debuggerList-from-ZoneGroup-.patch
-0912-Bug-1452982-part-3-Remove-ZoneGroup-nursery-storeBuf.patch
-0913-Bug-1452982-part-4-Move-jit-related-fields-from-Zone.patch
-0914-Bug-1452982-part-4.2.patch
-0915-Bug-1452982-part-5-Refactor-JitRuntime-isOptimizatio.patch
-0916-Bug-1452982-part-6-Remove-ZoneGroup.patch
-0917-Bug-1452982-part-7-Rename-ZoneGroupData-to-ZoneData.patch
-0918-Bug-1452982-part-8-Remove-ZoneGroup.h-cpp-files.patch
-0919-Bug-1452982-part-9-Remove-rename-remaining-ZoneGroup.patch
-0920-Bug-1452982-part-10-Rename-ActiveCooperatingThread-t.patch
-0921-Bug-1452982-part-11-Rename-ActiveThread-to-MainThrea.patch
-0922-Bug-1452982-part-12-Clean-up-ContextKind-and-CheckTh.patch
-0923-Bug-1452982-part-13-Misc-cleanup-related-to-cooperat.patch
-0924-Bug-1452982-part-14-Rename-active-thread-to-main-thr.patch
-0925-Bug-1452982-part-15-Rename-some-constants.patch
 0926-Bug-1456494-Initialize-Zone-helperThreadUse_-first-t.patch
 0928-Fix-unified-debug-build-bustage.-2197.patch
 0974-Remove-unnecessary-flag.patch
@@ -8429,11 +8433,6 @@ js-patches-start
 
 1172572-1-70a1.patch
 
-mozilla-central_419570.patch
-mozilla-central_419571.patch
-mozilla-central_419572.patch
-mozilla-central_419573.patch
-L-1485698-63a1.patch
 mozilla-central_518695.patch
 js-patches-end
 mozilla-esr91-push_538632.patch
@@ -8518,8 +8517,6 @@ L-1745566-916.patch
 
 
 start-servo-58-patches
-L-1429656-59a1.patch
-L-1430299-59a1.patch
 mozilla-release58_438300.patch
 mozilla-release58_439057.patch
 mozilla-release58_441476.patch
@@ -9671,11 +9668,8 @@ L-1373878-3-58a1.patch
 
 
 L-1373878-4-58a1.patch
-mozilla-central_476624.patch
-mozilla-central_480696.patch
 L-1500356-2-harfbuzz230-66a1.patch
 mozilla-central_489031.patch
-mozilla-central_489301.patch
 mozilla-release58_425695.patch
 mozilla-central_489590.patch
 mozilla-central_495732.patch
@@ -9799,7 +9793,6 @@ L-1482828-63a1.patch
 L-1484668-63a1.patch
 L-1484987-63a1.patch
 L-1488186-63a1.patch
-L-1453456-3-61a1.patch
 L-1453456-4-67a1.patch
 L-1453456-5-67a1.patch
 L-1453456-6-67a1.patch
@@ -10177,7 +10170,6 @@ L-mozilla-release58_435830.patch
 L-mozilla-release58_436025.patch
 X-mozilla-release58_435896.patch
 L-mozilla-release58_435903.patch
-L-mozilla-release58_435910.patch
 L-mozilla-release58_435952.patch
 L-mozilla-release58_436023.patch
 WIP-NOBUG-WFX-modulecrash-25312.patch
@@ -10299,7 +10291,6 @@ mozilla-central-push_421052.patch
 mozilla-central-push_421053.patch
 mozilla-central-push_421054.patch
 mozilla-central-push_421066.patch
-mozilla-central-push_421127.patch
 
 the-taken-out-stuff-start.patch
 I-am-here.patch
@@ -10360,12 +10351,7 @@ mozilla-central-push_422014.patch
 mozilla-central-push_422015.patch
 mozilla-central-push_422043.patch
 mozilla-central-push_422046.patch
-mozilla-central-push_422049.patch
-mozilla-central-push_422050.patch
 mozilla-central-push_422052.patch
-mozilla-central-push_422053.patch
-mozilla-central-push_422054.patch
-mozilla-central-push_422055.patch
 mozilla-central-push_422056.patch
 mozilla-central-push_422291.patch
 mozilla-central-push_422298.patch
@@ -10465,9 +10451,7 @@ mozilla-central-push_423303.patch
 mozilla-central-push_423353.patch
 mozilla-central-push_423354.patch
 mozilla-central-push_423355.patch
-mozilla-central-push_423356.patch
 mozilla-central-push_423357.patch
-mozilla-central-push_423358.patch
 mozilla-central-push_423359.patch
 mozilla-central-push_423362.patch
 mozilla-central-push_423363.patch
@@ -10481,14 +10465,8 @@ mozilla-central-push_423435.patch
 mozilla-central-push_423436.patch
 mozilla-central-push_423440.patch
 bbbbbbbbbbbbbbbbbbbbbbbbbb
-1461305
-1466363
-1478503
 1494752 check 604 patch
 1532851
-1485698
-1466487
-1468792
 cccccccccccccccccccccccccccc