Reduce storage by sharing face amongst lazy_loaders

This commit is contained in:
Behdad Esfahbod 2018-08-02 01:27:40 -07:00
parent bdd3c11a19
commit ff7826e90b
4 changed files with 88 additions and 70 deletions

View File

@ -590,93 +590,106 @@ struct BEInt<Type, 4>
* Lazy struct and blob loaders. * Lazy struct and blob loaders.
*/ */
template <typename Subclass, template <unsigned int WheresFace,
typename Subclass,
typename Returned, typename Returned,
typename Stored = Returned> typename Stored = Returned>
struct hb_base_lazy_loader_t struct hb_base_lazy_loader_t
{ {
static_assert (WheresFace > 0, "");
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); } inline const Subclass* thiz (void) const { return static_cast<const Subclass *> (this); }
inline Subclass* thiz (void) { return static_cast<Subclass *> (this); }
inline void init (hb_face_t *face_) inline void init (void)
{ {
face = face_;
instance = nullptr; instance = nullptr;
} }
inline void fini (void)
{
if (instance)
thiz ()->destroy (instance);
}
inline const Returned * operator-> (void) const inline const Returned * operator-> (void) const
{ {
return thiz ()->get (); return thiz ()->get ();
} }
protected: inline Stored * get_stored (void) const
hb_face_t *face;
mutable Stored *instance;
};
template <typename T>
struct hb_lazy_loader_t : hb_base_lazy_loader_t<hb_lazy_loader_t<T>, T>
{
inline void fini (void)
{
if (this->instance && this->instance != &Null(T))
{
this->instance->fini();
free (this->instance);
}
}
inline const T* get (void) const
{ {
retry: retry:
T *p = (T *) hb_atomic_ptr_get (&this->instance); Stored *p = (Stored *) hb_atomic_ptr_get (&this->instance);
if (unlikely (!p)) if (unlikely (!p))
{ {
p = (T *) calloc (1, sizeof (T)); hb_face_t *face = *(((hb_face_t **) this) - WheresFace);
if (unlikely (!p)) p = thiz ()->create (face);
p = const_cast<T *> (&Null(T)); if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<Stored **>(&this->instance), nullptr, p)))
else
p->init (this->face);
if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<T **>(&this->instance), nullptr, p)))
{ {
if (p != &Null(T)) thiz ()->destroy (p);
p->fini ();
goto retry; goto retry;
} }
} }
return p; return p;
} }
inline const Returned * get (void) const
{
return thiz ()->convert (get_stored ());
}
static inline const Returned* convert (const Stored *p)
{
return p;
}
private:
/* Must only have one pointer. */
mutable Stored *instance;
}; };
template <typename T> template <unsigned int WheresFace, typename T>
struct hb_table_lazy_loader_t : hb_base_lazy_loader_t<hb_table_lazy_loader_t<T>, T, hb_blob_t> struct hb_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_lazy_loader_t<WheresFace, T>, T>
{ {
inline void fini (void) static inline T *create (hb_face_t *face)
{ {
hb_blob_destroy (this->instance); T *p = (T *) calloc (1, sizeof (T));
if (unlikely (!p))
p = const_cast<T *> (&Null(T));
else
p->init (face);
return p;
}
static inline void destroy (T *p)
{
if (p != &Null(T))
{
p->fini();
free (p);
}
}
};
template <unsigned int WheresFace, typename T>
struct hb_table_lazy_loader_t : hb_base_lazy_loader_t<WheresFace, hb_table_lazy_loader_t<WheresFace, T>, T, hb_blob_t>
{
static inline hb_blob_t *create (hb_face_t *face)
{
return hb_sanitize_context_t ().reference_table<T> (face);
}
static inline void destroy (hb_blob_t *p)
{
hb_blob_destroy (p);
}
static inline const T* convert (const hb_blob_t *blob)
{
return blob->as<T> ();
} }
inline hb_blob_t* get_blob (void) const inline hb_blob_t* get_blob (void) const
{ {
retry: return this->get_stored ();
hb_blob_t *b = (hb_blob_t *) hb_atomic_ptr_get (&this->instance);
if (unlikely (!b))
{
b = hb_sanitize_context_t ().reference_table<T> (this->face);
if (!hb_atomic_ptr_cmpexch (&this->instance, nullptr, b))
{
hb_blob_destroy (b);
goto retry;
}
this->instance = b;
}
return b;
}
inline const T* get (void) const
{
hb_blob_t *b = get_blob ();
return b->as<T> ();
} }
}; };

View File

@ -44,10 +44,12 @@ struct hb_ot_font_t
OT::cmap::accelerator_t cmap; OT::cmap::accelerator_t cmap;
OT::hmtx::accelerator_t h_metrics; OT::hmtx::accelerator_t h_metrics;
OT::vmtx::accelerator_t v_metrics; OT::vmtx::accelerator_t v_metrics;
hb_lazy_loader_t<OT::glyf::accelerator_t> glyf;
hb_lazy_loader_t<OT::CBDT::accelerator_t> cbdt; hb_face_t *face; /* MUST be before the lazy loaders. */
hb_lazy_loader_t<OT::post::accelerator_t> post; hb_lazy_loader_t<1, OT::glyf::accelerator_t> glyf;
hb_lazy_loader_t<OT::kern::accelerator_t> kern; hb_lazy_loader_t<2, OT::CBDT::accelerator_t> cbdt;
hb_lazy_loader_t<3, OT::post::accelerator_t> post;
hb_lazy_loader_t<4, OT::kern::accelerator_t> kern;
}; };
@ -62,10 +64,11 @@ _hb_ot_font_create (hb_face_t *face)
ot_font->cmap.init (face); ot_font->cmap.init (face);
ot_font->h_metrics.init (face); ot_font->h_metrics.init (face);
ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */ ot_font->v_metrics.init (face, ot_font->h_metrics.ascender - ot_font->h_metrics.descender); /* TODO Can we do this lazily? */
ot_font->glyf.init (face); ot_font->face = face;
ot_font->cbdt.init (face); ot_font->glyf.init ();
ot_font->post.init (face); ot_font->cbdt.init ();
ot_font->kern.init (face); ot_font->post.init ();
ot_font->kern.init ();
return ot_font; return ot_font;
} }

View File

@ -172,11 +172,12 @@ struct hb_ot_layout_t
const struct OT::GPOS *gpos; const struct OT::GPOS *gpos;
/* TODO Move the following out of this struct. */ /* TODO Move the following out of this struct. */
hb_table_lazy_loader_t<struct OT::BASE> base; hb_face_t *face; /* MUST be before the lazy loaders. */
hb_table_lazy_loader_t<struct OT::MATH> math; hb_table_lazy_loader_t<1, struct OT::BASE> base;
hb_table_lazy_loader_t<struct OT::fvar> fvar; hb_table_lazy_loader_t<2, struct OT::MATH> math;
hb_table_lazy_loader_t<struct OT::avar> avar; hb_table_lazy_loader_t<3, struct OT::fvar> fvar;
hb_table_lazy_loader_t<struct AAT::morx> morx; hb_table_lazy_loader_t<4, struct OT::avar> avar;
hb_table_lazy_loader_t<5, struct AAT::morx> morx;
unsigned int gsub_lookup_count; unsigned int gsub_lookup_count;
unsigned int gpos_lookup_count; unsigned int gpos_lookup_count;

View File

@ -63,10 +63,11 @@ _hb_ot_layout_create (hb_face_t *face)
layout->gpos_blob = hb_sanitize_context_t ().reference_table<OT::GPOS> (face); layout->gpos_blob = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
layout->gpos = layout->gpos_blob->as<OT::GPOS> (); layout->gpos = layout->gpos_blob->as<OT::GPOS> ();
layout->math.init (face); layout->face = face;
layout->fvar.init (face); layout->math.init ();
layout->avar.init (face); layout->fvar.init ();
layout->morx.init (face); layout->avar.init ();
layout->morx.init ();
{ {
/* /*