--- old/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh 2017-11-30 10:46:54.953458573 -0800 +++ new/src/java.desktop/share/native/libfontmanager/harfbuzz/hb-open-type-private.hh 2017-11-30 10:46:54.809458577 -0800 @@ -30,6 +30,8 @@ #define HB_OPEN_TYPE_PRIVATE_HH #include "hb-private.hh" +#include "hb-debug.hh" +#include "hb-face-private.hh" namespace OT { @@ -84,7 +86,7 @@ #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ inline void _instance_assertion_on_line_##_line (void) const \ { \ - ASSERT_STATIC (_assertion); \ + static_assert ((_assertion), ""); \ ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \ } # define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion) @@ -129,14 +131,16 @@ */ /* Global nul-content Null pool. Enlarge as necessary. */ -/* TODO This really should be a extern HB_INTERNAL and defined somewhere... */ -static const void *_NullPool[(256+8) / sizeof (void *)]; + +#define HB_NULL_POOL_SIZE 264 +static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE."); +extern HB_INTERNAL const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)]; /* Generic nul-content Null objects. */ template static inline const Type& Null (void) { - ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool)); - return *CastP (_NullPool); + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + return *CastP (_hb_NullPool); } /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ @@ -146,7 +150,7 @@ /*static*/ inline const Type& Null (void) { \ return *CastP (_Null##Type); \ } /* The following line really exists such that we end in a place needing semicolon */ \ -ASSERT_STATIC (Type::min_size + 1 <= sizeof (_Null##Type)) +static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") /* Accessor macro. */ #define Null(Type) Null() @@ -171,16 +175,6 @@ * Sanitize */ -#ifndef HB_DEBUG_SANITIZE -#define HB_DEBUG_SANITIZE (HB_DEBUG+0) -#endif - - -#define TRACE_SANITIZE(this) \ - hb_auto_trace_t trace \ - (&c->debug_depth, c->get_name (), this, HB_FUNC, \ - ""); - /* This limits sanitizing time on really broken fonts. */ #ifndef HB_SANITIZE_MAX_EDITS #define HB_SANITIZE_MAX_EDITS 32 @@ -191,9 +185,9 @@ { inline hb_sanitize_context_t (void) : debug_depth (0), - start (NULL), end (NULL), + start (nullptr), end (nullptr), writable (false), edit_count (0), - blob (NULL) {} + blob (nullptr) {} inline const char *get_name (void) { return "SANITIZE"; } template @@ -213,7 +207,7 @@ inline void start_processing (void) { - this->start = hb_blob_get_data (this->blob, NULL); + this->start = hb_blob_get_data (this->blob, nullptr); this->end = this->start + hb_blob_get_length (this->blob); assert (this->start <= this->end); /* Must not overflow. */ this->edit_count = 0; @@ -232,8 +226,8 @@ this->start, this->end, this->edit_count); hb_blob_destroy (this->blob); - this->blob = NULL; - this->start = this->end = NULL; + this->blob = nullptr; + this->start = this->end = nullptr; } inline bool check_range (const void *base, unsigned int len) const @@ -348,7 +342,7 @@ } else { unsigned int edit_count = c->edit_count; if (edit_count && !c->writable) { - c->start = hb_blob_get_data_writable (blob, NULL); + c->start = hb_blob_get_data_writable (blob, nullptr); c->end = c->start + hb_blob_get_length (blob); if (c->start) { @@ -373,7 +367,7 @@ static const Type* lock_instance (hb_blob_t *blob) { hb_blob_make_immutable (blob); - const char *base = hb_blob_get_data (blob, NULL); + const char *base = hb_blob_get_data (blob, nullptr); return unlikely (!base) ? &Null(Type) : CastP (base); } }; @@ -384,16 +378,6 @@ * Serialize */ -#ifndef HB_DEBUG_SERIALIZE -#define HB_DEBUG_SERIALIZE (HB_DEBUG+0) -#endif - - -#define TRACE_SERIALIZE(this) \ - hb_auto_trace_t trace \ - (&c->debug_depth, "SERIALIZE", c, HB_FUNC, \ - ""); - struct hb_serialize_context_t { @@ -444,7 +428,7 @@ { if (unlikely (this->ran_out_of_room || this->end - this->head < ptrdiff_t (size))) { this->ran_out_of_room = true; - return NULL; + return nullptr; } memset (this->head, 0, size); char *ret = this->head; @@ -470,7 +454,7 @@ { unsigned int size = obj.get_size (); Type *ret = this->allocate_size (size); - if (unlikely (!ret)) return NULL; + if (unlikely (!ret)) return nullptr; memcpy (ret, obj, size); return ret; } @@ -480,7 +464,7 @@ { unsigned int size = obj.min_size; assert (this->start <= (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); - if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return NULL; + if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return nullptr; return reinterpret_cast (&obj); } @@ -489,7 +473,7 @@ { unsigned int size = obj.get_size (); assert (this->start < (char *) &obj && (char *) &obj <= this->head && (char *) &obj + size >= this->head); - if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return NULL; + if (unlikely (!this->allocate_size (((char *) &obj) + size - this->head))) return nullptr; return reinterpret_cast (&obj); } @@ -631,10 +615,11 @@ inline bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } inline bool operator != (const IntType &o) const { return !(*this == o); } static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } - inline int cmp (Type a) const + template + inline int cmp (Type2 a) const { Type b = v; - if (sizeof (Type) < sizeof (int)) + if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int)) return (int) a - (int) b; else return a < b ? -1 : a == b ? 0 : +1; @@ -650,9 +635,9 @@ DEFINE_SIZE_STATIC (Size); }; -typedef IntType CHAR; /* 8-bit signed integer. */ -typedef IntType BYTE; /* 8-bit unsigned integer. */ -typedef IntType INT8; /* 8-bit signed integer. */ +typedef IntType CHAR; /* 8-bit signed integer. */ +typedef IntType BYTE; /* 8-bit unsigned integer. */ +typedef IntType INT8; /* 8-bit signed integer. */ typedef IntType USHORT; /* 16-bit unsigned integer. */ typedef IntType SHORT; /* 16-bit signed integer. */ typedef IntType ULONG; /* 32-bit unsigned integer. */ @@ -712,10 +697,7 @@ DEFINE_NULL_DATA (Tag, " "); /* Glyph index number, same as uint16 (length = 16 bits) */ -struct GlyphID : USHORT { - static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); } - inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; } -}; +typedef USHORT GlyphID; /* Script/language-system/feature index */ struct Index : USHORT { @@ -829,6 +811,7 @@ } DEFINE_SIZE_STATIC (sizeof(OffsetType)); }; +template struct LOffsetTo : OffsetTo {}; template static inline const Type& operator + (const Base &base, const OffsetTo &offset) { return offset (base); } template @@ -941,7 +924,7 @@ inline bool sanitize_shallow (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && c->check_array (array, Type::static_size, len)); + return_trace (len.sanitize (c) && c->check_array (array, Type::static_size, len)); } public: @@ -950,6 +933,7 @@ public: DEFINE_SIZE_ARRAY (sizeof (LenType), array); }; +template struct LArrayOf : ArrayOf {}; /* Array of Offset's */ template @@ -1006,12 +990,6 @@ return_trace (true); } - inline bool sanitize_shallow (hb_sanitize_context_t *c) const - { - return c->check_struct (this) - && c->check_array (this, Type::static_size, len); - } - inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -1029,6 +1007,15 @@ return_trace (true); } + private: + inline bool sanitize_shallow (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (len.sanitize (c) && + (!len || c->check_array (array, Type::static_size, len - 1))); + } + + public: LenType len; Type array[VAR]; public: @@ -1036,7 +1023,9 @@ }; -/* An array with sorted elements. Supports binary searching. */ +/* + * An array with sorted elements. Supports binary searching. + */ template struct SortedArrayOf : ArrayOf { @@ -1044,11 +1033,12 @@ inline int bsearch (const SearchType &x) const { /* Hand-coded bsearch here since this is in the hot inner loop. */ + const Type *array = this->array; int min = 0, max = (int) this->len - 1; while (min <= max) { int mid = (min + max) / 2; - int c = this->array[mid].cmp (x); + int c = array[mid].cmp (x); if (c < 0) max = mid - 1; else if (c > 0) @@ -1060,6 +1050,131 @@ } }; +/* + * Binary-search arrays + */ + +struct BinSearchHeader +{ + inline operator uint32_t (void) const { return len; } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + protected: + USHORT len; + USHORT searchRangeZ; + USHORT entrySelectorZ; + USHORT rangeShiftZ; + + public: + DEFINE_SIZE_STATIC (8); +}; + +template +struct BinSearchArrayOf : SortedArrayOf {}; + + +/* Lazy struct and blob loaders. */ + +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ +template +struct hb_lazy_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = nullptr; + } + + inline void fini (void) + { + if (instance && instance != &OT::Null(T)) + { + instance->fini(); + free (instance); + } + } + + inline const T* get (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + p = (T *) calloc (1, sizeof (T)); + if (unlikely (!p)) + p = const_cast (&OT::Null(T)); + else + p->init (face); + if (unlikely (!hb_atomic_ptr_cmpexch (const_cast(&instance), nullptr, p))) + { + if (p != &OT::Null(T)) + p->fini (); + goto retry; + } + } + return p; + } + + inline const T* operator-> (void) const + { + return get (); + } + + private: + hb_face_t *face; + T *instance; +}; + +/* Logic is shared between hb_lazy_loader_t and hb_lazy_table_loader_t */ +template +struct hb_lazy_table_loader_t +{ + inline void init (hb_face_t *face_) + { + face = face_; + instance = nullptr; + blob = nullptr; + } + + inline void fini (void) + { + hb_blob_destroy (blob); + } + + inline const T* get (void) const + { + retry: + T *p = (T *) hb_atomic_ptr_get (&instance); + if (unlikely (!p)) + { + hb_blob_t *blob_ = OT::Sanitizer::sanitize (face->reference_table (T::tableTag)); + p = const_cast(OT::Sanitizer::lock_instance (blob_)); + if (!hb_atomic_ptr_cmpexch (const_cast(&instance), nullptr, p)) + { + hb_blob_destroy (blob_); + goto retry; + } + blob = blob_; + } + return p; + } + + inline const T* operator-> (void) const + { + return get(); + } + + private: + hb_face_t *face; + T *instance; + mutable hb_blob_t *blob; +}; + } /* namespace OT */