[repacker] add 'virtual links' to the serializer.

These aren't associated with an offset field, but instead exist solely to add an ordering constraint to the object graph.
This commit is contained in:
Garret Rieger 2021-09-23 14:14:06 -07:00
parent 59d8f6c817
commit 7615b94ecf
2 changed files with 29 additions and 2 deletions

View File

@ -828,8 +828,9 @@ struct graph_t
if (visited[link.objidx]) continue;
const auto& child = vertices_[link.objidx].obj;
unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
int64_t child_weight = (child.tail - child.head) +
((int64_t) 1 << (link.width * 8)) * (vertices_[link.objidx].space + 1);
((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
int64_t child_distance = next_distance + child_weight;
if (child_distance < vertices_[link.objidx].distance)
@ -874,6 +875,10 @@ struct graph_t
bool is_valid_offset (int64_t offset,
const hb_serialize_context_t::object_t::link_t& link) const
{
if (unlikely (!link.width))
// Virtual links can't overflow.
return link.is_signed || offset >= 0;
if (link.is_signed)
{
if (link.width == 4)
@ -966,6 +971,9 @@ struct graph_t
{
switch (link.width)
{
case 0:
// Virtual links aren't serialized.
return;
case 4:
if (link.is_signed)
{

View File

@ -51,6 +51,12 @@ enum hb_serialize_error_t {
};
HB_MARK_AS_FLAG_T (hb_serialize_error_t);
// This is a 0 byte wide offset, used to add virtual links to the serializer object graph.
// It does not correspond to a real offset and exists soley to enforce an ordering constraint
// in the graph's packed order.
struct VirtualOffset {
};
struct hb_serialize_context_t
{
typedef unsigned objidx_t;
@ -376,11 +382,22 @@ struct hb_serialize_context_t
err (HB_SERIALIZE_ERROR_OTHER);
link.width = sizeof (T);
link.objidx = objidx;
if (unlikely (!sizeof (T)))
{
// This link is not associated with an actual offset and exists merely to enforce
// an ordering constraint.
link.is_signed = 0;
link.whence = 0;
link.position = 0;
link.bias = 0;
return;
}
link.is_signed = std::is_signed<hb_unwrap_type (T)>::value;
link.whence = (unsigned) whence;
link.position = (const char *) &ofs - current->head;
link.bias = bias;
link.objidx = objidx;
}
unsigned to_bias (const void *base) const
@ -402,6 +419,8 @@ struct hb_serialize_context_t
for (const object_t* parent : ++hb_iter (packed))
for (const object_t::link_t &link : parent->links)
{
if (unlikely (!link.width)) continue; // Don't need to resolve virtual offsets
const object_t* child = packed[link.objidx];
if (unlikely (!child)) { err (HB_SERIALIZE_ERROR_OTHER); return; }
unsigned offset = 0;