You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2013/07/17 16:12:30 UTC

[lucy-commits] [10/34] Migrate Lucy's index classes to IVARS.

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/Snapshot.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/Snapshot.c b/core/Lucy/Index/Snapshot.c
index beca285..4bae50f 100644
--- a/core/Lucy/Index/Snapshot.c
+++ b/core/Lucy/Index/Snapshot.c
@@ -38,10 +38,11 @@ Snapshot_new() {
 
 static void
 S_zero_out(Snapshot *self) {
-    DECREF(self->entries);
-    DECREF(self->path);
-    self->entries  = Hash_new(0);
-    self->path = NULL;
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
+    DECREF(ivars->entries);
+    DECREF(ivars->path);
+    ivars->entries  = Hash_new(0);
+    ivars->path = NULL;
 }
 
 Snapshot*
@@ -52,19 +53,22 @@ Snapshot_init(Snapshot *self) {
 
 void
 Snapshot_destroy(Snapshot *self) {
-    DECREF(self->entries);
-    DECREF(self->path);
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
+    DECREF(ivars->entries);
+    DECREF(ivars->path);
     SUPER_DESTROY(self, SNAPSHOT);
 }
 
 void
 Snapshot_add_entry(Snapshot *self, const CharBuf *entry) {
-    Hash_Store(self->entries, (Obj*)entry, (Obj*)CFISH_TRUE);
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
+    Hash_Store(ivars->entries, (Obj*)entry, (Obj*)CFISH_TRUE);
 }
 
 bool
 Snapshot_delete_entry(Snapshot *self, const CharBuf *entry) {
-    Obj *val = Hash_Delete(self->entries, (Obj*)entry);
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
+    Obj *val = Hash_Delete(ivars->entries, (Obj*)entry);
     if (val) {
         Obj_Dec_RefCount(val);
         return true;
@@ -76,34 +80,39 @@ Snapshot_delete_entry(Snapshot *self, const CharBuf *entry) {
 
 VArray*
 Snapshot_list(Snapshot *self) {
-    return Hash_Keys(self->entries);
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
+    return Hash_Keys(ivars->entries);
 }
 
 uint32_t
 Snapshot_num_entries(Snapshot *self) {
-    return Hash_Get_Size(self->entries);
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
+    return Hash_Get_Size(ivars->entries);
 }
 
 void
 Snapshot_set_path(Snapshot *self, const CharBuf *path) {
-    DECREF(self->path);
-    self->path = path ? CB_Clone(path) : NULL;
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
+    DECREF(ivars->path);
+    ivars->path = path ? CB_Clone(path) : NULL;
 }
 
 CharBuf*
 Snapshot_get_path(Snapshot *self) {
-    return self->path;
+    return Snapshot_IVARS(self)->path;
 }
 
 Snapshot*
 Snapshot_read_file(Snapshot *self, Folder *folder, const CharBuf *path) {
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
+
     // Eliminate all prior data. Pick a snapshot file.
     S_zero_out(self);
-    self->path = path ? CB_Clone(path) : IxFileNames_latest_snapshot(folder);
+    ivars->path = path ? CB_Clone(path) : IxFileNames_latest_snapshot(folder);
 
-    if (self->path) {
+    if (ivars->path) {
         Hash *snap_data
-            = (Hash*)CERTIFY(Json_slurp_json(folder, self->path), HASH);
+            = (Hash*)CERTIFY(Json_slurp_json(folder, ivars->path), HASH);
         Obj *format_obj
             = CERTIFY(Hash_Fetch_Str(snap_data, "format", 6), OBJ);
         int32_t format = (int32_t)Obj_To_I64(format_obj);
@@ -128,11 +137,11 @@ Snapshot_read_file(Snapshot *self, Folder *folder, const CharBuf *path) {
             DECREF(list);
             list = cleaned;
         }
-        Hash_Clear(self->entries);
+        Hash_Clear(ivars->entries);
         for (uint32_t i = 0, max = VA_Get_Size(list); i < max; i++) {
             CharBuf *entry
                 = (CharBuf*)CERTIFY(VA_Fetch(list, i), CHARBUF);
-            Hash_Store(self->entries, (Obj*)entry, (Obj*)CFISH_TRUE);
+            Hash_Store(ivars->entries, (Obj*)entry, (Obj*)CFISH_TRUE);
         }
 
         DECREF(list);
@@ -163,26 +172,27 @@ S_clean_segment_contents(VArray *orig) {
 
 void
 Snapshot_write_file(Snapshot *self, Folder *folder, const CharBuf *path) {
+    SnapshotIVARS *const ivars = Snapshot_IVARS(self);
     Hash   *all_data = Hash_new(0);
     VArray *list     = Snapshot_List(self);
 
     // Update path.
-    DECREF(self->path);
+    DECREF(ivars->path);
     if (path) {
-        self->path = CB_Clone(path);
+        ivars->path = CB_Clone(path);
     }
     else {
         CharBuf *latest = IxFileNames_latest_snapshot(folder);
         uint64_t gen = latest ? IxFileNames_extract_gen(latest) + 1 : 1;
         char base36[StrHelp_MAX_BASE36_BYTES];
         StrHelp_to_base36(gen, &base36);
-        self->path = CB_newf("snapshot_%s.json", &base36);
+        ivars->path = CB_newf("snapshot_%s.json", &base36);
         DECREF(latest);
     }
 
     // Don't overwrite.
-    if (Folder_Exists(folder, self->path)) {
-        THROW(ERR, "Snapshot file '%o' already exists", self->path);
+    if (Folder_Exists(folder, ivars->path)) {
+        THROW(ERR, "Snapshot file '%o' already exists", ivars->path);
     }
 
     // Sort, then store file names.
@@ -196,7 +206,7 @@ Snapshot_write_file(Snapshot *self, Folder *folder, const CharBuf *path) {
                    (Obj*)CB_newf("%i32", (int32_t)Snapshot_current_file_subformat));
 
     // Write out JSON-ized data to the new file.
-    Json_spew_json((Obj*)all_data, folder, self->path);
+    Json_spew_json((Obj*)all_data, folder, ivars->path);
 
     DECREF(all_data);
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/SortCache.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/SortCache.c b/core/Lucy/Index/SortCache.c
index 00d41b2..31975ad 100644
--- a/core/Lucy/Index/SortCache.c
+++ b/core/Lucy/Index/SortCache.c
@@ -24,20 +24,22 @@ SortCache*
 SortCache_init(SortCache *self, const CharBuf *field, FieldType *type,
                void *ords, int32_t cardinality, int32_t doc_max, int32_t null_ord,
                int32_t ord_width) {
+    SortCacheIVARS *const ivars = SortCache_IVARS(self);
+
     // Init.
-    self->native_ords = false;
+    ivars->native_ords = false;
 
     // Assign.
     if (!FType_Sortable(type)) {
         THROW(ERR, "Non-sortable FieldType for %o", field);
     }
-    self->field       = CB_Clone(field);
-    self->type        = (FieldType*)INCREF(type);
-    self->ords        = ords;
-    self->cardinality = cardinality;
-    self->doc_max     = doc_max;
-    self->null_ord    = null_ord;
-    self->ord_width   = ord_width;
+    ivars->field       = CB_Clone(field);
+    ivars->type        = (FieldType*)INCREF(type);
+    ivars->ords        = ords;
+    ivars->cardinality = cardinality;
+    ivars->doc_max     = doc_max;
+    ivars->null_ord    = null_ord;
+    ivars->ord_width   = ord_width;
 
     ABSTRACT_CLASS_CHECK(self, SORTCACHE);
     return self;
@@ -45,56 +47,58 @@ SortCache_init(SortCache *self, const CharBuf *field, FieldType *type,
 
 void
 SortCache_destroy(SortCache *self) {
-    DECREF(self->field);
-    DECREF(self->type);
+    SortCacheIVARS *const ivars = SortCache_IVARS(self);
+    DECREF(ivars->field);
+    DECREF(ivars->type);
     SUPER_DESTROY(self, SORTCACHE);
 }
 
 bool
 SortCache_get_native_ords(SortCache *self) {
-    return self->native_ords;
+    return SortCache_IVARS(self)->native_ords;
 }
 
 void
 SortCache_set_native_ords(SortCache *self, bool native_ords) {
-    self->native_ords = native_ords;
+    SortCache_IVARS(self)->native_ords = native_ords;
 }
 
 int32_t
 SortCache_ordinal(SortCache *self, int32_t doc_id) {
-    if ((uint32_t)doc_id > (uint32_t)self->doc_max) {
-        THROW(ERR, "Out of range: %i32 > %i32", doc_id, self->doc_max);
+    SortCacheIVARS *const ivars = SortCache_IVARS(self);
+    if ((uint32_t)doc_id > (uint32_t)ivars->doc_max) {
+        THROW(ERR, "Out of range: %i32 > %i32", doc_id, ivars->doc_max);
     }
-    switch (self->ord_width) {
-        case 1: return NumUtil_u1get(self->ords, doc_id);
-        case 2: return NumUtil_u2get(self->ords, doc_id);
-        case 4: return NumUtil_u4get(self->ords, doc_id);
+    switch (ivars->ord_width) {
+        case 1: return NumUtil_u1get(ivars->ords, doc_id);
+        case 2: return NumUtil_u2get(ivars->ords, doc_id);
+        case 4: return NumUtil_u4get(ivars->ords, doc_id);
         case 8: {
-                uint8_t *ints = (uint8_t*)self->ords;
+                uint8_t *ints = (uint8_t*)ivars->ords;
                 return ints[doc_id];
             }
         case 16:
-            if (self->native_ords) {
-                uint16_t *ints = (uint16_t*)self->ords;
+            if (ivars->native_ords) {
+                uint16_t *ints = (uint16_t*)ivars->ords;
                 return ints[doc_id];
             }
             else {
-                uint8_t *bytes = (uint8_t*)self->ords;
+                uint8_t *bytes = (uint8_t*)ivars->ords;
                 bytes += doc_id * sizeof(uint16_t);
                 return NumUtil_decode_bigend_u16(bytes);
             }
         case 32:
-            if (self->native_ords) {
-                uint32_t *ints = (uint32_t*)self->ords;
+            if (ivars->native_ords) {
+                uint32_t *ints = (uint32_t*)ivars->ords;
                 return ints[doc_id];
             }
             else {
-                uint8_t *bytes = (uint8_t*)self->ords;
+                uint8_t *bytes = (uint8_t*)ivars->ords;
                 bytes += doc_id * sizeof(uint32_t);
                 return NumUtil_decode_bigend_u32(bytes);
             }
         default: {
-                THROW(ERR, "Invalid ord width: %i32", self->ord_width);
+                THROW(ERR, "Invalid ord width: %i32", ivars->ord_width);
                 UNREACHABLE_RETURN(int32_t);
             }
     }
@@ -102,9 +106,10 @@ SortCache_ordinal(SortCache *self, int32_t doc_id) {
 
 int32_t
 SortCache_find(SortCache *self, Obj *term) {
-    FieldType *const type   = self->type;
+    SortCacheIVARS *const ivars = SortCache_IVARS(self);
+    FieldType *const type   = ivars->type;
     int32_t          lo     = 0;
-    int32_t          hi     = self->cardinality - 1;
+    int32_t          hi     = ivars->cardinality - 1;
     int32_t          result = -100;
     Obj             *blank  = SortCache_Make_Blank(self);
 
@@ -113,7 +118,7 @@ SortCache_find(SortCache *self, Obj *term) {
         && !Obj_Is_A(blank, Obj_Get_VTable(term))
        ) {
         THROW(ERR, "SortCache error for field %o: term is a %o, and not "
-              "comparable to a %o", self->field, Obj_Get_Class_Name(term),
+              "comparable to a %o", ivars->field, Obj_Get_Class_Name(term),
               Obj_Get_Class_Name(blank));
     }
 
@@ -151,22 +156,22 @@ SortCache_find(SortCache *self, Obj *term) {
 
 void*
 SortCache_get_ords(SortCache *self) {
-    return self->ords;
+    return SortCache_IVARS(self)->ords;
 }
 
 int32_t
 SortCache_get_cardinality(SortCache *self) {
-    return self->cardinality;
+    return SortCache_IVARS(self)->cardinality;
 }
 
 int32_t
 SortCache_get_null_ord(SortCache *self) {
-    return self->null_ord;
+    return SortCache_IVARS(self)->null_ord;
 }
 
 int32_t
 SortCache_get_ord_width(SortCache *self) {
-    return self->ord_width;
+    return SortCache_IVARS(self)->ord_width;
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/SortCache/NumericSortCache.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/SortCache/NumericSortCache.c b/core/Lucy/Index/SortCache/NumericSortCache.c
index 0898062..d4af636 100644
--- a/core/Lucy/Index/SortCache/NumericSortCache.c
+++ b/core/Lucy/Index/SortCache/NumericSortCache.c
@@ -45,19 +45,20 @@ NumSortCache_init(NumericSortCache *self, const CharBuf *field,
     void    *ords    = InStream_Buf(ord_in, (size_t)ord_len);
     SortCache_init((SortCache*)self, field, type, ords, cardinality, doc_max,
                    null_ord, ord_width);
+    NumericSortCacheIVARS *const ivars = NumSortCache_IVARS(self);
 
     // Assign.
-    self->ord_in = (InStream*)INCREF(ord_in);
-    self->dat_in = (InStream*)INCREF(dat_in);
+    ivars->ord_in = (InStream*)INCREF(ord_in);
+    ivars->dat_in = (InStream*)INCREF(dat_in);
 
     // Validate ord file length.
     double BITS_PER_BYTE = 8.0;
-    double docs_per_byte = BITS_PER_BYTE / self->ord_width;
+    double docs_per_byte = BITS_PER_BYTE / ivars->ord_width;
     double max_ords      = ord_len * docs_per_byte;
-    if (max_ords < self->doc_max + 1) {
+    if (max_ords < ivars->doc_max + 1) {
         DECREF(self);
         THROW(ERR, "Conflict between ord count max %f64 and doc_max %i32 for "
-              "field %o", max_ords, self->doc_max, field);
+              "field %o", max_ords, ivars->doc_max, field);
     }
 
     ABSTRACT_CLASS_CHECK(self, NUMERICSORTCACHE);
@@ -66,13 +67,14 @@ NumSortCache_init(NumericSortCache *self, const CharBuf *field,
 
 void
 NumSortCache_destroy(NumericSortCache *self) {
-    if (self->ord_in) {
-        InStream_Close(self->ord_in);
-        InStream_Dec_RefCount(self->ord_in);
+    NumericSortCacheIVARS *const ivars = NumSortCache_IVARS(self);
+    if (ivars->ord_in) {
+        InStream_Close(ivars->ord_in);
+        InStream_Dec_RefCount(ivars->ord_in);
     }
-    if (self->dat_in) {
-        InStream_Close(self->dat_in);
-        InStream_Dec_RefCount(self->dat_in);
+    if (ivars->dat_in) {
+        InStream_Close(ivars->dat_in);
+        InStream_Dec_RefCount(ivars->dat_in);
     }
     SUPER_DESTROY(self, NUMERICSORTCACHE);
 }
@@ -101,16 +103,17 @@ F64SortCache_init(Float64SortCache *self, const CharBuf *field,
 
 Obj*
 F64SortCache_value(Float64SortCache *self, int32_t ord, Obj *blank) {
-    if (ord == self->null_ord) {
+    Float64SortCacheIVARS *const ivars = F64SortCache_IVARS(self);
+    if (ord == ivars->null_ord) {
         return NULL;
     }
     else if (ord < 0) {
-        THROW(ERR, "Ordinal less than 0 for %o: %i32", self->field, ord);
+        THROW(ERR, "Ordinal less than 0 for %o: %i32", ivars->field, ord);
     }
     else {
         Float64 *num_blank = (Float64*)CERTIFY(blank, FLOAT64);
-        InStream_Seek(self->dat_in, ord * sizeof(double));
-        Float64_Set_Value(num_blank, InStream_Read_F64(self->dat_in));
+        InStream_Seek(ivars->dat_in, ord * sizeof(double));
+        Float64_Set_Value(num_blank, InStream_Read_F64(ivars->dat_in));
     }
     return blank;
 }
@@ -145,16 +148,17 @@ F32SortCache_init(Float32SortCache *self, const CharBuf *field,
 
 Obj*
 F32SortCache_value(Float32SortCache *self, int32_t ord, Obj *blank) {
-    if (ord == self->null_ord) {
+    Float32SortCacheIVARS *const ivars = F32SortCache_IVARS(self);
+    if (ord == ivars->null_ord) {
         return NULL;
     }
     else if (ord < 0) {
-        THROW(ERR, "Ordinal less than 0 for %o: %i32", self->field, ord);
+        THROW(ERR, "Ordinal less than 0 for %o: %i32", ivars->field, ord);
     }
     else {
         Float32 *num_blank = (Float32*)CERTIFY(blank, FLOAT32);
-        InStream_Seek(self->dat_in, ord * sizeof(float));
-        Float32_Set_Value(num_blank, InStream_Read_F32(self->dat_in));
+        InStream_Seek(ivars->dat_in, ord * sizeof(float));
+        Float32_Set_Value(num_blank, InStream_Read_F32(ivars->dat_in));
     }
     return blank;
 }
@@ -189,16 +193,17 @@ I32SortCache_init(Int32SortCache *self, const CharBuf *field,
 
 Obj*
 I32SortCache_value(Int32SortCache *self, int32_t ord, Obj *blank) {
-    if (ord == self->null_ord) {
+    Int32SortCacheIVARS *const ivars = I32SortCache_IVARS(self);
+    if (ord == ivars->null_ord) {
         return NULL;
     }
     else if (ord < 0) {
-        THROW(ERR, "Ordinal less than 0 for %o: %i32", self->field, ord);
+        THROW(ERR, "Ordinal less than 0 for %o: %i32", ivars->field, ord);
     }
     else {
         Integer32 *int_blank = (Integer32*)CERTIFY(blank, INTEGER32);
-        InStream_Seek(self->dat_in, ord * sizeof(int32_t));
-        Int32_Set_Value(int_blank, InStream_Read_I32(self->dat_in));
+        InStream_Seek(ivars->dat_in, ord * sizeof(int32_t));
+        Int32_Set_Value(int_blank, InStream_Read_I32(ivars->dat_in));
     }
     return blank;
 }
@@ -233,16 +238,17 @@ I64SortCache_init(Int64SortCache *self, const CharBuf *field,
 
 Obj*
 I64SortCache_value(Int64SortCache *self, int32_t ord, Obj *blank) {
-    if (ord == self->null_ord) {
+    Int64SortCacheIVARS *const ivars = I64SortCache_IVARS(self);
+    if (ord == ivars->null_ord) {
         return NULL;
     }
     else if (ord < 0) {
-        THROW(ERR, "Ordinal less than 0 for %o: %i32", self->field, ord);
+        THROW(ERR, "Ordinal less than 0 for %o: %i32", ivars->field, ord);
     }
     else {
         Integer64 *int_blank = (Integer64*)CERTIFY(blank, INTEGER64);
-        InStream_Seek(self->dat_in, ord * sizeof(int64_t));
-        Int64_Set_Value(int_blank, InStream_Read_I64(self->dat_in));
+        InStream_Seek(ivars->dat_in, ord * sizeof(int64_t));
+        Int64_Set_Value(int_blank, InStream_Read_I64(ivars->dat_in));
     }
     return blank;
 }

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/SortCache/TextSortCache.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/SortCache/TextSortCache.c b/core/Lucy/Index/SortCache/TextSortCache.c
index 1905215..9c05c63 100644
--- a/core/Lucy/Index/SortCache/TextSortCache.c
+++ b/core/Lucy/Index/SortCache/TextSortCache.c
@@ -49,37 +49,39 @@ TextSortCache_init(TextSortCache *self, const CharBuf *field,
     void *ords = InStream_Buf(ord_in, (size_t)ord_len);
     SortCache_init((SortCache*)self, field, type, ords, cardinality, doc_max,
                    null_ord, ord_width);
+    TextSortCacheIVARS *const ivars = TextSortCache_IVARS(self);
 
     // Validate ords file length.
-    double  bytes_per_doc = self->ord_width / 8.0;
+    double  bytes_per_doc = ivars->ord_width / 8.0;
     double  max_ords      = ord_len / bytes_per_doc;
-    if (max_ords < self->doc_max + 1) {
-        WARN("ORD WIDTH: %i32 %i32", ord_width, self->ord_width);
+    if (max_ords < ivars->doc_max + 1) {
+        WARN("ORD WIDTH: %i32 %i32", ord_width, ivars->ord_width);
         THROW(ERR, "Conflict between ord count max %f64 and doc_max %i32 for "
               "field %o", max_ords, doc_max, field);
     }
 
     // Assign.
-    self->ord_in = (InStream*)INCREF(ord_in);
-    self->ix_in  = (InStream*)INCREF(ix_in);
-    self->dat_in = (InStream*)INCREF(dat_in);
+    ivars->ord_in = (InStream*)INCREF(ord_in);
+    ivars->ix_in  = (InStream*)INCREF(ix_in);
+    ivars->dat_in = (InStream*)INCREF(dat_in);
 
     return self;
 }
 
 void
 TextSortCache_destroy(TextSortCache *self) {
-    if (self->ord_in) {
-        InStream_Close(self->ord_in);
-        InStream_Dec_RefCount(self->ord_in);
+    TextSortCacheIVARS *const ivars = TextSortCache_IVARS(self);
+    if (ivars->ord_in) {
+        InStream_Close(ivars->ord_in);
+        InStream_Dec_RefCount(ivars->ord_in);
     }
-    if (self->ix_in) {
-        InStream_Close(self->ix_in);
-        InStream_Dec_RefCount(self->ix_in);
+    if (ivars->ix_in) {
+        InStream_Close(ivars->ix_in);
+        InStream_Dec_RefCount(ivars->ix_in);
     }
-    if (self->dat_in) {
-        InStream_Close(self->dat_in);
-        InStream_Dec_RefCount(self->dat_in);
+    if (ivars->dat_in) {
+        InStream_Close(ivars->dat_in);
+        InStream_Dec_RefCount(ivars->dat_in);
     }
     SUPER_DESTROY(self, TEXTSORTCACHE);
 }
@@ -88,11 +90,12 @@ TextSortCache_destroy(TextSortCache *self) {
 
 Obj*
 TextSortCache_value(TextSortCache *self, int32_t ord, Obj *blank) {
-    if (ord == self->null_ord) {
+    TextSortCacheIVARS *const ivars = TextSortCache_IVARS(self);
+    if (ord == ivars->null_ord) {
         return NULL;
     }
-    InStream_Seek(self->ix_in, ord * sizeof(int64_t));
-    int64_t offset = InStream_Read_I64(self->ix_in);
+    InStream_Seek(ivars->ix_in, ord * sizeof(int64_t));
+    int64_t offset = InStream_Read_I64(ivars->ix_in);
     if (offset == NULL_SENTINEL) {
         return NULL;
     }
@@ -100,8 +103,8 @@ TextSortCache_value(TextSortCache *self, int32_t ord, Obj *blank) {
         uint32_t next_ord = ord + 1;
         int64_t next_offset;
         while (1) {
-            InStream_Seek(self->ix_in, next_ord * sizeof(int64_t));
-            next_offset = InStream_Read_I64(self->ix_in);
+            InStream_Seek(ivars->ix_in, next_ord * sizeof(int64_t));
+            next_offset = InStream_Read_I64(ivars->ix_in);
             if (next_offset != NULL_SENTINEL) { break; }
             next_ord++;
         }
@@ -110,13 +113,13 @@ TextSortCache_value(TextSortCache *self, int32_t ord, Obj *blank) {
         CERTIFY(blank, CHARBUF);
         int64_t len = next_offset - offset;
         char *ptr = CB_Grow((CharBuf*)blank, (size_t)len);
-        InStream_Seek(self->dat_in, offset);
-        InStream_Read_Bytes(self->dat_in, ptr, (size_t)len);
+        InStream_Seek(ivars->dat_in, offset);
+        InStream_Read_Bytes(ivars->dat_in, ptr, (size_t)len);
         ptr[len] = '\0';
         if (!StrHelp_utf8_valid(ptr, (size_t)len)) {
             CB_Set_Size((CharBuf*)blank, 0);
             THROW(ERR, "Invalid UTF-8 at %i64 in %o", offset,
-                  InStream_Get_Filename(self->dat_in));
+                  InStream_Get_Filename(ivars->dat_in));
         }
         CB_Set_Size((CharBuf*)blank, (size_t)len);
     }

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/SortFieldWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/SortFieldWriter.c b/core/Lucy/Index/SortFieldWriter.c
index 6d3bc16..59a90ec 100644
--- a/core/Lucy/Index/SortFieldWriter.c
+++ b/core/Lucy/Index/SortFieldWriter.c
@@ -77,56 +77,58 @@ SortFieldWriter_init(SortFieldWriter *self, Schema *schema,
                      OutStream *temp_dat_out) {
     // Init.
     SortEx_init((SortExternal*)self, sizeof(SFWriterElem));
-    self->null_ord        = -1;
-    self->count           = 0;
-    self->ord_start       = 0;
-    self->ord_end         = 0;
-    self->ix_start        = 0;
-    self->ix_end          = 0;
-    self->dat_start       = 0;
-    self->dat_end         = 0;
-    self->run_cardinality = -1;
-    self->run_max         = -1;
-    self->sort_cache      = NULL;
-    self->doc_map         = NULL;
-    self->sorted_ids      = NULL;
-    self->run_ord         = 0;
-    self->run_tick        = 0;
-    self->ord_width       = 0;
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+    ivars->null_ord        = -1;
+    ivars->count           = 0;
+    ivars->ord_start       = 0;
+    ivars->ord_end         = 0;
+    ivars->ix_start        = 0;
+    ivars->ix_end          = 0;
+    ivars->dat_start       = 0;
+    ivars->dat_end         = 0;
+    ivars->run_cardinality = -1;
+    ivars->run_max         = -1;
+    ivars->sort_cache      = NULL;
+    ivars->doc_map         = NULL;
+    ivars->sorted_ids      = NULL;
+    ivars->run_ord         = 0;
+    ivars->run_tick        = 0;
+    ivars->ord_width       = 0;
 
     // Assign.
-    self->field        = CB_Clone(field);
-    self->schema       = (Schema*)INCREF(schema);
-    self->snapshot     = (Snapshot*)INCREF(snapshot);
-    self->segment      = (Segment*)INCREF(segment);
-    self->polyreader   = (PolyReader*)INCREF(polyreader);
-    self->mem_pool     = (MemoryPool*)INCREF(memory_pool);
-    self->temp_ord_out = (OutStream*)INCREF(temp_ord_out);
-    self->temp_ix_out  = (OutStream*)INCREF(temp_ix_out);
-    self->temp_dat_out = (OutStream*)INCREF(temp_dat_out);
-    self->mem_thresh   = mem_thresh;
+    ivars->field        = CB_Clone(field);
+    ivars->schema       = (Schema*)INCREF(schema);
+    ivars->snapshot     = (Snapshot*)INCREF(snapshot);
+    ivars->segment      = (Segment*)INCREF(segment);
+    ivars->polyreader   = (PolyReader*)INCREF(polyreader);
+    ivars->mem_pool     = (MemoryPool*)INCREF(memory_pool);
+    ivars->temp_ord_out = (OutStream*)INCREF(temp_ord_out);
+    ivars->temp_ix_out  = (OutStream*)INCREF(temp_ix_out);
+    ivars->temp_dat_out = (OutStream*)INCREF(temp_dat_out);
+    ivars->mem_thresh   = mem_thresh;
 
     // Derive.
-    self->field_num = Seg_Field_Num(segment, field);
+    ivars->field_num = Seg_Field_Num(segment, field);
     FieldType *type = (FieldType*)CERTIFY(
-                          Schema_Fetch_Type(self->schema, field), FIELDTYPE);
-    self->type    = (FieldType*)INCREF(type);
-    self->prim_id = FType_Primitive_ID(type);
-    if (self->prim_id == FType_TEXT || self->prim_id == FType_BLOB) {
-        self->var_width = true;
+                          Schema_Fetch_Type(ivars->schema, field), FIELDTYPE);
+    ivars->type    = (FieldType*)INCREF(type);
+    ivars->prim_id = FType_Primitive_ID(type);
+    if (ivars->prim_id == FType_TEXT || ivars->prim_id == FType_BLOB) {
+        ivars->var_width = true;
     }
     else {
-        self->var_width = false;
+        ivars->var_width = false;
     }
-    self->uniq_vals = (Hash*)ZKHash_new(memory_pool, self->prim_id);
+    ivars->uniq_vals = (Hash*)ZKHash_new(memory_pool, ivars->prim_id);
 
     return self;
 }
 
 void
 SortFieldWriter_clear_cache(SortFieldWriter *self) {
-    if (self->uniq_vals) {
-        Hash_Clear(self->uniq_vals);
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+    if (ivars->uniq_vals) {
+        Hash_Clear(ivars->uniq_vals);
     }
     SortFieldWriter_Clear_Cache_t super_clear_cache
         = SUPER_METHOD_PTR(SORTFIELDWRITER, Lucy_SortFieldWriter_Clear_Cache);
@@ -135,35 +137,36 @@ SortFieldWriter_clear_cache(SortFieldWriter *self) {
 
 void
 SortFieldWriter_destroy(SortFieldWriter *self) {
-    DECREF(self->uniq_vals);
-    self->uniq_vals = NULL;
-    DECREF(self->field);
-    DECREF(self->schema);
-    DECREF(self->snapshot);
-    DECREF(self->segment);
-    DECREF(self->polyreader);
-    DECREF(self->type);
-    DECREF(self->mem_pool);
-    DECREF(self->temp_ord_out);
-    DECREF(self->temp_ix_out);
-    DECREF(self->temp_dat_out);
-    DECREF(self->ord_in);
-    DECREF(self->ix_in);
-    DECREF(self->dat_in);
-    DECREF(self->sort_cache);
-    DECREF(self->doc_map);
-    FREEMEM(self->sorted_ids);
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+    DECREF(ivars->uniq_vals);
+    ivars->uniq_vals = NULL;
+    DECREF(ivars->field);
+    DECREF(ivars->schema);
+    DECREF(ivars->snapshot);
+    DECREF(ivars->segment);
+    DECREF(ivars->polyreader);
+    DECREF(ivars->type);
+    DECREF(ivars->mem_pool);
+    DECREF(ivars->temp_ord_out);
+    DECREF(ivars->temp_ix_out);
+    DECREF(ivars->temp_dat_out);
+    DECREF(ivars->ord_in);
+    DECREF(ivars->ix_in);
+    DECREF(ivars->dat_in);
+    DECREF(ivars->sort_cache);
+    DECREF(ivars->doc_map);
+    FREEMEM(ivars->sorted_ids);
     SUPER_DESTROY(self, SORTFIELDWRITER);
 }
 
 int32_t
 SortFieldWriter_get_null_ord(SortFieldWriter *self) {
-    return self->null_ord;
+    return SortFieldWriter_IVARS(self)->null_ord;
 }
 
 int32_t
 SortFieldWriter_get_ord_width(SortFieldWriter *self) {
-    return self->ord_width;
+    return SortFieldWriter_IVARS(self)->ord_width;
 }
 
 static Obj*
@@ -179,28 +182,32 @@ S_find_unique_value(Hash *uniq_vals, Obj *val) {
 
 void
 SortFieldWriter_add(SortFieldWriter *self, int32_t doc_id, Obj *value) {
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+
     // Uniq-ify the value, and record it for this document.
     SFWriterElem elem;
-    elem.value = S_find_unique_value(self->uniq_vals, value);
+    elem.value = S_find_unique_value(ivars->uniq_vals, value);
     elem.doc_id = doc_id;
     SortFieldWriter_Feed(self, &elem);
-    self->count++;
+    ivars->count++;
 }
 
 void
 SortFieldWriter_add_segment(SortFieldWriter *self, SegReader *reader,
                             I32Array *doc_map, SortCache *sort_cache) {
     if (!sort_cache) { return; }
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
     SortFieldWriter *run
-        = SortFieldWriter_new(self->schema, self->snapshot, self->segment,
-                              self->polyreader, self->field, self->mem_pool,
-                              self->mem_thresh, NULL, NULL, NULL);
-    run->sort_cache = (SortCache*)INCREF(sort_cache);
-    run->doc_map    = (I32Array*)INCREF(doc_map);
-    run->run_max    = SegReader_Doc_Max(reader);
-    run->run_cardinality = SortCache_Get_Cardinality(sort_cache);
-    run->null_ord   = SortCache_Get_Null_Ord(sort_cache);
-    run->run_tick   = 1;
+        = SortFieldWriter_new(ivars->schema, ivars->snapshot, ivars->segment,
+                              ivars->polyreader, ivars->field, ivars->mem_pool,
+                              ivars->mem_thresh, NULL, NULL, NULL);
+    SortFieldWriterIVARS *const run_ivars = SortFieldWriter_IVARS(run);
+    run_ivars->sort_cache = (SortCache*)INCREF(sort_cache);
+    run_ivars->doc_map    = (I32Array*)INCREF(doc_map);
+    run_ivars->run_max    = SegReader_Doc_Max(reader);
+    run_ivars->run_cardinality = SortCache_Get_Cardinality(sort_cache);
+    run_ivars->null_ord   = SortCache_Get_Null_Ord(sort_cache);
+    run_ivars->run_tick   = 1;
     SortFieldWriter_Add_Run(self, (SortExternal*)run);
 }
 
@@ -322,10 +329,11 @@ S_write_val(Obj *val, int8_t prim_id, OutStream *ix_out, OutStream *dat_out,
 
 int
 SortFieldWriter_compare(SortFieldWriter *self, void *va, void *vb) {
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
     SFWriterElem *a = (SFWriterElem*)va;
     SFWriterElem *b = (SFWriterElem*)vb;
     int32_t comparison
-        = FType_null_back_compare_values(self->type, a->value, b->value);
+        = FType_null_back_compare_values(ivars->type, a->value, b->value);
     if (comparison == 0) { comparison = b->doc_id - a->doc_id; }
     return comparison;
 }
@@ -342,64 +350,68 @@ S_compare_doc_ids_by_ord_rev(void *context, const void *va, const void *vb) {
 
 static void
 S_lazy_init_sorted_ids(SortFieldWriter *self) {
-    if (!self->sorted_ids) {
-        self->sorted_ids
-            = (int32_t*)MALLOCATE((self->run_max + 1) * sizeof(int32_t));
-        for (int32_t i = 0, max = self->run_max; i <= max; i++) {
-            self->sorted_ids[i] = i;
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+    if (!ivars->sorted_ids) {
+        ivars->sorted_ids
+            = (int32_t*)MALLOCATE((ivars->run_max + 1) * sizeof(int32_t));
+        for (int32_t i = 0, max = ivars->run_max; i <= max; i++) {
+            ivars->sorted_ids[i] = i;
         }
-        Sort_quicksort(self->sorted_ids + 1, self->run_max, sizeof(int32_t),
-                       S_compare_doc_ids_by_ord_rev, self->sort_cache);
+        Sort_quicksort(ivars->sorted_ids + 1, ivars->run_max, sizeof(int32_t),
+                       S_compare_doc_ids_by_ord_rev, ivars->sort_cache);
     }
 }
 
 void
 SortFieldWriter_flush(SortFieldWriter *self) {
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+
     // Don't add a run unless we have data to put in it.
     if (SortFieldWriter_Cache_Count(self) == 0) { return; }
 
-    OutStream *const temp_ord_out = self->temp_ord_out;
-    OutStream *const temp_ix_out  = self->temp_ix_out;
-    OutStream *const temp_dat_out = self->temp_dat_out;
+    OutStream *const temp_ord_out = ivars->temp_ord_out;
+    OutStream *const temp_ix_out  = ivars->temp_ix_out;
+    OutStream *const temp_dat_out = ivars->temp_dat_out;
 
     SortFieldWriter_Sort_Cache(self);
     SortFieldWriter *run
-        = SortFieldWriter_new(self->schema, self->snapshot, self->segment,
-                              self->polyreader, self->field, self->mem_pool,
-                              self->mem_thresh, NULL, NULL, NULL);
+        = SortFieldWriter_new(ivars->schema, ivars->snapshot, ivars->segment,
+                              ivars->polyreader, ivars->field, ivars->mem_pool,
+                              ivars->mem_thresh, NULL, NULL, NULL);
+    SortFieldWriterIVARS *const run_ivars = SortFieldWriter_IVARS(run);
 
     // Record stream starts and align.
-    run->ord_start = OutStream_Align(temp_ord_out, sizeof(int64_t));
-    if (self->var_width) {
-        run->ix_start  = OutStream_Align(temp_ix_out, sizeof(int64_t));
+    run_ivars->ord_start = OutStream_Align(temp_ord_out, sizeof(int64_t));
+    if (ivars->var_width) {
+        run_ivars->ix_start  = OutStream_Align(temp_ix_out, sizeof(int64_t));
     }
-    run->dat_start = OutStream_Align(temp_dat_out, sizeof(int64_t));
+    run_ivars->dat_start = OutStream_Align(temp_dat_out, sizeof(int64_t));
 
     // Have the run borrow the array of elems.
-    run->cache      = self->cache;
-    run->cache_max  = self->cache_max;
-    run->cache_tick = self->cache_tick;
-    run->cache_cap  = self->cache_cap;
+    run_ivars->cache      = ivars->cache;
+    run_ivars->cache_max  = ivars->cache_max;
+    run_ivars->cache_tick = ivars->cache_tick;
+    run_ivars->cache_cap  = ivars->cache_cap;
 
     // Write files, record stats.
-    run->run_max = (int32_t)Seg_Get_Count(self->segment);
-    run->run_cardinality = S_write_files(run, temp_ord_out, temp_ix_out,
-                                         temp_dat_out);
+    run_ivars->run_max = (int32_t)Seg_Get_Count(ivars->segment);
+    run_ivars->run_cardinality = S_write_files(run, temp_ord_out, temp_ix_out,
+                                               temp_dat_out);
 
     // Reclaim the buffer from the run and empty it.
-    run->cache       = NULL;
-    run->cache_max   = 0;
-    run->cache_tick  = 0;
-    run->cache_cap   = 0;
-    self->cache_tick = self->cache_max;
+    run_ivars->cache       = NULL;
+    run_ivars->cache_max   = 0;
+    run_ivars->cache_tick  = 0;
+    run_ivars->cache_cap   = 0;
+    ivars->cache_tick = ivars->cache_max;
     SortFieldWriter_Clear_Cache(self);
 
     // Record stream ends.
-    run->ord_end = OutStream_Tell(temp_ord_out);
-    if (self->var_width) {
-        run->ix_end  = OutStream_Tell(temp_ix_out);
+    run_ivars->ord_end = OutStream_Tell(temp_ord_out);
+    if (ivars->var_width) {
+        run_ivars->ix_end  = OutStream_Tell(temp_ix_out);
     }
-    run->dat_end = OutStream_Tell(temp_dat_out);
+    run_ivars->dat_end = OutStream_Tell(temp_dat_out);
 
     // Add the run to the array.
     SortFieldWriter_Add_Run(self, (SortExternal*)run);
@@ -407,7 +419,8 @@ SortFieldWriter_flush(SortFieldWriter *self) {
 
 uint32_t
 SortFieldWriter_refill(SortFieldWriter *self) {
-    if (!self->sort_cache) { return 0; }
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+    if (!ivars->sort_cache) { return 0; }
 
     // Sanity check, then reset the cache and prepare to start loading items.
     uint32_t cache_count = SortFieldWriter_Cache_Count(self);
@@ -416,28 +429,28 @@ SortFieldWriter_refill(SortFieldWriter *self) {
               cache_count);
     }
     SortFieldWriter_Clear_Cache(self);
-    MemPool_Release_All(self->mem_pool);
+    MemPool_Release_All(ivars->mem_pool);
     S_lazy_init_sorted_ids(self);
 
-    const int32_t    null_ord   = self->null_ord;
-    Hash *const      uniq_vals  = self->uniq_vals;
-    I32Array *const  doc_map    = self->doc_map;
-    SortCache *const sort_cache = self->sort_cache;
+    const int32_t    null_ord   = ivars->null_ord;
+    Hash *const      uniq_vals  = ivars->uniq_vals;
+    I32Array *const  doc_map    = ivars->doc_map;
+    SortCache *const sort_cache = ivars->sort_cache;
     Obj *const       blank      = SortCache_Make_Blank(sort_cache);
 
-    while (self->run_ord < self->run_cardinality
-           && MemPool_Get_Consumed(self->mem_pool) < self->mem_thresh
+    while (ivars->run_ord < ivars->run_cardinality
+           && MemPool_Get_Consumed(ivars->mem_pool) < ivars->mem_thresh
           ) {
-        Obj *val = SortCache_Value(sort_cache, self->run_ord, blank);
+        Obj *val = SortCache_Value(sort_cache, ivars->run_ord, blank);
         if (val) {
             Hash_Store(uniq_vals, val, (Obj*)CFISH_TRUE);
             break;
         }
-        self->run_ord++;
+        ivars->run_ord++;
     }
     uint32_t count = 0;
-    while (self->run_tick <= self->run_max) {
-        int32_t raw_doc_id = self->sorted_ids[self->run_tick];
+    while (ivars->run_tick <= ivars->run_max) {
+        int32_t raw_doc_id = ivars->sorted_ids[ivars->run_tick];
         int32_t ord = SortCache_Ordinal(sort_cache, raw_doc_id);
         if (ord != null_ord) {
             int32_t remapped = doc_map
@@ -449,17 +462,17 @@ SortFieldWriter_refill(SortFieldWriter *self) {
                 count++;
             }
         }
-        else if (ord > self->run_ord) {
+        else if (ord > ivars->run_ord) {
             break;
         }
-        self->run_tick++;
+        ivars->run_tick++;
     }
-    self->run_ord++;
+    ivars->run_ord++;
     SortFieldWriter_Sort_Cache(self);
 
-    if (self->run_ord >= self->run_cardinality) {
-        DECREF(self->sort_cache);
-        self->sort_cache = NULL;
+    if (ivars->run_ord >= ivars->run_cardinality) {
+        DECREF(ivars->sort_cache);
+        ivars->sort_cache = NULL;
     }
 
     DECREF(blank);
@@ -468,11 +481,12 @@ SortFieldWriter_refill(SortFieldWriter *self) {
 
 void
 SortFieldWriter_flip(SortFieldWriter *self) {
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
     uint32_t num_items = SortFieldWriter_Cache_Count(self);
-    uint32_t num_runs = VA_Get_Size(self->runs);
+    uint32_t num_runs = VA_Get_Size(ivars->runs);
 
-    if (self->flipped) { THROW(ERR, "Can't call Flip() twice"); }
-    self->flipped = true;
+    if (ivars->flipped) { THROW(ERR, "Can't call Flip() twice"); }
+    ivars->flipped = true;
 
     // Sanity check.
     if (num_runs && num_items) {
@@ -484,40 +498,41 @@ SortFieldWriter_flip(SortFieldWriter *self) {
         SortFieldWriter_Sort_Cache(self);
     }
     else if (num_runs) {
-        Folder  *folder = PolyReader_Get_Folder(self->polyreader);
-        CharBuf *seg_name = Seg_Get_Name(self->segment);
+        Folder  *folder = PolyReader_Get_Folder(ivars->polyreader);
+        CharBuf *seg_name = Seg_Get_Name(ivars->segment);
         CharBuf *filepath = CB_newf("%o/sort_ord_temp", seg_name);
-        self->ord_in = Folder_Open_In(folder, filepath);
-        if (!self->ord_in) { RETHROW(INCREF(Err_get_error())); }
-        if (self->var_width) {
+        ivars->ord_in = Folder_Open_In(folder, filepath);
+        if (!ivars->ord_in) { RETHROW(INCREF(Err_get_error())); }
+        if (ivars->var_width) {
             CB_setf(filepath, "%o/sort_ix_temp", seg_name);
-            self->ix_in = Folder_Open_In(folder, filepath);
-            if (!self->ix_in) { RETHROW(INCREF(Err_get_error())); }
+            ivars->ix_in = Folder_Open_In(folder, filepath);
+            if (!ivars->ix_in) { RETHROW(INCREF(Err_get_error())); }
         }
         CB_setf(filepath, "%o/sort_dat_temp", seg_name);
-        self->dat_in = Folder_Open_In(folder, filepath);
-        if (!self->dat_in) { RETHROW(INCREF(Err_get_error())); }
+        ivars->dat_in = Folder_Open_In(folder, filepath);
+        if (!ivars->dat_in) { RETHROW(INCREF(Err_get_error())); }
         DECREF(filepath);
 
         // Assign streams and a slice of mem_thresh.
-        size_t sub_thresh = self->mem_thresh / num_runs;
+        size_t sub_thresh = ivars->mem_thresh / num_runs;
         if (sub_thresh < 65536) { sub_thresh = 65536; }
         for (uint32_t i = 0; i < num_runs; i++) {
-            SortFieldWriter *run = (SortFieldWriter*)VA_Fetch(self->runs, i);
-            S_flip_run(run, sub_thresh, self->ord_in, self->ix_in,
-                       self->dat_in);
+            SortFieldWriter *run = (SortFieldWriter*)VA_Fetch(ivars->runs, i);
+            S_flip_run(run, sub_thresh, ivars->ord_in, ivars->ix_in,
+                       ivars->dat_in);
         }
     }
 
-    self->flipped = true;
+    ivars->flipped = true;
 }
 
 static int32_t
 S_write_files(SortFieldWriter *self, OutStream *ord_out, OutStream *ix_out,
               OutStream *dat_out) {
-    int8_t    prim_id   = self->prim_id;
-    int32_t   doc_max   = (int32_t)Seg_Get_Count(self->segment);
-    bool      has_nulls = self->count == doc_max ? false : true;
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+    int8_t    prim_id   = ivars->prim_id;
+    int32_t   doc_max   = (int32_t)Seg_Get_Count(ivars->segment);
+    bool      has_nulls = ivars->count == doc_max ? false : true;
     size_t    size      = (doc_max + 1) * sizeof(int32_t);
     int32_t  *ords      = (int32_t*)MALLOCATE(size);
     int32_t   ord       = 0;
@@ -541,7 +556,7 @@ S_write_files(SortFieldWriter *self, OutStream *ord_out, OutStream *ix_out,
     while (NULL != (elem = (SFWriterElem*)SortFieldWriter_Fetch(self))) {
         if (elem->value != last_val_address) {
             int32_t comparison
-                = FType_Compare_Values(self->type, elem->value, val);
+                = FType_Compare_Values(ivars->type, elem->value, val);
             if (comparison != 0) {
                 ord++;
                 S_write_val(elem->value, prim_id, ix_out, dat_out, dat_start);
@@ -557,19 +572,19 @@ S_write_files(SortFieldWriter *self, OutStream *ord_out, OutStream *ix_out,
     if (has_nulls) {
         S_write_val(NULL, prim_id, ix_out, dat_out, dat_start);
         ord++;
-        self->null_ord = ord;
+        ivars->null_ord = ord;
     }
-    int32_t null_ord = self->null_ord;
+    int32_t null_ord = ivars->null_ord;
 
     // Write one extra file pointer so that we can always derive length.
-    if (self->var_width) {
+    if (ivars->var_width) {
         OutStream_Write_I64(ix_out, OutStream_Tell(dat_out) - dat_start);
     }
 
     // Calculate cardinality and ord width.
     int32_t cardinality = ord + 1;
-    self->ord_width     = S_calc_width(cardinality);
-    int32_t ord_width   = self->ord_width;
+    ivars->ord_width     = S_calc_width(cardinality);
+    int32_t ord_width   = ivars->ord_width;
 
     // Write ords.
     const double BITS_PER_BYTE = 8.0;
@@ -590,19 +605,21 @@ S_write_files(SortFieldWriter *self, OutStream *ord_out, OutStream *ix_out,
 
 int32_t
 SortFieldWriter_finish(SortFieldWriter *self) {
+    SortFieldWriterIVARS *const ivars = SortFieldWriter_IVARS(self);
+
     // Bail if there's no data.
     if (!SortFieldWriter_Peek(self)) { return 0; }
 
-    int32_t  field_num = self->field_num;
-    Folder  *folder    = PolyReader_Get_Folder(self->polyreader);
-    CharBuf *seg_name  = Seg_Get_Name(self->segment);
+    int32_t  field_num = ivars->field_num;
+    Folder  *folder    = PolyReader_Get_Folder(ivars->polyreader);
+    CharBuf *seg_name  = Seg_Get_Name(ivars->segment);
     CharBuf *path      = CB_newf("%o/sort-%i32.ord", seg_name, field_num);
 
     // Open streams.
     OutStream *ord_out = Folder_Open_Out(folder, path);
     if (!ord_out) { RETHROW(INCREF(Err_get_error())); }
     OutStream *ix_out = NULL;
-    if (self->var_width) {
+    if (ivars->var_width) {
         CB_setf(path, "%o/sort-%i32.ix", seg_name, field_num);
         ix_out = Folder_Open_Out(folder, path);
         if (!ix_out) { RETHROW(INCREF(Err_get_error())); }
@@ -628,78 +645,80 @@ SortFieldWriter_finish(SortFieldWriter *self) {
 static void
 S_flip_run(SortFieldWriter *run, size_t sub_thresh, InStream *ord_in,
            InStream *ix_in, InStream *dat_in) {
-    if (run->flipped) { THROW(ERR, "Can't Flip twice"); }
-    run->flipped = true;
+    SortFieldWriterIVARS *const run_ivars = SortFieldWriter_IVARS(run);
+
+    if (run_ivars->flipped) { THROW(ERR, "Can't Flip twice"); }
+    run_ivars->flipped = true;
 
     // Get our own MemoryPool, ZombieKeyedHash, and slice of mem_thresh.
-    DECREF(run->uniq_vals);
-    DECREF(run->mem_pool);
-    run->mem_pool   = MemPool_new(0);
-    run->uniq_vals  = (Hash*)ZKHash_new(run->mem_pool, run->prim_id);
-    run->mem_thresh = sub_thresh;
+    DECREF(run_ivars->uniq_vals);
+    DECREF(run_ivars->mem_pool);
+    run_ivars->mem_pool   = MemPool_new(0);
+    run_ivars->uniq_vals  = (Hash*)ZKHash_new(run_ivars->mem_pool, run_ivars->prim_id);
+    run_ivars->mem_thresh = sub_thresh;
 
     // Done if we already have a SortCache to read from.
-    if (run->sort_cache) { return; }
+    if (run_ivars->sort_cache) { return; }
 
     // Open the temp files for reading.
-    CharBuf *seg_name = Seg_Get_Name(run->segment);
+    CharBuf *seg_name = Seg_Get_Name(run_ivars->segment);
     CharBuf *alias    = CB_newf("%o/sort_ord_temp-%i64-to-%i64", seg_name,
-                                run->ord_start, run->ord_end);
-    InStream *ord_in_dupe = InStream_Reopen(ord_in, alias, run->ord_start,
-                                            run->ord_end - run->ord_start);
+                                run_ivars->ord_start, run_ivars->ord_end);
+    InStream *ord_in_dupe = InStream_Reopen(ord_in, alias, run_ivars->ord_start,
+                                            run_ivars->ord_end - run_ivars->ord_start);
     InStream *ix_in_dupe = NULL;
-    if (run->var_width) {
+    if (run_ivars->var_width) {
         CB_setf(alias, "%o/sort_ix_temp-%i64-to-%i64", seg_name,
-                run->ix_start, run->ix_end);
-        ix_in_dupe = InStream_Reopen(ix_in, alias, run->ix_start,
-                                     run->ix_end - run->ix_start);
+                run_ivars->ix_start, run_ivars->ix_end);
+        ix_in_dupe = InStream_Reopen(ix_in, alias, run_ivars->ix_start,
+                                     run_ivars->ix_end - run_ivars->ix_start);
     }
     CB_setf(alias, "%o/sort_dat_temp-%i64-to-%i64", seg_name,
-            run->dat_start, run->dat_end);
-    InStream *dat_in_dupe = InStream_Reopen(dat_in, alias, run->dat_start,
-                                            run->dat_end - run->dat_start);
+            run_ivars->dat_start, run_ivars->dat_end);
+    InStream *dat_in_dupe = InStream_Reopen(dat_in, alias, run_ivars->dat_start,
+                                            run_ivars->dat_end - run_ivars->dat_start);
     DECREF(alias);
 
     // Get a SortCache.
-    CharBuf *field = Seg_Field_Name(run->segment, run->field_num);
-    switch (run->prim_id & FType_PRIMITIVE_ID_MASK) {
+    CharBuf *field = Seg_Field_Name(run_ivars->segment, run_ivars->field_num);
+    switch (run_ivars->prim_id & FType_PRIMITIVE_ID_MASK) {
         case FType_TEXT:
-            run->sort_cache = (SortCache*)TextSortCache_new(
-                                  field, run->type, run->run_cardinality,
-                                  run->run_max, run->null_ord,
-                                  run->ord_width, ord_in_dupe,
+            run_ivars->sort_cache = (SortCache*)TextSortCache_new(
+                                  field, run_ivars->type, run_ivars->run_cardinality,
+                                  run_ivars->run_max, run_ivars->null_ord,
+                                  run_ivars->ord_width, ord_in_dupe,
                                   ix_in_dupe, dat_in_dupe);
             break;
         case FType_INT32:
-            run->sort_cache = (SortCache*)I32SortCache_new(
-                                  field, run->type, run->run_cardinality,
-                                  run->run_max, run->null_ord,
-                                  run->ord_width, ord_in_dupe,
+            run_ivars->sort_cache = (SortCache*)I32SortCache_new(
+                                  field, run_ivars->type, run_ivars->run_cardinality,
+                                  run_ivars->run_max, run_ivars->null_ord,
+                                  run_ivars->ord_width, ord_in_dupe,
                                   dat_in_dupe);
             break;
         case FType_INT64:
-            run->sort_cache = (SortCache*)I64SortCache_new(
-                                  field, run->type, run->run_cardinality,
-                                  run->run_max, run->null_ord,
-                                  run->ord_width, ord_in_dupe,
+            run_ivars->sort_cache = (SortCache*)I64SortCache_new(
+                                  field, run_ivars->type, run_ivars->run_cardinality,
+                                  run_ivars->run_max, run_ivars->null_ord,
+                                  run_ivars->ord_width, ord_in_dupe,
                                   dat_in_dupe);
             break;
         case FType_FLOAT32:
-            run->sort_cache = (SortCache*)F32SortCache_new(
-                                  field, run->type, run->run_cardinality,
-                                  run->run_max, run->null_ord,
-                                  run->ord_width, ord_in_dupe,
+            run_ivars->sort_cache = (SortCache*)F32SortCache_new(
+                                  field, run_ivars->type, run_ivars->run_cardinality,
+                                  run_ivars->run_max, run_ivars->null_ord,
+                                  run_ivars->ord_width, ord_in_dupe,
                                   dat_in_dupe);
             break;
         case FType_FLOAT64:
-            run->sort_cache = (SortCache*)F64SortCache_new(
-                                  field, run->type, run->run_cardinality,
-                                  run->run_max, run->null_ord,
-                                  run->ord_width, ord_in_dupe,
+            run_ivars->sort_cache = (SortCache*)F64SortCache_new(
+                                  field, run_ivars->type, run_ivars->run_cardinality,
+                                  run_ivars->run_max, run_ivars->null_ord,
+                                  run_ivars->ord_width, ord_in_dupe,
                                   dat_in_dupe);
             break;
         default:
-            THROW(ERR, "No SortCache class for %o", run->type);
+            THROW(ERR, "No SortCache class for %o", run_ivars->type);
     }
 
     DECREF(ord_in_dupe);

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/SortReader.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/SortReader.c b/core/Lucy/Index/SortReader.c
index 159d837..25f2df4 100644
--- a/core/Lucy/Index/SortReader.c
+++ b/core/Lucy/Index/SortReader.c
@@ -58,57 +58,56 @@ DefSortReader_new(Schema *schema, Folder *folder, Snapshot *snapshot,
 DefaultSortReader*
 DefSortReader_init(DefaultSortReader *self, Schema *schema, Folder *folder,
                    Snapshot *snapshot, VArray *segments, int32_t seg_tick) {
-    Segment *segment;
-    Hash    *metadata;
     DataReader_init((DataReader*)self, schema, folder, snapshot, segments,
                     seg_tick);
-    segment = DefSortReader_Get_Segment(self);
-    metadata = (Hash*)Seg_Fetch_Metadata_Str(segment, "sort", 4);
+    DefaultSortReaderIVARS *const ivars = DefSortReader_IVARS(self);
+    Segment *segment  = DefSortReader_Get_Segment(self);
+    Hash    *metadata = (Hash*)Seg_Fetch_Metadata_Str(segment, "sort", 4);
 
     // Check format.
-    self->format = 0;
+    ivars->format = 0;
     if (metadata) {
         Obj *format = Hash_Fetch_Str(metadata, "format", 6);
         if (!format) { THROW(ERR, "Missing 'format' var"); }
         else {
-            self->format = (int32_t)Obj_To_I64(format);
-            if (self->format < 2 || self->format > 3) {
+            ivars->format = (int32_t)Obj_To_I64(format);
+            if (ivars->format < 2 || ivars->format > 3) {
                 THROW(ERR, "Unsupported sort cache format: %i32",
-                      self->format);
+                      ivars->format);
             }
         }
     }
 
     // Init.
-    self->caches = Hash_new(0);
+    ivars->caches = Hash_new(0);
 
     // Either extract or fake up the "counts", "null_ords", and "ord_widths"
     // hashes.
     if (metadata) {
-        self->counts
+        ivars->counts
             = (Hash*)INCREF(CERTIFY(Hash_Fetch_Str(metadata, "counts", 6),
                                     HASH));
-        self->null_ords = (Hash*)Hash_Fetch_Str(metadata, "null_ords", 9);
-        if (self->null_ords) {
-            CERTIFY(self->null_ords, HASH);
-            INCREF(self->null_ords);
+        ivars->null_ords = (Hash*)Hash_Fetch_Str(metadata, "null_ords", 9);
+        if (ivars->null_ords) {
+            CERTIFY(ivars->null_ords, HASH);
+            INCREF(ivars->null_ords);
         }
         else {
-            self->null_ords = Hash_new(0);
+            ivars->null_ords = Hash_new(0);
         }
-        self->ord_widths = (Hash*)Hash_Fetch_Str(metadata, "ord_widths", 10);
-        if (self->ord_widths) {
-            CERTIFY(self->ord_widths, HASH);
-            INCREF(self->ord_widths);
+        ivars->ord_widths = (Hash*)Hash_Fetch_Str(metadata, "ord_widths", 10);
+        if (ivars->ord_widths) {
+            CERTIFY(ivars->ord_widths, HASH);
+            INCREF(ivars->ord_widths);
         }
         else {
-            self->ord_widths = Hash_new(0);
+            ivars->ord_widths = Hash_new(0);
         }
     }
     else {
-        self->counts     = Hash_new(0);
-        self->null_ords  = Hash_new(0);
-        self->ord_widths = Hash_new(0);
+        ivars->counts     = Hash_new(0);
+        ivars->null_ords  = Hash_new(0);
+        ivars->ord_widths = Hash_new(0);
     }
 
     return self;
@@ -116,30 +115,32 @@ DefSortReader_init(DefaultSortReader *self, Schema *schema, Folder *folder,
 
 void
 DefSortReader_close(DefaultSortReader *self) {
-    if (self->caches) {
-        Hash_Dec_RefCount(self->caches);
-        self->caches = NULL;
+    DefaultSortReaderIVARS *const ivars = DefSortReader_IVARS(self);
+    if (ivars->caches) {
+        Hash_Dec_RefCount(ivars->caches);
+        ivars->caches = NULL;
     }
-    if (self->counts) {
-        Hash_Dec_RefCount(self->counts);
-        self->counts = NULL;
+    if (ivars->counts) {
+        Hash_Dec_RefCount(ivars->counts);
+        ivars->counts = NULL;
     }
-    if (self->null_ords) {
-        Hash_Dec_RefCount(self->null_ords);
-        self->null_ords = NULL;
+    if (ivars->null_ords) {
+        Hash_Dec_RefCount(ivars->null_ords);
+        ivars->null_ords = NULL;
     }
-    if (self->ord_widths) {
-        Hash_Dec_RefCount(self->ord_widths);
-        self->ord_widths = NULL;
+    if (ivars->ord_widths) {
+        Hash_Dec_RefCount(ivars->ord_widths);
+        ivars->ord_widths = NULL;
     }
 }
 
 void
 DefSortReader_destroy(DefaultSortReader *self) {
-    DECREF(self->caches);
-    DECREF(self->counts);
-    DECREF(self->null_ords);
-    DECREF(self->ord_widths);
+    DefaultSortReaderIVARS *const ivars = DefSortReader_IVARS(self);
+    DECREF(ivars->caches);
+    DECREF(ivars->counts);
+    DECREF(ivars->null_ords);
+    DECREF(ivars->ord_widths);
     SUPER_DESTROY(self, DEFAULTSORTREADER);
 }
 
@@ -155,8 +156,10 @@ S_calc_ord_width(int32_t cardinality) {
 
 static SortCache*
 S_lazy_init_sort_cache(DefaultSortReader *self, const CharBuf *field) {
+    DefaultSortReaderIVARS *const ivars = DefSortReader_IVARS(self);
+
     // See if we have any values.
-    Obj *count_obj = Hash_Fetch(self->counts, (Obj*)field);
+    Obj *count_obj = Hash_Fetch(ivars->counts, (Obj*)field);
     int32_t count = count_obj ? (int32_t)Obj_To_I64(count_obj) : 0;
     if (!count) { return NULL; }
 
@@ -203,9 +206,9 @@ S_lazy_init_sort_cache(DefaultSortReader *self, const CharBuf *field) {
     }
     DECREF(path);
 
-    Obj     *null_ord_obj = Hash_Fetch(self->null_ords, (Obj*)field);
+    Obj     *null_ord_obj = Hash_Fetch(ivars->null_ords, (Obj*)field);
     int32_t  null_ord = null_ord_obj ? (int32_t)Obj_To_I64(null_ord_obj) : -1;
-    Obj     *ord_width_obj = Hash_Fetch(self->ord_widths, (Obj*)field);
+    Obj     *ord_width_obj = Hash_Fetch(ivars->ord_widths, (Obj*)field);
     int32_t  ord_width = ord_width_obj
                          ? (int32_t)Obj_To_I64(ord_width_obj)
                          : S_calc_ord_width(count);
@@ -241,9 +244,9 @@ S_lazy_init_sort_cache(DefaultSortReader *self, const CharBuf *field) {
         default:
             THROW(ERR, "No SortCache class for %o", type);
     }
-    Hash_Store(self->caches, (Obj*)field, (Obj*)cache);
+    Hash_Store(ivars->caches, (Obj*)field, (Obj*)cache);
 
-    if (self->format == 2) { // bug compatibility
+    if (ivars->format == 2) { // bug compatibility
         SortCache_Set_Native_Ords(cache, true);
     }
 
@@ -259,7 +262,8 @@ DefSortReader_fetch_sort_cache(DefaultSortReader *self, const CharBuf *field) {
     SortCache *cache = NULL;
 
     if (field) {
-        cache = (SortCache*)Hash_Fetch(self->caches, (Obj*)field);
+        DefaultSortReaderIVARS *const ivars = DefSortReader_IVARS(self);
+        cache = (SortCache*)Hash_Fetch(ivars->caches, (Obj*)field);
         if (!cache) {
             cache = S_lazy_init_sort_cache(self, field);
         }

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/SortWriter.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/SortWriter.c b/core/Lucy/Index/SortWriter.c
index fedde9a..28a88b7 100644
--- a/core/Lucy/Index/SortWriter.c
+++ b/core/Lucy/Index/SortWriter.c
@@ -52,32 +52,34 @@ SortWriter_init(SortWriter *self, Schema *schema, Snapshot *snapshot,
                 Segment *segment, PolyReader *polyreader) {
     uint32_t field_max = Schema_Num_Fields(schema) + 1;
     DataWriter_init((DataWriter*)self, schema, snapshot, segment, polyreader);
+    SortWriterIVARS *const ivars = SortWriter_IVARS(self);
 
     // Init.
-    self->field_writers   = VA_new(field_max);
-    self->counts          = Hash_new(0);
-    self->null_ords       = Hash_new(0);
-    self->ord_widths      = Hash_new(0);
-    self->temp_ord_out    = NULL;
-    self->temp_ix_out     = NULL;
-    self->temp_dat_out    = NULL;
-    self->mem_pool        = MemPool_new(0);
-    self->mem_thresh      = default_mem_thresh;
-    self->flush_at_finish = false;
+    ivars->field_writers   = VA_new(field_max);
+    ivars->counts          = Hash_new(0);
+    ivars->null_ords       = Hash_new(0);
+    ivars->ord_widths      = Hash_new(0);
+    ivars->temp_ord_out    = NULL;
+    ivars->temp_ix_out     = NULL;
+    ivars->temp_dat_out    = NULL;
+    ivars->mem_pool        = MemPool_new(0);
+    ivars->mem_thresh      = default_mem_thresh;
+    ivars->flush_at_finish = false;
 
     return self;
 }
 
 void
 SortWriter_destroy(SortWriter *self) {
-    DECREF(self->field_writers);
-    DECREF(self->counts);
-    DECREF(self->null_ords);
-    DECREF(self->ord_widths);
-    DECREF(self->temp_ord_out);
-    DECREF(self->temp_ix_out);
-    DECREF(self->temp_dat_out);
-    DECREF(self->mem_pool);
+    SortWriterIVARS *const ivars = SortWriter_IVARS(self);
+    DECREF(ivars->field_writers);
+    DECREF(ivars->counts);
+    DECREF(ivars->null_ords);
+    DECREF(ivars->ord_widths);
+    DECREF(ivars->temp_ord_out);
+    DECREF(ivars->temp_ix_out);
+    DECREF(ivars->temp_dat_out);
+    DECREF(ivars->mem_pool);
     SUPER_DESTROY(self, SORTWRITER);
 }
 
@@ -88,42 +90,44 @@ SortWriter_set_default_mem_thresh(size_t mem_thresh) {
 
 static SortFieldWriter*
 S_lazy_init_field_writer(SortWriter *self, int32_t field_num) {
+    SortWriterIVARS *const ivars = SortWriter_IVARS(self);
+
     SortFieldWriter *field_writer
-        = (SortFieldWriter*)VA_Fetch(self->field_writers, field_num);
+        = (SortFieldWriter*)VA_Fetch(ivars->field_writers, field_num);
     if (!field_writer) {
 
         // Open temp files.
-        if (!self->temp_ord_out) {
-            Folder  *folder   = self->folder;
-            CharBuf *seg_name = Seg_Get_Name(self->segment);
+        if (!ivars->temp_ord_out) {
+            Folder  *folder   = ivars->folder;
+            CharBuf *seg_name = Seg_Get_Name(ivars->segment);
             CharBuf *path     = CB_newf("%o/sort_ord_temp", seg_name);
-            self->temp_ord_out = Folder_Open_Out(folder, path);
-            if (!self->temp_ord_out) {
+            ivars->temp_ord_out = Folder_Open_Out(folder, path);
+            if (!ivars->temp_ord_out) {
                 DECREF(path);
                 RETHROW(INCREF(Err_get_error()));
             }
             CB_setf(path, "%o/sort_ix_temp", seg_name);
-            self->temp_ix_out = Folder_Open_Out(folder, path);
-            if (!self->temp_ix_out) {
+            ivars->temp_ix_out = Folder_Open_Out(folder, path);
+            if (!ivars->temp_ix_out) {
                 DECREF(path);
                 RETHROW(INCREF(Err_get_error()));
             }
             CB_setf(path, "%o/sort_dat_temp", seg_name);
-            self->temp_dat_out = Folder_Open_Out(folder, path);
-            if (!self->temp_dat_out) {
+            ivars->temp_dat_out = Folder_Open_Out(folder, path);
+            if (!ivars->temp_dat_out) {
                 DECREF(path);
                 RETHROW(INCREF(Err_get_error()));
             }
             DECREF(path);
         }
 
-        CharBuf *field = Seg_Field_Name(self->segment, field_num);
+        CharBuf *field = Seg_Field_Name(ivars->segment, field_num);
         field_writer
-            = SortFieldWriter_new(self->schema, self->snapshot, self->segment,
-                                  self->polyreader, field, self->mem_pool,
-                                  self->mem_thresh, self->temp_ord_out,
-                                  self->temp_ix_out, self->temp_dat_out);
-        VA_Store(self->field_writers, field_num, (Obj*)field_writer);
+            = SortFieldWriter_new(ivars->schema, ivars->snapshot, ivars->segment,
+                                  ivars->polyreader, field, ivars->mem_pool,
+                                  ivars->mem_thresh, ivars->temp_ord_out,
+                                  ivars->temp_ix_out, ivars->temp_dat_out);
+        VA_Store(ivars->field_writers, field_num, (Obj*)field_writer);
     }
     return field_writer;
 }
@@ -131,6 +135,7 @@ S_lazy_init_field_writer(SortWriter *self, int32_t field_num) {
 void
 SortWriter_add_inverted_doc(SortWriter *self, Inverter *inverter,
                             int32_t doc_id) {
+    SortWriterIVARS *const ivars = SortWriter_IVARS(self);
     int32_t field_num;
 
     Inverter_Iterate(inverter);
@@ -146,21 +151,22 @@ SortWriter_add_inverted_doc(SortWriter *self, Inverter *inverter,
 
     // If our SortFieldWriters have collectively passed the memory threshold,
     // flush all of them, then release all unique values with a single action.
-    if (MemPool_Get_Consumed(self->mem_pool) > self->mem_thresh) {
-        for (uint32_t i = 0; i < VA_Get_Size(self->field_writers); i++) {
+    if (MemPool_Get_Consumed(ivars->mem_pool) > ivars->mem_thresh) {
+        for (uint32_t i = 0; i < VA_Get_Size(ivars->field_writers); i++) {
             SortFieldWriter *const field_writer
-                = (SortFieldWriter*)VA_Fetch(self->field_writers, i);
+                = (SortFieldWriter*)VA_Fetch(ivars->field_writers, i);
             if (field_writer) { SortFieldWriter_Flush(field_writer); }
         }
-        MemPool_Release_All(self->mem_pool);
-        self->flush_at_finish = true;
+        MemPool_Release_All(ivars->mem_pool);
+        ivars->flush_at_finish = true;
     }
 }
 
 void
 SortWriter_add_segment(SortWriter *self, SegReader *reader,
                        I32Array *doc_map) {
-    VArray *fields = Schema_All_Fields(self->schema);
+    SortWriterIVARS *const ivars = SortWriter_IVARS(self);
+    VArray *fields = Schema_All_Fields(ivars->schema);
 
     // Proceed field-at-a-time, rather than doc-at-a-time.
     for (uint32_t i = 0, max = VA_Get_Size(fields); i < max; i++) {
@@ -171,11 +177,11 @@ SortWriter_add_segment(SortWriter *self, SegReader *reader,
                            ? SortReader_Fetch_Sort_Cache(sort_reader, field)
                            : NULL;
         if (cache) {
-            int32_t field_num = Seg_Field_Num(self->segment, field);
+            int32_t field_num = Seg_Field_Num(ivars->segment, field);
             SortFieldWriter *field_writer
                 = S_lazy_init_field_writer(self, field_num);
             SortFieldWriter_Add_Segment(field_writer, reader, doc_map, cache);
-            self->flush_at_finish = true;
+            ivars->flush_at_finish = true;
         }
     }
 
@@ -184,14 +190,15 @@ SortWriter_add_segment(SortWriter *self, SegReader *reader,
 
 void
 SortWriter_finish(SortWriter *self) {
-    VArray *const field_writers = self->field_writers;
+    SortWriterIVARS *const ivars = SortWriter_IVARS(self);
+    VArray *const field_writers = ivars->field_writers;
 
     // If we have no data, bail out.
-    if (!self->temp_ord_out) { return; }
+    if (!ivars->temp_ord_out) { return; }
 
     // If we've either flushed or added segments, flush everything so that any
     // one field can use the entire margin up to mem_thresh.
-    if (self->flush_at_finish) {
+    if (ivars->flush_at_finish) {
         for (uint32_t i = 1, max = VA_Get_Size(field_writers); i < max; i++) {
             SortFieldWriter *field_writer
                 = (SortFieldWriter*)VA_Fetch(field_writers, i);
@@ -202,26 +209,26 @@ SortWriter_finish(SortWriter *self) {
     }
 
     // Close down temp streams.
-    OutStream_Close(self->temp_ord_out);
-    OutStream_Close(self->temp_ix_out);
-    OutStream_Close(self->temp_dat_out);
+    OutStream_Close(ivars->temp_ord_out);
+    OutStream_Close(ivars->temp_ix_out);
+    OutStream_Close(ivars->temp_dat_out);
 
     for (uint32_t i = 1, max = VA_Get_Size(field_writers); i < max; i++) {
         SortFieldWriter *field_writer
             = (SortFieldWriter*)VA_Delete(field_writers, i);
         if (field_writer) {
-            CharBuf *field = Seg_Field_Name(self->segment, i);
+            CharBuf *field = Seg_Field_Name(ivars->segment, i);
             SortFieldWriter_Flip(field_writer);
             int32_t count = SortFieldWriter_Finish(field_writer);
-            Hash_Store(self->counts, (Obj*)field,
+            Hash_Store(ivars->counts, (Obj*)field,
                        (Obj*)CB_newf("%i32", count));
             int32_t null_ord = SortFieldWriter_Get_Null_Ord(field_writer);
             if (null_ord != -1) {
-                Hash_Store(self->null_ords, (Obj*)field,
+                Hash_Store(ivars->null_ords, (Obj*)field,
                            (Obj*)CB_newf("%i32", null_ord));
             }
             int32_t ord_width = SortFieldWriter_Get_Ord_Width(field_writer);
-            Hash_Store(self->ord_widths, (Obj*)field,
+            Hash_Store(ivars->ord_widths, (Obj*)field,
                        (Obj*)CB_newf("%i32", ord_width));
         }
 
@@ -230,12 +237,12 @@ SortWriter_finish(SortWriter *self) {
     VA_Clear(field_writers);
 
     // Store metadata.
-    Seg_Store_Metadata_Str(self->segment, "sort", 4,
+    Seg_Store_Metadata_Str(ivars->segment, "sort", 4,
                            (Obj*)SortWriter_Metadata(self));
 
     // Clean up.
-    Folder  *folder   = self->folder;
-    CharBuf *seg_name = Seg_Get_Name(self->segment);
+    Folder  *folder   = ivars->folder;
+    CharBuf *seg_name = Seg_Get_Name(ivars->segment);
     CharBuf *path     = CB_newf("%o/sort_ord_temp", seg_name);
     Folder_Delete(folder, path);
     CB_setf(path, "%o/sort_ix_temp", seg_name);
@@ -247,10 +254,11 @@ SortWriter_finish(SortWriter *self) {
 
 Hash*
 SortWriter_metadata(SortWriter *self) {
+    SortWriterIVARS *const ivars = SortWriter_IVARS(self);
     Hash *const metadata  = DataWriter_metadata((DataWriter*)self);
-    Hash_Store_Str(metadata, "counts", 6, INCREF(self->counts));
-    Hash_Store_Str(metadata, "null_ords", 9, INCREF(self->null_ords));
-    Hash_Store_Str(metadata, "ord_widths", 10, INCREF(self->ord_widths));
+    Hash_Store_Str(metadata, "counts", 6, INCREF(ivars->counts));
+    Hash_Store_Str(metadata, "null_ords", 9, INCREF(ivars->null_ords));
+    Hash_Store_Str(metadata, "ord_widths", 10, INCREF(ivars->ord_widths));
     return metadata;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/TermInfo.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/TermInfo.c b/core/Lucy/Index/TermInfo.c
index ef40da2..b4fc2a9 100644
--- a/core/Lucy/Index/TermInfo.c
+++ b/core/Lucy/Index/TermInfo.c
@@ -28,91 +28,98 @@ TInfo_new(int32_t doc_freq) {
 
 TermInfo*
 TInfo_init(TermInfo *self, int32_t doc_freq) {
-    self->doc_freq      = doc_freq;
-    self->post_filepos  = 0;
-    self->skip_filepos  = 0;
-    self->lex_filepos   = 0;
+    TermInfoIVARS *const ivars = TInfo_IVARS(self);
+    ivars->doc_freq      = doc_freq;
+    ivars->post_filepos  = 0;
+    ivars->skip_filepos  = 0;
+    ivars->lex_filepos   = 0;
     return self;
 }
 
 TermInfo*
 TInfo_clone(TermInfo *self) {
-    TermInfo *twin = TInfo_new(self->doc_freq);
-    twin->post_filepos = self->post_filepos;
-    twin->skip_filepos = self->skip_filepos;
-    twin->lex_filepos  = self->lex_filepos;
+    TermInfoIVARS *const ivars = TInfo_IVARS(self);
+    TermInfo *twin = TInfo_new(ivars->doc_freq);
+    TermInfoIVARS *const twin_ivars = TInfo_IVARS(twin);
+    twin_ivars->post_filepos = ivars->post_filepos;
+    twin_ivars->skip_filepos = ivars->skip_filepos;
+    twin_ivars->lex_filepos  = ivars->lex_filepos;
     return twin;
 }
 
 int32_t
 TInfo_get_doc_freq(TermInfo *self) {
-    return self->doc_freq;
+    return TInfo_IVARS(self)->doc_freq;
 }
 
 int64_t
 TInfo_get_lex_filepos(TermInfo *self) {
-    return self->lex_filepos;
+    return TInfo_IVARS(self)->lex_filepos;
 }
 
 int64_t
 TInfo_get_post_filepos(TermInfo *self) {
-    return self->post_filepos;
+    return TInfo_IVARS(self)->post_filepos;
 }
 
 int64_t
 TInfo_get_skip_filepos(TermInfo *self) {
-    return self->skip_filepos;
+    return TInfo_IVARS(self)->skip_filepos;
 }
 
 void
 TInfo_set_doc_freq(TermInfo *self, int32_t doc_freq) {
-    self->doc_freq = doc_freq;
+    TInfo_IVARS(self)->doc_freq = doc_freq;
 }
 
 void
 TInfo_set_lex_filepos(TermInfo *self, int64_t filepos) {
-    self->lex_filepos = filepos;
+    TInfo_IVARS(self)->lex_filepos = filepos;
 }
 
 void
 TInfo_set_post_filepos(TermInfo *self, int64_t filepos) {
-    self->post_filepos = filepos;
+    TInfo_IVARS(self)->post_filepos = filepos;
 }
 
 void
 TInfo_set_skip_filepos(TermInfo *self, int64_t filepos) {
-    self->skip_filepos = filepos;
+    TInfo_IVARS(self)->skip_filepos = filepos;
 }
 
 // TODO: this should probably be some sort of Dump variant rather than
 // To_String.
 CharBuf*
 TInfo_to_string(TermInfo *self) {
+    TermInfoIVARS *const ivars = TInfo_IVARS(self);
     return CB_newf(
                "doc freq:      %i32\n"
                "post filepos:  %i64\n"
                "skip filepos:  %i64\n"
                "index filepos: %i64",
-               self->doc_freq, self->post_filepos,
-               self->skip_filepos, self->lex_filepos
+               ivars->doc_freq, ivars->post_filepos,
+               ivars->skip_filepos, ivars->lex_filepos
            );
 }
 
 void
 TInfo_mimic(TermInfo *self, Obj *other) {
-    TermInfo *twin = (TermInfo*)CERTIFY(other, TERMINFO);
-    self->doc_freq     = twin->doc_freq;
-    self->post_filepos = twin->post_filepos;
-    self->skip_filepos = twin->skip_filepos;
-    self->lex_filepos  = twin->lex_filepos;
+    CERTIFY(other, TERMINFO);
+    TermInfoIVARS *const ivars = TInfo_IVARS(self);
+    TermInfoIVARS *const ovars = TInfo_IVARS((TermInfo*)other);
+    ivars->doc_freq     = ovars->doc_freq;
+    ivars->post_filepos = ovars->post_filepos;
+    ivars->skip_filepos = ovars->skip_filepos;
+    ivars->lex_filepos  = ovars->lex_filepos;
 }
 
 void
 TInfo_reset(TermInfo *self) {
-    self->doc_freq      = 0;
-    self->post_filepos  = 0;
-    self->skip_filepos  = 0;
-    self->lex_filepos   = 0;
+    TermInfoIVARS *const ivars = TInfo_IVARS(self);
+    ivars->doc_freq      = 0;
+    ivars->post_filepos  = 0;
+    ivars->skip_filepos  = 0;
+    ivars->lex_filepos   = 0;
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/TermStepper.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/TermStepper.c b/core/Lucy/Index/TermStepper.c
index b78030e..466d7da 100644
--- a/core/Lucy/Index/TermStepper.c
+++ b/core/Lucy/Index/TermStepper.c
@@ -26,31 +26,35 @@
 TermStepper*
 TermStepper_init(TermStepper *self) {
     Stepper_init((Stepper*)self);
-    self->value = NULL;
+    TermStepperIVARS *const ivars = TermStepper_IVARS(self);
+    ivars->value = NULL;
     return self;
 }
 
 void
 TermStepper_destroy(TermStepper *self) {
-    DECREF(self->value);
+    TermStepperIVARS *const ivars = TermStepper_IVARS(self);
+    DECREF(ivars->value);
     SUPER_DESTROY(self, TERMSTEPPER);
 }
 
 void
 TermStepper_reset(TermStepper *self) {
-    DECREF(self->value);
-    self->value = NULL;
+    TermStepperIVARS *const ivars = TermStepper_IVARS(self);
+    DECREF(ivars->value);
+    ivars->value = NULL;
 }
 
 Obj*
 TermStepper_get_value(TermStepper *self) {
-    return self->value;
+    return TermStepper_IVARS(self)->value;
 }
 
 void
 TermStepper_set_value(TermStepper *self, Obj *value) {
-    DECREF(self->value);
-    self->value = value ? INCREF(value) : NULL;
+    TermStepperIVARS *const ivars = TermStepper_IVARS(self);
+    DECREF(ivars->value);
+    ivars->value = value ? INCREF(value) : NULL;
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/TermVector.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/TermVector.c b/core/Lucy/Index/TermVector.c
index 4c3216b..4b0ee04 100644
--- a/core/Lucy/Index/TermVector.c
+++ b/core/Lucy/Index/TermVector.c
@@ -33,18 +33,20 @@ TV_new(const CharBuf *field, const CharBuf *text, I32Array *positions,
 TermVector*
 TV_init(TermVector *self, const CharBuf *field, const CharBuf *text,
         I32Array *positions, I32Array *start_offsets, I32Array *end_offsets) {
+    TermVectorIVARS *const ivars = TV_IVARS(self);
+
     // Assign.
-    self->field          = CB_Clone(field);
-    self->text           = CB_Clone(text);
-    self->num_pos        = I32Arr_Get_Size(positions);
-    self->positions      = (I32Array*)INCREF(positions);
-    self->start_offsets  = (I32Array*)INCREF(start_offsets);
-    self->end_offsets    = (I32Array*)INCREF(end_offsets);
-
-    if (I32Arr_Get_Size(start_offsets) != self->num_pos
-        || I32Arr_Get_Size(end_offsets) != self->num_pos
+    ivars->field          = CB_Clone(field);
+    ivars->text           = CB_Clone(text);
+    ivars->num_pos        = I32Arr_Get_Size(positions);
+    ivars->positions      = (I32Array*)INCREF(positions);
+    ivars->start_offsets  = (I32Array*)INCREF(start_offsets);
+    ivars->end_offsets    = (I32Array*)INCREF(end_offsets);
+
+    if (I32Arr_Get_Size(start_offsets) != ivars->num_pos
+        || I32Arr_Get_Size(end_offsets) != ivars->num_pos
        ) {
-        THROW(ERR, "Unbalanced arrays: %u32 %u32 %u32", self->num_pos,
+        THROW(ERR, "Unbalanced arrays: %u32 %u32 %u32", ivars->num_pos,
               I32Arr_Get_Size(start_offsets), I32Arr_Get_Size(end_offsets));
     }
 
@@ -53,40 +55,42 @@ TV_init(TermVector *self, const CharBuf *field, const CharBuf *text,
 
 void
 TV_destroy(TermVector *self) {
-    DECREF(self->field);
-    DECREF(self->text);
-    DECREF(self->positions);
-    DECREF(self->start_offsets);
-    DECREF(self->end_offsets);
+    TermVectorIVARS *const ivars = TV_IVARS(self);
+    DECREF(ivars->field);
+    DECREF(ivars->text);
+    DECREF(ivars->positions);
+    DECREF(ivars->start_offsets);
+    DECREF(ivars->end_offsets);
     SUPER_DESTROY(self, TERMVECTOR);
 }
 
 I32Array*
 TV_get_positions(TermVector *self) {
-    return self->positions;
+    return TV_IVARS(self)->positions;
 }
 
 I32Array*
 TV_get_start_offsets(TermVector *self) {
-    return self->start_offsets;
+    return TV_IVARS(self)->start_offsets;
 }
 
 I32Array*
 TV_get_end_offsets(TermVector *self) {
-    return self->end_offsets;
+    return TV_IVARS(self)->end_offsets;
 }
 
 void
 TV_serialize(TermVector *self, OutStream *target) {
-    int32_t *posits = self->positions->ints;
-    int32_t *starts = self->start_offsets->ints;
-    int32_t *ends   = self->start_offsets->ints;
+    TermVectorIVARS *const ivars = TV_IVARS(self);
+    int32_t *posits = I32Arr_IVARS(ivars->positions)->ints;
+    int32_t *starts = I32Arr_IVARS(ivars->start_offsets)->ints;
+    int32_t *ends   = I32Arr_IVARS(ivars->start_offsets)->ints;
 
-    Freezer_serialize_charbuf(self->field, target);
-    Freezer_serialize_charbuf(self->text, target);
-    OutStream_Write_C32(target, self->num_pos);
+    Freezer_serialize_charbuf(ivars->field, target);
+    Freezer_serialize_charbuf(ivars->text, target);
+    OutStream_Write_C32(target, ivars->num_pos);
 
-    for (uint32_t i = 0; i < self->num_pos; i++) {
+    for (uint32_t i = 0; i < ivars->num_pos; i++) {
         OutStream_Write_C32(target, posits[i]);
         OutStream_Write_C32(target, starts[i]);
         OutStream_Write_C32(target, ends[i]);
@@ -125,21 +129,20 @@ TV_deserialize(TermVector *self, InStream *instream) {
 
 bool
 TV_equals(TermVector *self, Obj *other) {
-    TermVector *const twin = (TermVector*)other;
-    int32_t *const posits       = self->positions->ints;
-    int32_t *const starts       = self->start_offsets->ints;
-    int32_t *const ends         = self->start_offsets->ints;
-    int32_t *const other_posits = twin->positions->ints;
-    int32_t *const other_starts = twin->start_offsets->ints;
-    int32_t *const other_ends   = twin->start_offsets->ints;
-
-    if (twin == self) { return true; }
-
-    if (!CB_Equals(self->field, (Obj*)twin->field)) { return false; }
-    if (!CB_Equals(self->text, (Obj*)twin->text))   { return false; }
-    if (self->num_pos != twin->num_pos)             { return false; }
-
-    for (uint32_t i = 0; i < self->num_pos; i++) {
+    if ((TermVector*)other == self) { return true; }
+    TermVectorIVARS *const ivars = TV_IVARS(self);
+    TermVectorIVARS *const ovars = TV_IVARS((TermVector*)other);
+    if (!CB_Equals(ivars->field, (Obj*)ovars->field)) { return false; }
+    if (!CB_Equals(ivars->text, (Obj*)ovars->text))   { return false; }
+    if (ivars->num_pos != ovars->num_pos)             { return false; }
+
+    int32_t *const posits       = I32Arr_IVARS(ivars->positions)->ints;
+    int32_t *const starts       = I32Arr_IVARS(ivars->start_offsets)->ints;
+    int32_t *const ends         = I32Arr_IVARS(ivars->start_offsets)->ints;
+    int32_t *const other_posits = I32Arr_IVARS(ovars->positions)->ints;
+    int32_t *const other_starts = I32Arr_IVARS(ovars->start_offsets)->ints;
+    int32_t *const other_ends   = I32Arr_IVARS(ovars->start_offsets)->ints;
+    for (uint32_t i = 0; i < ivars->num_pos; i++) {
         if (posits[i] != other_posits[i]) { return false; }
         if (starts[i] != other_starts[i]) { return false; }
         if (ends[i]   != other_ends[i])   { return false; }

http://git-wip-us.apache.org/repos/asf/lucy/blob/965fdb2a/core/Lucy/Index/ZombieKeyedHash.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Index/ZombieKeyedHash.c b/core/Lucy/Index/ZombieKeyedHash.c
index a69a5a7..512e2e5 100644
--- a/core/Lucy/Index/ZombieKeyedHash.c
+++ b/core/Lucy/Index/ZombieKeyedHash.c
@@ -26,33 +26,36 @@ ZKHash_new(MemoryPool *memory_pool, uint8_t primitive_id) {
     ZombieKeyedHash *self
         = (ZombieKeyedHash*)VTable_Make_Obj(ZOMBIEKEYEDHASH);
     Hash_init((Hash*)self, 0);
-    self->mem_pool = (MemoryPool*)INCREF(memory_pool);
-    self->prim_id  = primitive_id;
+    ZombieKeyedHashIVARS *const ivars = ZKHash_IVARS(self);
+    ivars->mem_pool = (MemoryPool*)INCREF(memory_pool);
+    ivars->prim_id  = primitive_id;
     return self;
 }
 
 void
 ZKHash_destroy(ZombieKeyedHash *self) {
-    DECREF(self->mem_pool);
+    ZombieKeyedHashIVARS *const ivars = ZKHash_IVARS(self);
+    DECREF(ivars->mem_pool);
     SUPER_DESTROY(self, ZOMBIEKEYEDHASH);
 }
 
 Obj*
 ZKHash_make_key(ZombieKeyedHash *self, Obj *key, int32_t hash_sum) {
+    ZombieKeyedHashIVARS *const ivars = ZKHash_IVARS(self);
     UNUSED_VAR(hash_sum);
     Obj *retval = NULL;
-    switch (self->prim_id & FType_PRIMITIVE_ID_MASK) {
+    switch (ivars->prim_id & FType_PRIMITIVE_ID_MASK) {
         case FType_TEXT: {
                 CharBuf *source = (CharBuf*)key;
                 size_t size = ZCB_size() + CB_Get_Size(source) + 1;
-                void *allocation = MemPool_grab(self->mem_pool, size);
+                void *allocation = MemPool_grab(ivars->mem_pool, size);
                 retval = (Obj*)ZCB_newf(allocation, size, "%o", source);
             }
             break;
         case FType_INT32: {
                 size_t size = VTable_Get_Obj_Alloc_Size(INTEGER32);
                 Integer32 *copy
-                    = (Integer32*)MemPool_grab(self->mem_pool, size);
+                    = (Integer32*)MemPool_grab(ivars->mem_pool, size);
                 VTable_Init_Obj(INTEGER32, copy);
                 Int32_init(copy, 0);
                 Int32_Mimic(copy, key);
@@ -62,7 +65,7 @@ ZKHash_make_key(ZombieKeyedHash *self, Obj *key, int32_t hash_sum) {
         case FType_INT64: {
                 size_t size = VTable_Get_Obj_Alloc_Size(INTEGER64);
                 Integer64 *copy
-                    = (Integer64*)MemPool_Grab(self->mem_pool, size);
+                    = (Integer64*)MemPool_Grab(ivars->mem_pool, size);
                 VTable_Init_Obj(INTEGER64, copy);
                 Int64_init(copy, 0);
                 Int64_Mimic(copy, key);
@@ -71,7 +74,7 @@ ZKHash_make_key(ZombieKeyedHash *self, Obj *key, int32_t hash_sum) {
             break;
         case FType_FLOAT32: {
                 size_t size = VTable_Get_Obj_Alloc_Size(FLOAT32);
-                Float32 *copy = (Float32*)MemPool_Grab(self->mem_pool, size);
+                Float32 *copy = (Float32*)MemPool_Grab(ivars->mem_pool, size);
                 VTable_Init_Obj(FLOAT32, copy);
                 Float32_init(copy, 0);
                 Float32_Mimic(copy, key);
@@ -80,7 +83,7 @@ ZKHash_make_key(ZombieKeyedHash *self, Obj *key, int32_t hash_sum) {
             break;
         case FType_FLOAT64: {
                 size_t size = VTable_Get_Obj_Alloc_Size(FLOAT64);
-                Float64 *copy = (Float64*)MemPool_Grab(self->mem_pool, size);
+                Float64 *copy = (Float64*)MemPool_Grab(ivars->mem_pool, size);
                 VTable_Init_Obj(FLOAT64, copy);
                 Float64_init(copy, 0);
                 Float64_Mimic(copy, key);
@@ -88,7 +91,7 @@ ZKHash_make_key(ZombieKeyedHash *self, Obj *key, int32_t hash_sum) {
             }
             break;
         default:
-            THROW(ERR, "Unrecognized primitive id: %i8", self->prim_id);
+            THROW(ERR, "Unrecognized primitive id: %i8", ivars->prim_id);
     }
 
     /* FIXME This is a hack.  It will leak memory if host objects get cached,