[subset-cff] Optimize op_str_t layout
diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh
index e90207a..4967629 100644
--- a/src/hb-cff-interp-common.hh
+++ b/src/hb-cff-interp-common.hh
@@ -480,7 +480,11 @@
 /* an operator prefixed by its operands in a byte string */
 struct op_str_t
 {
-  hb_ubytes_t str;
+  /* This used to be a hb_ubytes_t. Using a pointer and length
+   * saves 8 bytes in the struct. */
+  const unsigned char *ptr = nullptr;
+  unsigned length = 0;
+
   op_code_t  op;
 };
 
@@ -492,9 +496,9 @@
   {
     TRACE_SERIALIZE (this);
 
-    HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+    HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.length);
     if (unlikely (!d)) return_trace (false);
-    memcpy (d, &opstr.str[0], opstr.str.length);
+    memcpy (d, opstr.ptr, opstr.length);
     return_trace (true);
   }
 };
@@ -518,7 +522,9 @@
   {
     VAL *val = values.push ();
     val->op = op;
-    val->str = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
+    auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
+    val->ptr = arr.arrayZ;
+    val->length = arr.length;
     opStart = str_ref.get_offset ();
   }
 
@@ -526,7 +532,9 @@
   {
     VAL *val = values.push (v);
     val->op = op;
-    val->str = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
+    auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
+    val->ptr = arr.arrayZ;
+    val->length = arr.length;
     opStart = str_ref.get_offset ();
   }
 
diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh
index 1528985..69c9eb6 100644
--- a/src/hb-subset-cff-common.hh
+++ b/src/hb-subset-cff-common.hh
@@ -104,20 +104,20 @@
       encode_byte (op);
   }
 
-  void copy_str (const hb_ubytes_t &str)
+  void copy_str (const unsigned char *str, unsigned length)
   {
     unsigned int  offset = buff.length;
     /* Manually resize buffer since faster. */
-    if (likely ((signed) (buff.length + str.length) <= buff.allocated))
-      buff.length += str.length;
-    else if (unlikely (!buff.resize (offset + str.length)))
+    if (likely ((signed) (buff.length + length) <= buff.allocated))
+      buff.length += length;
+    else if (unlikely (!buff.resize (offset + length)))
       return;
 
     /* Since our strings are one or two bytes typically,
      * this is faster than memcpy. */
-    for (unsigned i = 0; i < str.length; i++)
-      buff.arrayZ[i + offset] = str.arrayZ[i];
-    // memcpy (buff.arrayZ + offset, &str[0], str.length);
+    for (unsigned i = 0; i < length; i++)
+      buff.arrayZ[i + offset] = str[i];
+    // memcpy (buff.arrayZ + offset, str, length);
   }
 
   bool is_error () const { return buff.in_error (); }
@@ -183,9 +183,9 @@
     }
     else
     {
-      HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
+      HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.length);
       if (unlikely (!d)) return_trace (false);
-      memcpy (d, &opstr.str[0], opstr.str.length);
+      memcpy (d, opstr.ptr, opstr.length);
     }
     return_trace (true);
   }
@@ -883,7 +883,7 @@
 	    break;
 
 	  default:
-	    encoder.copy_str (opstr.str);
+	    encoder.copy_str (opstr.ptr, opstr.length);
 	    break;
 	}
       }
diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc
index fbf1894..53b0ed2 100644
--- a/src/hb-subset-cff1.cc
+++ b/src/hb-subset-cff1.cc
@@ -167,9 +167,10 @@
 	   * for supplement, the original byte string is copied along with the op code */
 	  op_str_t supp_op;
 	  supp_op.op = op;
-	  if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
+	  if ( unlikely (!(opstr.length >= opstr.last_arg_offset + 3)))
 	    return_trace (false);
-	  supp_op.str = hb_ubytes_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+	  supp_op.ptr = opstr.ptr + opstr.last_arg_offset;
+	  supp_op.length = opstr.length - opstr.last_arg_offset;
 	  return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
 			UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
 			copy_opstr (c, supp_op));