From fe05e48086be9ed685b8a6ca4af966660744bc0f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 15:06:25 -0700 Subject: [PATCH 01/25] [serialize] Add ran_out_of_room --- src/hb-serialize.hh | 8 +++++++- src/hb-subset.cc | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index f5e4df521..679ae4ed6 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -51,6 +51,7 @@ struct hb_serialize_context_t void reset () { this->successful = true; + this->ran_out_of_room = false; this->head = this->start; this->debug_depth = 0; } @@ -111,7 +112,11 @@ struct hb_serialize_context_t template Type *allocate_size (unsigned int size) { - if (unlikely (!this->successful || this->end - this->head < ptrdiff_t (size))) { + if (unlikely (!this->successful)) return nullptr; + + if (this->end - this->head < ptrdiff_t (size)) + { + this->ran_out_of_room = true; this->successful = false; return nullptr; } @@ -190,6 +195,7 @@ struct hb_serialize_context_t unsigned int debug_depth; char *start, *end, *head; bool successful; + bool ran_out_of_room; }; diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 135265fc1..b3f064697 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -83,7 +83,7 @@ _subset2 (hb_subset_plan_t *plan) hb_serialize_context_t serializer ((void *) buf, buf_size); hb_subset_context_t c (plan, &serializer); result = table->subset (&c); - if (serializer.in_error ()) + 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); @@ -94,6 +94,11 @@ _subset2 (hb_subset_plan_t *plan) } goto retry; } + if (serializer.in_error ()) + { + abort (); + } + if (result) { hb_blob_t *dest_blob = serializer.copy_blob (); From 6dcf7c4017619c782dbc8bd2c584bb33df96fc83 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 15:08:39 -0700 Subject: [PATCH 02/25] [serialize] Add unused 'tail' --- src/hb-serialize.hh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 679ae4ed6..ea389c0c0 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -53,6 +53,7 @@ struct hb_serialize_context_t this->successful = true; this->ran_out_of_room = false; this->head = this->start; + this->tail = this->end; this->debug_depth = 0; } @@ -114,7 +115,7 @@ struct hb_serialize_context_t { if (unlikely (!this->successful)) return nullptr; - if (this->end - this->head < ptrdiff_t (size)) + if (this->tail - this->head < ptrdiff_t (size)) { this->ran_out_of_room = true; this->successful = false; @@ -192,8 +193,8 @@ struct hb_serialize_context_t } public: + char *start, *head, *tail, *end; unsigned int debug_depth; - char *start, *end, *head; bool successful; bool ran_out_of_room; }; From 7fd940f899da4948d2c61ed497c1face42776187 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 16:29:19 -0700 Subject: [PATCH 03/25] [map] Add TODO --- src/hb-map.hh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hb-map.hh b/src/hb-map.hh index d36515a74..a2bbff5c1 100644 --- a/src/hb-map.hh +++ b/src/hb-map.hh @@ -46,6 +46,10 @@ struct hb_hashmap_t static_assert (hb_is_integer (K) || hb_is_pointer (K), ""); static_assert (hb_is_integer (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 { K key; @@ -248,6 +252,10 @@ struct hb_hashmap_t } }; +/* + * hb_map_t + */ + struct hb_map_t : hb_hashmap_t Date: Sat, 30 Mar 2019 16:38:06 -0700 Subject: [PATCH 04/25] [map] Add another TODO item --- src/hb-map.hh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hb-map.hh b/src/hb-map.hh index a2bbff5c1..341c15929 100644 --- a/src/hb-map.hh +++ b/src/hb-map.hh @@ -34,6 +34,8 @@ * hb_hashmap_t */ +/* TODO if K/V is signed integer, -1 is not a good default. + * Don't know how to get to -MAX using bit work. */ template From dbe9ba6711c6d35374de645097babfd81bc295b2 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 17:10:59 -0700 Subject: [PATCH 05/25] [serialize] Add object_t, link_t, and snapshot_t --- src/hb-serialize.hh | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index ea389c0c0..2af34dc07 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -55,6 +55,9 @@ struct hb_serialize_context_t this->head = this->start; this->tail = this->end; this->debug_depth = 0; + + this->packed.resize (1); + this->current.resize (0); } bool propagate_error (bool e) @@ -192,11 +195,38 @@ struct hb_serialize_context_t nullptr, nullptr); } - public: + public: /* TODO Make private. */ char *start, *head, *tail, *end; unsigned int debug_depth; bool successful; bool ran_out_of_room; + + private: + + /* Stack of packed objects. Object 0 is always nil object. */ + struct object_t + { + void fini () { links.fini (); } + + struct link_t + { + bool wide: 1; + unsigned offset : 31; + unsigned objidx; + }; + + hb_bytes_t bytes; + hb_vector_t links; + }; + hb_vector_t packed; + + /* Stack of currently under construction object locations. */ + struct snapshot_t + { + char *head, *tail; + }; + snapshot_t snapshot () { snapshot_t s = {head, tail} ; return s; } + hb_vector_t current; }; From 63c35651893b2a1c555f728012e9ad36c0f84145 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 17:12:40 -0700 Subject: [PATCH 06/25] [serialize] Simplify propagate_error() --- src/hb-serialize.hh | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 2af34dc07..8ca660f53 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -66,15 +66,10 @@ struct hb_serialize_context_t { return this->successful = this->successful && !obj.in_error (); } template bool propagate_error (const T *obj) { return this->successful = this->successful && !obj->in_error (); } - template bool propagate_error (T1 &o1, T2 &o2) - { return propagate_error (o1) && propagate_error (o2); } - template bool propagate_error (T1 *o1, T2 *o2) + template bool propagate_error (T1 &&o1, T2 &&o2) { return propagate_error (o1) && propagate_error (o2); } template - bool propagate_error (T1 &o1, T2 &o2, T3 &o3) - { return propagate_error (o1) && propagate_error (o2, o3); } - template - bool propagate_error (T1 *o1, T2 *o2, T3 *o3) + bool propagate_error (T1 &&o1, T2 &&o2, T3 &&o3) { return propagate_error (o1) && propagate_error (o2, o3); } /* To be called around main operation. */ From bed150bd2e8d61950ea17d1b5a4bf4705801c1cc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 17:26:35 -0700 Subject: [PATCH 07/25] [serialize] Start fleshing out object stack --- src/hb-serialize.hh | 91 ++++++++++++++++++++++++++++++++------------- src/hb-vector.hh | 9 +++-- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 8ca660f53..86f802a26 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -39,6 +39,30 @@ struct hb_serialize_context_t { + typedef unsigned objidx_t; + + struct object_t + { + void fini () { links.fini (); } + + struct link_t + { + bool wide: 1; + unsigned offset : 31; + objidx_t objidx; + }; + + hb_bytes_t bytes; + hb_vector_t links; + }; + + struct snapshot_t + { + char *head, *tail; + }; + snapshot_t snapshot () { snapshot_t s = {head, tail} ; return s; } + + hb_serialize_context_t (void *start_, unsigned int size) { this->start = (char *) start_; @@ -56,7 +80,8 @@ struct hb_serialize_context_t this->tail = this->end; this->debug_depth = 0; - this->packed.resize (1); + this->packed.resize (0); + this->packed.push ()->bytes.arrayZ = this->end; this->current.resize (0); } @@ -81,18 +106,53 @@ struct hb_serialize_context_t this->start, this->end, (unsigned long) (this->end - this->start)); - return start_embed (); + assert (!current.length); + return push (); } - void end_serialize () + objidx_t end_serialize () { DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, - "end [%p..%p] serialized %d bytes; %s", + "end [%p..%p] serialized %u bytes; %s", this->start, this->end, - (int) (this->head - this->start), + (unsigned) (this->head - this->start), this->successful ? "successful" : "UNSUCCESSFUL"); + assert (current.length == 1); + return pop_pack (); } - unsigned int length () const { return this->head - this->start; } + template + Type *push () + { + current.push (snapshot ()); + return start_embed (); + } + void pop_discard () + { + revert (current.pop ()); + } + objidx_t pop_pack () + { + return 0; + } + + void revert (snapshot_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 ().bytes.arrayZ < tail) + packed.pop (); + assert (packed.tail ().bytes.arrayZ == tail); + } + + unsigned int length () const { return this->head - current.tail ().head; } void align (unsigned int alignment) { @@ -199,28 +259,9 @@ struct hb_serialize_context_t private: /* Stack of packed objects. Object 0 is always nil object. */ - struct object_t - { - void fini () { links.fini (); } - - struct link_t - { - bool wide: 1; - unsigned offset : 31; - unsigned objidx; - }; - - hb_bytes_t bytes; - hb_vector_t links; - }; hb_vector_t packed; /* Stack of currently under construction object locations. */ - struct snapshot_t - { - char *head, *tail; - }; - snapshot_t snapshot () { snapshot_t s = {head, tail} ; return s; } hb_vector_t current; }; diff --git a/src/hb-vector.hh b/src/hb-vector.hh index 0354845c4..fd24950f7 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -87,6 +87,9 @@ struct hb_vector_t return arrayZ()[i]; } + Type& tail () { return (*this)[length - 1]; } + const Type& tail () const { return (*this)[length - 1]; } + explicit operator bool () const { return length; } /* Sink interface. */ @@ -188,10 +191,10 @@ struct hb_vector_t return true; } - void pop () + Type pop () { - if (!length) return; - length--; + if (!length) return Null(Type); + return arrayZ()[--length]; } void remove (unsigned int i) From a43290192beedc6335efc3841c05ec7fa54e8871 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 17:51:26 -0700 Subject: [PATCH 08/25] [serialize] Add packed_map --- src/hb-map.hh | 7 +++++++ src/hb-serialize.hh | 24 +++++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/hb-map.hh b/src/hb-map.hh index 341c15929..a176ccd28 100644 --- a/src/hb-map.hh +++ b/src/hb-map.hh @@ -96,6 +96,13 @@ struct hb_hashmap_t fini_shallow (); } + void reset () + { + /* TODO Keep array? */ + fini_shallow (); + init_shallow (); + } + bool in_error () const { return !successful; } bool resize () diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 86f802a26..6911e92a5 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -31,6 +31,7 @@ #include "hb.hh" #include "hb-blob.hh" +#include "hb-map.hh" /* @@ -80,9 +81,10 @@ struct hb_serialize_context_t this->tail = this->end; this->debug_depth = 0; + this->current.resize (0); this->packed.resize (0); this->packed.push ()->bytes.arrayZ = this->end; - this->current.resize (0); + this->packed_map.reset (); } bool propagate_error (bool e) @@ -132,6 +134,19 @@ struct hb_serialize_context_t } objidx_t pop_pack () { + snapshot_t snap = current.pop (); + + char *s = snap.head; + char *e = head; + unsigned l = e - s; + + tail -= l; + memmove (tail, s, l); + + /* TODO... */ + packed.push (); + + head = snap.head; return 0; } @@ -258,11 +273,14 @@ struct hb_serialize_context_t private: + /* Stack of currently under construction object locations. */ + hb_vector_t current; + /* Stack of packed objects. Object 0 is always nil object. */ hb_vector_t packed; - /* Stack of currently under construction object locations. */ - hb_vector_t current; + /* Map view of packed objects. */ + hb_hashmap_t packed_map; }; From 6f69c9d26fa53cd8a2331395bbc146bfc85fd1e3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 18:00:03 -0700 Subject: [PATCH 09/25] [serialize] Minor --- src/hb-serialize.hh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 6911e92a5..204055c60 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -53,7 +53,8 @@ struct hb_serialize_context_t objidx_t objidx; }; - hb_bytes_t bytes; + char *head; + unsigned length; hb_vector_t links; }; @@ -83,7 +84,7 @@ struct hb_serialize_context_t this->current.resize (0); this->packed.resize (0); - this->packed.push ()->bytes.arrayZ = this->end; + this->packed.push ()->head = this->end; this->packed_map.reset (); } @@ -162,9 +163,9 @@ struct hb_serialize_context_t void discard_stale_objects () { while (packed.length > 1 && - packed.tail ().bytes.arrayZ < tail) + packed.tail ().head < tail) packed.pop (); - assert (packed.tail ().bytes.arrayZ == tail); + assert (packed.tail ().head == tail); } unsigned int length () const { return this->head - current.tail ().head; } From 357c7c611cc20f86c646bd2d392c243140f92d34 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 18:13:57 -0700 Subject: [PATCH 10/25] [vector] Add copy constructor and assignment operator --- src/hb-vector.hh | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index fd24950f7..5b1a83c56 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -38,8 +38,13 @@ 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_iter (o) | hb_sink (this); + } ~hb_vector_t () { fini (); } unsigned int length; @@ -69,6 +74,16 @@ struct hb_vector_t fini (); } + void reset () { resize (0); } + + hb_vector_t& operator = (const hb_vector_t &o) + { + reset (); + alloc (o.length); + hb_iter (o) | hb_sink (this); + return *this; + } + const Type * arrayZ () const { return arrayZ_; } Type * arrayZ () { return arrayZ_; } From 9a19b885f9136b0b7cdfa04679274cd4b6d16188 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 18:14:30 -0700 Subject: [PATCH 11/25] [serialize] Flesh out packing --- src/hb-serialize.hh | 58 ++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 204055c60..828d23992 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -42,7 +42,12 @@ struct hb_serialize_context_t { typedef unsigned objidx_t; - struct object_t + struct range_t + { + char *head, *tail; + }; + + struct object_t : range_t { void fini () { links.fini (); } @@ -53,16 +58,10 @@ struct hb_serialize_context_t objidx_t objidx; }; - char *head; - unsigned length; hb_vector_t links; }; - struct snapshot_t - { - char *head, *tail; - }; - snapshot_t snapshot () { snapshot_t s = {head, tail} ; return s; } + range_t snapshot () { range_t s = {head, tail} ; return s; } hb_serialize_context_t (void *start_, unsigned int size) @@ -82,8 +81,8 @@ struct hb_serialize_context_t this->tail = this->end; this->debug_depth = 0; - this->current.resize (0); - this->packed.resize (0); + this->current.reset (); + this->packed.reset (); this->packed.push ()->head = this->end; this->packed_map.reset (); } @@ -119,6 +118,9 @@ struct hb_serialize_context_t this->start, this->end, (unsigned) (this->head - this->start), this->successful ? "successful" : "UNSUCCESSFUL"); + + /* TODO Propagate errors. */ + assert (current.length == 1); return pop_pack (); } @@ -126,7 +128,10 @@ struct hb_serialize_context_t template Type *push () { - current.push (snapshot ()); + object_t obj; + obj.head = head; + obj.tail = tail; + current.push (obj); return start_embed (); } void pop_discard () @@ -135,23 +140,27 @@ struct hb_serialize_context_t } objidx_t pop_pack () { - snapshot_t snap = current.pop (); + object_t obj = current.pop (); - char *s = snap.head; - char *e = head; - unsigned l = e - s; + unsigned len = head - obj.head; - tail -= l; - memmove (tail, s, l); + tail -= len; + memmove (tail, obj.head, len); + head = obj.head; - /* TODO... */ - packed.push (); + obj.head = tail; + obj.tail = tail + len; - head = snap.head; - return 0; + packed.push (obj); + + /* TODO Handle error. */ + if (unlikely (packed.in_error ())) + return 0; + + return packed.length - 1; } - void revert (snapshot_t snap) + void revert (range_t snap) { assert (snap.head <= head); assert (tail <= snap.tail); @@ -274,8 +283,9 @@ struct hb_serialize_context_t private: - /* Stack of currently under construction object locations. */ - hb_vector_t current; + /* Stack of currently under construction objects. */ + /* Note. We store the "end - tail" distance in the length member of these. */ + hb_vector_t current; /* Stack of packed objects. Object 0 is always nil object. */ hb_vector_t packed; From 7c9ceabcef426ca6fc54b70db9dd8cb63937710b Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 18:19:36 -0700 Subject: [PATCH 12/25] [meta] Add hb_move and hb_forward ala std:: --- src/hb-meta.hh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/hb-meta.hh b/src/hb-meta.hh index a303c67a7..63c8a8cf5 100644 --- a/src/hb-meta.hh +++ b/src/hb-meta.hh @@ -72,6 +72,17 @@ static const struct } hb_deref_pointer HB_UNUSED; +/* std::move and std::forward */ + +template +hb_remove_reference (T)&& hb_move (T&& t) { return (hb_remove_reference (T)&&) (t); } + +template +T&& hb_forward (hb_remove_reference (T)& t) { return (T&&) t; } +template +T&& hb_forward (hb_remove_reference (T)&& t) { return (T&&) t; } + + /* Void! For when we need a expression-type of void. */ struct hb_void_t { typedef void value; }; From 4c4d3c3ed55a8f1eea20593c08322e61fe1cdd3c Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 18:30:50 -0700 Subject: [PATCH 13/25] [vector] Add some move and forwarding --- src/hb-serialize.hh | 2 +- src/hb-vector.hh | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 828d23992..407a330a0 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -151,7 +151,7 @@ struct hb_serialize_context_t obj.head = tail; obj.tail = tail + len; - packed.push (obj); + packed.push (hb_move (obj)); /* TODO Handle error. */ if (unlikely (packed.in_error ())) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index 5b1a83c56..879340506 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -109,7 +109,7 @@ struct hb_vector_t /* Sink interface. */ template - hb_vector_t& operator << (const T& v) { push (v); return *this; } + hb_vector_t& operator << (T&& v) { push (hb_forward (v)); return *this; } hb_array_t< Type> as_array () { return hb_array (arrayZ(), length); } hb_array_t as_array () const { return hb_array (arrayZ(), length); } @@ -149,10 +149,10 @@ struct hb_vector_t return &arrayZ()[length - 1]; } template - Type *push (const T& v) + Type *push (T&& v) { Type *p = push (); - *p = v; + *p = hb_forward (v); return p; } @@ -209,7 +209,7 @@ struct hb_vector_t Type pop () { if (!length) return Null(Type); - return arrayZ()[--length]; + return hb_move (arrayZ()[--length]); /* Does this move actually work? */ } void remove (unsigned int i) From e6b78003efbe02ba4542cadcc13bc1dd0b1d57b0 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 18:33:30 -0700 Subject: [PATCH 14/25] [vector] Add move semantics --- src/hb-vector.hh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index 879340506..f68943987 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -45,6 +45,13 @@ struct hb_vector_t alloc (o.length); hb_iter (o) | hb_sink (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; @@ -83,6 +90,15 @@ struct hb_vector_t hb_iter (o) | hb_sink (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; + } const Type * arrayZ () const { return arrayZ_; } Type * arrayZ () { return arrayZ_; } From 10f062234eb7c762a36cf750e75fe6f74ee89a3d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 18:44:01 -0700 Subject: [PATCH 15/25] [map] Shuffle fini code --- src/hb-map.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-map.hh b/src/hb-map.hh index a176ccd28..f5c999170 100644 --- a/src/hb-map.hh +++ b/src/hb-map.hh @@ -88,10 +88,10 @@ struct hb_hashmap_t { free (items); items = nullptr; + population = occupancy = 0; } void fini () { - population = occupancy = 0; hb_object_fini (this); fini_shallow (); } From 0b1fe7b716628f7b7b4098da9ef544e1518008f5 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 18:48:26 -0700 Subject: [PATCH 16/25] [serializer] Unbreak for now --- src/hb-serialize.hh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 407a330a0..805ac492c 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -111,7 +111,7 @@ struct hb_serialize_context_t assert (!current.length); return push (); } - objidx_t end_serialize () + void end_serialize () { DEBUG_MSG_LEVEL (SERIALIZE, this->start, 0, -1, "end [%p..%p] serialized %u bytes; %s", @@ -122,7 +122,8 @@ struct hb_serialize_context_t /* TODO Propagate errors. */ assert (current.length == 1); - return pop_pack (); + /* TODO Enable when callers are updated. */ + //pop_pack (); } template From 8512dc565d310e9fd80d831282736284cc3ecd2e Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:01:23 -0700 Subject: [PATCH 17/25] [serialize] Simplify copy --- src/hb-serialize.hh | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 805ac492c..733536153 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -246,16 +246,6 @@ struct hb_serialize_context_t Type *extend (Type &obj) { return extend_size (obj, obj.get_size ()); } /* Output routines. */ - template - 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 (p); - } hb_bytes_t copy_bytes () const { assert (this->successful); @@ -267,13 +257,15 @@ struct hb_serialize_context_t return hb_bytes_t (); return hb_bytes_t ((char *) p, len); } + template + Type *copy () const + { return reinterpret_cast ((char *) copy_bytes ().arrayZ); } 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); + 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. */ From 946d446f9b795f657d56ca443edbc0b77d660a50 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:03:55 -0700 Subject: [PATCH 18/25] [serialize] Copy both sides of the buffer --- src/hb-serialize.hh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 733536153..7f3206702 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -249,13 +249,18 @@ struct hb_serialize_context_t hb_bytes_t copy_bytes () const { assert (this->successful); - unsigned int len = this->head - this->start; - void *p = malloc (len); + /* 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, len); + { + 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 ((char *) p, len); + return hb_bytes_t (p, len); } template Type *copy () const From f254f45a1e6b1de6d83c97033773d20408772763 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:05:51 -0700 Subject: [PATCH 19/25] [serialize] Only pack main object if there are other objects Avoids a memmove for tables that don't use the object packing mechanism. --- src/hb-serialize.hh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 7f3206702..617928815 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -122,8 +122,11 @@ struct hb_serialize_context_t /* TODO Propagate errors. */ assert (current.length == 1); - /* TODO Enable when callers are updated. */ - //pop_pack (); + + /* Only "pack" if there exist other objects... Otherwise, don't bother. + * Saves a copy. */ + if (packed.length > 1) + pop_pack (); } template From 7fd82283263f8caded4870d6e12f74c7e660fa8d Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:16:20 -0700 Subject: [PATCH 20/25] [serialize] Towards maintaining hashmap --- src/hb-algs.hh | 2 +- src/hb-serialize.hh | 16 ++++++++++++++-- src/hb-vector.hh | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index 128e49036..ab6782de3 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -45,7 +45,7 @@ static const struct template uint32_t operator () (const T *v) const - { return hb_hash (v); } + { return operator() (v); } template diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 617928815..e7873ab69 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -51,6 +51,14 @@ struct hb_serialize_context_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 == memcmp (head, o.head, tail - head) + && 0 == memcmp (&links, &o.links, links.get_size ()); + } + struct link_t { bool wide: 1; @@ -155,13 +163,17 @@ struct hb_serialize_context_t obj.head = tail; obj.tail = tail + len; - packed.push (hb_move (obj)); + object_t *key = packed.push (hb_move (obj)); /* TODO Handle error. */ if (unlikely (packed.in_error ())) return 0; - return packed.length - 1; + objidx_t objidx = packed.length - 1; + + packed_map.set (key, objidx); + + return objidx; } void revert (range_t snap) diff --git a/src/hb-vector.hh b/src/hb-vector.hh index f68943987..2a92a892e 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -122,6 +122,7 @@ struct hb_vector_t 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 From d74dc3ef65a159fe585e906deccdb32b570433aa Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:26:37 -0700 Subject: [PATCH 21/25] [serialize] Don't insert empty object into tree --- src/hb-serialize.hh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index e7873ab69..3bbff7541 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -160,6 +160,9 @@ struct hb_serialize_context_t memmove (tail, obj.head, len); head = obj.head; + if (!len) + return 0; + obj.head = tail; obj.tail = tail + len; @@ -304,7 +307,7 @@ struct hb_serialize_context_t hb_vector_t packed; /* Map view of packed objects. */ - hb_hashmap_t packed_map; + hb_hashmap_t packed_map; }; From d6b28057a5cc636138cd453947d3a2008f18729f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:31:51 -0700 Subject: [PATCH 22/25] Fix hb_hash(pointer) --- src/hb-algs.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index ab6782de3..c1b38e877 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -45,7 +45,7 @@ static const struct template uint32_t operator () (const T *v) const - { return operator() (v); } + { return operator() (*v); } template From b189bbc48fb4b7c251d30b26a57ad84d1cb6dbe4 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:41:48 -0700 Subject: [PATCH 23/25] Implement hashing of objects Should be improved for hb_bytes_t. --- src/hb-algs.hh | 2 +- src/hb-array.hh | 13 +++++++++++++ src/hb-serialize.hh | 5 +++++ src/hb-vector.hh | 5 +++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/hb-algs.hh b/src/hb-algs.hh index c1b38e877..adf5c483f 100644 --- a/src/hb-algs.hh +++ b/src/hb-algs.hh @@ -40,7 +40,7 @@ static const struct //{ return hb_deref_pointer (v).hash (); } /* Instead, the following ugly soution: */ template + hb_enable_if (!hb_is_integer (hb_remove_const (hb_remove_reference (T))) && !hb_is_pointer (T))> uint32_t operator () (T&& v) const { return v.hash (); } template diff --git a/src/hb-array.hh b/src/hb-array.hh index ab453f5a2..16f53cc8f 100644 --- a/src/hb-array.hh +++ b/src/hb-array.hh @@ -79,6 +79,8 @@ struct hb_array_t : hb_iter_with_fallback_t, Type&> operator hb_array_t () { return hb_array_t (arrayZ, length); } template operator T * () const { return arrayZ; } + uint32_t hash () const; + /* * Compare, Sort, and Search. */ @@ -273,9 +275,20 @@ template inline hb_sorted_array_t hb_sorted_array (T (&array_)[length_]) { return hb_sorted_array_t (array_); } +template +uint32_t hb_array_t::hash () const +{ + uint32_t h = 0; + for (unsigned i = 0; i < length; i++) + h ^= hb_hash (arrayZ[i]); + return h; +} typedef hb_array_t hb_bytes_t; typedef hb_array_t hb_ubytes_t; +/* TODO Specialize hashing for hb_bytes_t and hb_ubytes_t. */ +//template <> +//uint32_t hb_array_t::hash () const { return 0; } #endif /* HB_ARRAY_HH */ diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 3bbff7541..d8e1e2fb8 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -58,6 +58,11 @@ struct hb_serialize_context_t && 0 == memcmp (head, o.head, tail - head) && 0 == memcmp (&links, &o.links, links.get_size ()); } + uint32_t hash () const + { + return hb_bytes_t (head, tail - head).hash () ^ + links.as_bytes ().hash (); + } struct link_t { diff --git a/src/hb-vector.hh b/src/hb-vector.hh index 2a92a892e..4621b5134 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -100,6 +100,11 @@ struct hb_vector_t return *this; } + hb_bytes_t as_bytes () const { return hb_bytes_t ((const char *) arrayZ_, + length * item_size); } + + uint32_t hash () const { return as_bytes ().hash (); } + const Type * arrayZ () const { return arrayZ_; } Type * arrayZ () { return arrayZ_; } From 313b3057c335da6baa4cd447bac95812992413b9 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:46:35 -0700 Subject: [PATCH 24/25] [serializer] Implement dedup! --- src/hb-serialize.hh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index d8e1e2fb8..4de87d823 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -83,6 +83,12 @@ struct hb_serialize_context_t this->end = this->start + size; reset (); } + ~hb_serialize_context_t () + { + current.fini_deep (); + packed.fini_deep (); + packed_map.fini (); + } bool in_error () const { return !this->successful; } @@ -158,8 +164,15 @@ struct hb_serialize_context_t objidx_t pop_pack () { object_t obj = current.pop (); + obj.tail = head; + unsigned len = obj.tail - obj.head; - unsigned len = head - obj.head; + objidx_t objidx = packed_map.get (&obj); + if (objidx) + { + obj.fini (); + return objidx; + } tail -= len; memmove (tail, obj.head, len); @@ -177,7 +190,7 @@ struct hb_serialize_context_t if (unlikely (packed.in_error ())) return 0; - objidx_t objidx = packed.length - 1; + objidx = packed.length - 1; packed_map.set (key, objidx); @@ -305,7 +318,6 @@ struct hb_serialize_context_t private: /* Stack of currently under construction objects. */ - /* Note. We store the "end - tail" distance in the length member of these. */ hb_vector_t current; /* Stack of packed objects. Object 0 is always nil object. */ From d6005b49b32410543a8dfa93ce2a213223cf8f01 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 30 Mar 2019 19:49:56 -0700 Subject: [PATCH 25/25] [serialize] Start implementing linking --- src/hb-serialize.hh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/hb-serialize.hh b/src/hb-serialize.hh index 4de87d823..ab07080b8 100644 --- a/src/hb-serialize.hh +++ b/src/hb-serialize.hh @@ -143,9 +143,13 @@ struct hb_serialize_context_t assert (current.length == 1); /* Only "pack" if there exist other objects... Otherwise, don't bother. - * Saves a copy. */ - if (packed.length > 1) - pop_pack (); + * Saves a move. */ + if (packed.length == 1) + return; + + pop_pack (); + + link (); } template @@ -214,6 +218,11 @@ struct hb_serialize_context_t assert (packed.tail ().head == tail); } + void link () + { + // XXX + } + unsigned int length () const { return this->head - current.tail ().head; } void align (unsigned int alignment)