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:48 UTC

[lucy-commits] [28/34] git commit: refs/heads/master - Migrate more Lucy search classes to IVARS.

Migrate more Lucy search classes to IVARS.


Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/7ba2ba64
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/7ba2ba64
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/7ba2ba64

Branch: refs/heads/master
Commit: 7ba2ba64f954ca0d63ff80b407dd4187e00fe8ea
Parents: 14e863f
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Sun Jun 30 21:59:23 2013 -0700
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Tue Jul 16 16:08:43 2013 -0700

----------------------------------------------------------------------
 core/Lucy/Search/Collector/SortCollector.c | 300 +++++++++++++-----------
 core/Lucy/Search/QueryParser/ParserElem.c  |  51 ++--
 core/Lucy/Search/QueryParser/QueryLexer.c  |  10 +-
 3 files changed, 193 insertions(+), 168 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy/blob/7ba2ba64/core/Lucy/Search/Collector/SortCollector.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Search/Collector/SortCollector.c b/core/Lucy/Search/Collector/SortCollector.c
index 9c4d182..7c877bf 100644
--- a/core/Lucy/Search/Collector/SortCollector.c
+++ b/core/Lucy/Search/Collector/SortCollector.c
@@ -63,7 +63,7 @@ S_derive_action(SortRule *rule, SortCache *sort_cache);
 
 // Decide whether a doc should be inserted into the HitQueue.
 static INLINE bool
-SI_competitive(SortCollector *self, int32_t doc_id);
+SI_competitive(SortCollectorIVARS *ivars, int32_t doc_id);
 
 SortCollector*
 SortColl_new(Schema *schema, SortSpec *sort_spec, uint32_t wanted) {
@@ -98,33 +98,34 @@ SortColl_init(SortCollector *self, Schema *schema, SortSpec *sort_spec,
 
     // Init.
     Coll_init((Collector*)self);
-    self->total_hits    = 0;
-    self->bubble_doc    = INT32_MAX;
-    self->bubble_score  = F32_NEGINF;
-    self->seg_doc_max   = 0;
+    SortCollectorIVARS *const ivars = SortColl_IVARS(self);
+    ivars->total_hits    = 0;
+    ivars->bubble_doc    = INT32_MAX;
+    ivars->bubble_score  = F32_NEGINF;
+    ivars->seg_doc_max   = 0;
 
     // Assign.
-    self->wanted        = wanted;
+    ivars->wanted        = wanted;
 
     // Derive.
-    self->hit_q         = HitQ_new(schema, sort_spec, wanted);
-    self->rules         = rules; // absorb refcount.
-    self->num_rules     = num_rules;
-    self->sort_caches   = (SortCache**)CALLOCATE(num_rules, sizeof(SortCache*));
-    self->ord_arrays    = (void**)CALLOCATE(num_rules, sizeof(void*));
-    self->actions       = (uint8_t*)CALLOCATE(num_rules, sizeof(uint8_t));
+    ivars->hit_q         = HitQ_new(schema, sort_spec, wanted);
+    ivars->rules         = rules; // absorb refcount.
+    ivars->num_rules     = num_rules;
+    ivars->sort_caches   = (SortCache**)CALLOCATE(num_rules, sizeof(SortCache*));
+    ivars->ord_arrays    = (void**)CALLOCATE(num_rules, sizeof(void*));
+    ivars->actions       = (uint8_t*)CALLOCATE(num_rules, sizeof(uint8_t));
 
     // Build up an array of "actions" which we will execute during each call
     // to Collect(). Determine whether we need to track scores and field
     // values.
-    self->need_score  = false;
-    self->need_values = false;
+    ivars->need_score  = false;
+    ivars->need_values = false;
     for (uint32_t i = 0; i < num_rules; i++) {
         SortRule *rule   = (SortRule*)VA_Fetch(rules, i);
         int32_t rule_type  = SortRule_Get_Type(rule);
-        self->actions[i] = S_derive_action(rule, NULL);
+        ivars->actions[i] = S_derive_action(rule, NULL);
         if (rule_type == SortRule_SCORE) {
-            self->need_score = true;
+            ivars->need_score = true;
         }
         else if (rule_type == SortRule_FIELD) {
             CharBuf *field = SortRule_Get_Field(rule);
@@ -132,30 +133,30 @@ SortColl_init(SortCollector *self, Schema *schema, SortSpec *sort_spec,
             if (!type || !FType_Sortable(type)) {
                 THROW(ERR, "'%o' isn't a sortable field", field);
             }
-            self->need_values = true;
+            ivars->need_values = true;
         }
     }
 
     // Perform an optimization.  So long as we always collect docs in
     // ascending order, Collect() will favor lower doc numbers -- so we may
     // not need to execute a final COMPARE_BY_DOC_ID action.
-    self->num_actions = num_rules;
-    if (self->actions[num_rules - 1] == COMPARE_BY_DOC_ID) {
-        self->num_actions--;
+    ivars->num_actions = num_rules;
+    if (ivars->actions[num_rules - 1] == COMPARE_BY_DOC_ID) {
+        ivars->num_actions--;
     }
 
     // Override our derived actions with an action which will be excecuted
     // autmatically until the queue fills up.
-    self->auto_actions    = (uint8_t*)MALLOCATE(1);
-    self->auto_actions[0] = wanted ? AUTO_ACCEPT : AUTO_REJECT;
-    self->derived_actions = self->actions;
-    self->actions         = self->auto_actions;
+    ivars->auto_actions    = (uint8_t*)MALLOCATE(1);
+    ivars->auto_actions[0] = wanted ? AUTO_ACCEPT : AUTO_REJECT;
+    ivars->derived_actions = ivars->actions;
+    ivars->actions         = ivars->auto_actions;
 
 
     // Prepare a MatchDoc-in-waiting.
-    VArray *values = self->need_values ? VA_new(num_rules) : NULL;
-    float   score  = self->need_score  ? F32_NEGINF : F32_NAN;
-    self->bumped = MatchDoc_new(INT32_MAX, score, values);
+    VArray *values = ivars->need_values ? VA_new(num_rules) : NULL;
+    float   score  = ivars->need_score  ? F32_NEGINF : F32_NAN;
+    ivars->bumped = MatchDoc_new(INT32_MAX, score, values);
     DECREF(values);
 
     return self;
@@ -163,13 +164,14 @@ SortColl_init(SortCollector *self, Schema *schema, SortSpec *sort_spec,
 
 void
 SortColl_destroy(SortCollector *self) {
-    DECREF(self->hit_q);
-    DECREF(self->rules);
-    DECREF(self->bumped);
-    FREEMEM(self->sort_caches);
-    FREEMEM(self->ord_arrays);
-    FREEMEM(self->auto_actions);
-    FREEMEM(self->derived_actions);
+    SortCollectorIVARS *const ivars = SortColl_IVARS(self);
+    DECREF(ivars->hit_q);
+    DECREF(ivars->rules);
+    DECREF(ivars->bumped);
+    FREEMEM(ivars->sort_caches);
+    FREEMEM(ivars->ord_arrays);
+    FREEMEM(ivars->auto_actions);
+    FREEMEM(ivars->derived_actions);
     SUPER_DESTROY(self, SORTCOLLECTOR);
 }
 
@@ -221,69 +223,75 @@ S_derive_action(SortRule *rule, SortCache *cache) {
 
 void
 SortColl_set_reader(SortCollector *self, SegReader *reader) {
+    SortCollectorIVARS *const ivars = SortColl_IVARS(self);
     SortReader *sort_reader
         = (SortReader*)SegReader_Fetch(reader, VTable_Get_Name(SORTREADER));
 
     // Reset threshold variables and trigger auto-action behavior.
-    self->bumped->doc_id = INT32_MAX;
-    self->bubble_doc     = INT32_MAX;
-    self->bumped->score  = self->need_score ? F32_NEGINF : F32_NAN;
-    self->bubble_score   = self->need_score ? F32_NEGINF : F32_NAN;
-    self->actions        = self->auto_actions;
+    MatchDocIVARS *const bumped_ivars = MatchDoc_IVARS(ivars->bumped);
+    bumped_ivars->doc_id = INT32_MAX;
+    ivars->bubble_doc    = INT32_MAX;
+    bumped_ivars->score  = ivars->need_score ? F32_NEGINF : F32_NAN;
+    ivars->bubble_score  = ivars->need_score ? F32_NEGINF : F32_NAN;
+    ivars->actions       = ivars->auto_actions;
 
     // Obtain sort caches. Derive actions array for this segment.
-    if (self->need_values && sort_reader) {
-        for (uint32_t i = 0, max = self->num_rules; i < max; i++) {
-            SortRule  *rule  = (SortRule*)VA_Fetch(self->rules, i);
+    if (ivars->need_values && sort_reader) {
+        for (uint32_t i = 0, max = ivars->num_rules; i < max; i++) {
+            SortRule  *rule  = (SortRule*)VA_Fetch(ivars->rules, i);
             CharBuf   *field = SortRule_Get_Field(rule);
             SortCache *cache = field
                                ? SortReader_Fetch_Sort_Cache(sort_reader, field)
                                : NULL;
-            self->sort_caches[i] = cache;
-            self->derived_actions[i] = S_derive_action(rule, cache);
-            if (cache) { self->ord_arrays[i] = SortCache_Get_Ords(cache); }
-            else       { self->ord_arrays[i] = NULL; }
+            ivars->sort_caches[i] = cache;
+            ivars->derived_actions[i] = S_derive_action(rule, cache);
+            if (cache) { ivars->ord_arrays[i] = SortCache_Get_Ords(cache); }
+            else       { ivars->ord_arrays[i] = NULL; }
         }
     }
-    self->seg_doc_max = reader ? SegReader_Doc_Max(reader) : 0;
+    ivars->seg_doc_max = reader ? SegReader_Doc_Max(reader) : 0;
     Coll_set_reader((Collector*)self, reader);
 }
 
 VArray*
 SortColl_pop_match_docs(SortCollector *self) {
-    return HitQ_Pop_All(self->hit_q);
+    SortCollectorIVARS *const ivars = SortColl_IVARS(self);
+    return HitQ_Pop_All(ivars->hit_q);
 }
 
 uint32_t
 SortColl_get_total_hits(SortCollector *self) {
-    return self->total_hits;
+    return SortColl_IVARS(self)->total_hits;
 }
 
 bool
 SortColl_need_score(SortCollector *self) {
-    return self->need_score;
+    return SortColl_IVARS(self)->need_score;
 }
 
 void
 SortColl_collect(SortCollector *self, int32_t doc_id) {
+    SortCollectorIVARS *const ivars = SortColl_IVARS(self);
+
     // Add to the total number of hits.
-    self->total_hits++;
+    ivars->total_hits++;
 
     // Collect this hit if it's competitive.
-    if (SI_competitive(self, doc_id)) {
-        MatchDoc *const match_doc = self->bumped;
-        match_doc->doc_id = doc_id + self->base;
+    if (SI_competitive(ivars, doc_id)) {
+        MatchDoc *const match_doc = ivars->bumped;
+        MatchDocIVARS *const match_doc_ivars = MatchDoc_IVARS(match_doc);
+        match_doc_ivars->doc_id = doc_id + ivars->base;
 
-        if (self->need_score && match_doc->score == F32_NEGINF) {
-            match_doc->score = Matcher_Score(self->matcher);
+        if (ivars->need_score && match_doc_ivars->score == F32_NEGINF) {
+            match_doc_ivars->score = Matcher_Score(ivars->matcher);
         }
 
         // Fetch values so that cross-segment sorting can work.
-        if (self->need_values) {
-            VArray *values = match_doc->values;
+        if (ivars->need_values) {
+            VArray *values = match_doc_ivars->values;
 
-            for (uint32_t i = 0, max = self->num_rules; i < max; i++) {
-                SortCache *cache   = self->sort_caches[i];
+            for (uint32_t i = 0, max = ivars->num_rules; i < max; i++) {
+                SortCache *cache   = ivars->sort_caches[i];
                 Obj       *old_val = (Obj*)VA_Delete(values, i);
                 if (cache) {
                     int32_t ord = SortCache_Ordinal(cache, doc_id);
@@ -298,29 +306,31 @@ SortColl_collect(SortCollector *self, int32_t doc_id) {
         }
 
         // Insert the new MatchDoc.
-        self->bumped = (MatchDoc*)HitQ_Jostle(self->hit_q, (Obj*)match_doc);
+        ivars->bumped = (MatchDoc*)HitQ_Jostle(ivars->hit_q, (Obj*)match_doc);
 
-        if (self->bumped) {
-            if (self->bumped == match_doc) {
+        if (ivars->bumped) {
+            if (ivars->bumped == match_doc) {
                 /* The queue is full, and we have established a threshold for
                  * this segment as to what sort of document is definitely not
                  * acceptable.  Turn off AUTO_ACCEPT and start actually
                  * testing whether hits are competitive. */
-                self->bubble_score  = match_doc->score;
-                self->bubble_doc    = doc_id;
-                self->actions       = self->derived_actions;
+                ivars->bubble_score  = match_doc_ivars->score;
+                ivars->bubble_doc    = doc_id;
+                ivars->actions       = ivars->derived_actions;
             }
 
             // Recycle.
-            self->bumped->score = self->need_score ? F32_NEGINF : F32_NAN;
+            MatchDoc_IVARS(ivars->bumped)->score = ivars->need_score
+                                                   ? F32_NEGINF
+                                                   : F32_NAN;
         }
         else {
             // The queue isn't full yet, so create a fresh MatchDoc.
-            VArray *values = self->need_values
-                             ? VA_new(self->num_rules)
+            VArray *values = ivars->need_values
+                             ? VA_new(ivars->num_rules)
                              : NULL;
-            float fake_score = self->need_score ? F32_NEGINF : F32_NAN;
-            self->bumped = MatchDoc_new(INT32_MAX, fake_score, values);
+            float fake_score = ivars->need_score ? F32_NEGINF : F32_NAN;
+            ivars->bumped = MatchDoc_new(INT32_MAX, fake_score, values);
             DECREF(values);
         }
 
@@ -328,36 +338,41 @@ SortColl_collect(SortCollector *self, int32_t doc_id) {
 }
 
 static INLINE int32_t
-SI_compare_by_ord1(SortCollector *self, uint32_t tick, int32_t a, int32_t b) {
-    void *const ords = self->ord_arrays[tick];
+SI_compare_by_ord1(SortCollectorIVARS *ivars, uint32_t tick,
+                   int32_t a, int32_t b) {
+    void *const ords = ivars->ord_arrays[tick];
     int32_t a_ord = NumUtil_u1get(ords, a);
     int32_t b_ord = NumUtil_u1get(ords, b);
     return a_ord - b_ord;
 }
 static INLINE int32_t
-SI_compare_by_ord2(SortCollector *self, uint32_t tick, int32_t a, int32_t b) {
-    void *const ords = self->ord_arrays[tick];
+SI_compare_by_ord2(SortCollectorIVARS *ivars, uint32_t tick,
+                   int32_t a, int32_t b) {
+    void *const ords = ivars->ord_arrays[tick];
     int32_t a_ord = NumUtil_u2get(ords, a);
     int32_t b_ord = NumUtil_u2get(ords, b);
     return a_ord - b_ord;
 }
 static INLINE int32_t
-SI_compare_by_ord4(SortCollector *self, uint32_t tick, int32_t a, int32_t b) {
-    void *const ords = self->ord_arrays[tick];
+SI_compare_by_ord4(SortCollectorIVARS *ivars, uint32_t tick,
+                   int32_t a, int32_t b) {
+    void *const ords = ivars->ord_arrays[tick];
     int32_t a_ord = NumUtil_u4get(ords, a);
     int32_t b_ord = NumUtil_u4get(ords, b);
     return a_ord - b_ord;
 }
 static INLINE int32_t
-SI_compare_by_ord8(SortCollector *self, uint32_t tick, int32_t a, int32_t b) {
-    uint8_t *ords = (uint8_t*)self->ord_arrays[tick];
+SI_compare_by_ord8(SortCollectorIVARS *ivars, uint32_t tick,
+                   int32_t a, int32_t b) {
+    uint8_t *ords = (uint8_t*)ivars->ord_arrays[tick];
     int32_t a_ord = ords[a];
     int32_t b_ord = ords[b];
     return a_ord - b_ord;
 }
 static INLINE int32_t
-SI_compare_by_ord16(SortCollector *self, uint32_t tick, int32_t a, int32_t b) {
-    uint8_t *ord_bytes = (uint8_t*)self->ord_arrays[tick];
+SI_compare_by_ord16(SortCollectorIVARS *ivars, uint32_t tick,
+                    int32_t a, int32_t b) {
+    uint8_t *ord_bytes = (uint8_t*)ivars->ord_arrays[tick];
     uint8_t *address_a = ord_bytes + a * sizeof(uint16_t);
     uint8_t *address_b = ord_bytes + b * sizeof(uint16_t);
     int32_t  ord_a = NumUtil_decode_bigend_u16(address_a);
@@ -365,8 +380,9 @@ SI_compare_by_ord16(SortCollector *self, uint32_t tick, int32_t a, int32_t b) {
     return ord_a - ord_b;
 }
 static INLINE int32_t
-SI_compare_by_ord32(SortCollector *self, uint32_t tick, int32_t a, int32_t b) {
-    uint8_t *ord_bytes = (uint8_t*)self->ord_arrays[tick];
+SI_compare_by_ord32(SortCollectorIVARS *ivars, uint32_t tick,
+                    int32_t a, int32_t b) {
+    uint8_t *ord_bytes = (uint8_t*)ivars->ord_arrays[tick];
     uint8_t *address_a = ord_bytes + a * sizeof(uint32_t);
     uint8_t *address_b = ord_bytes + b * sizeof(uint32_t);
     int32_t  ord_a = NumUtil_decode_bigend_u32(address_a);
@@ -374,42 +390,42 @@ SI_compare_by_ord32(SortCollector *self, uint32_t tick, int32_t a, int32_t b) {
     return ord_a - ord_b;
 }
 static INLINE int32_t
-SI_compare_by_native_ord16(SortCollector *self, uint32_t tick,
+SI_compare_by_native_ord16(SortCollectorIVARS *ivars, uint32_t tick,
                            int32_t a, int32_t b) {
-    uint16_t *ords = (uint16_t*)self->ord_arrays[tick];
+    uint16_t *ords = (uint16_t*)ivars->ord_arrays[tick];
     int32_t a_ord = ords[a];
     int32_t b_ord = ords[b];
     return a_ord - b_ord;
 }
 static INLINE int32_t
-SI_compare_by_native_ord32(SortCollector *self, uint32_t tick,
+SI_compare_by_native_ord32(SortCollectorIVARS *ivars, uint32_t tick,
                            int32_t a, int32_t b) {
-    int32_t *ords = (int32_t*)self->ord_arrays[tick];
+    int32_t *ords = (int32_t*)ivars->ord_arrays[tick];
     return ords[a] - ords[b];
 }
 
 // Bounds checking for doc id against the segment doc_max.  We assume that any
 // sort cache ord arrays can accomodate lookups up to this number.
 static INLINE int32_t
-SI_validate_doc_id(SortCollector *self, int32_t doc_id) {
+SI_validate_doc_id(SortCollectorIVARS *ivars, int32_t doc_id) {
     // Check as uint32_t since we're using these doc ids as array indexes.
-    if ((uint32_t)doc_id > (uint32_t)self->seg_doc_max) {
+    if ((uint32_t)doc_id > (uint32_t)ivars->seg_doc_max) {
         THROW(ERR, "Doc ID %i32 greater than doc max %i32", doc_id,
-              self->seg_doc_max);
+              ivars->seg_doc_max);
     }
     return doc_id;
 }
 
 static INLINE bool
-SI_competitive(SortCollector *self, int32_t doc_id) {
+SI_competitive(SortCollectorIVARS *ivars, int32_t doc_id) {
     /* Ordinarily, we would cache local copies of more member variables in
      * const automatic variables in order to improve code clarity and provide
      * more hints to the compiler about what variables are actually invariant
      * for the duration of this routine:
      *
-     *     uint8_t *const actions    = self->actions;
-     *     const uint32_t num_rules  = self->num_rules;
-     *     const int32_t bubble_doc = self->bubble_doc;
+     *     uint8_t *const actions    = ivars->actions;
+     *     const uint32_t num_rules  = ivars->num_rules;
+     *     const int32_t bubble_doc = ivars->bubble_doc;
      *
      * However, our major goal is to return as quickly as possible, and the
      * common case is that we'll have our answer before the first loop iter
@@ -420,7 +436,7 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
      * loop instead of a "for" loop, and the switch statement optimized for
      * compilation to a jump table.
      */
-    uint8_t *const actions = self->actions;
+    uint8_t *const actions = ivars->actions;
     uint32_t i = 0;
 
     // Iterate through our array of actions, returning as quickly as possible.
@@ -433,46 +449,46 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case AUTO_TIE:
                 break;
             case COMPARE_BY_SCORE: {
-                    float score = Matcher_Score(self->matcher);
-                    if (*(int32_t*)&score == *(int32_t*)&self->bubble_score) {
+                    float score = Matcher_Score(ivars->matcher);
+                    if (*(int32_t*)&score == *(int32_t*)&ivars->bubble_score) {
                         break;
                     }
-                    if (score > self->bubble_score) {
-                        self->bumped->score = score;
+                    if (score > ivars->bubble_score) {
+                        MatchDoc_IVARS(ivars->bumped)->score = score;
                         return true;
                     }
-                    else if (score < self->bubble_score) {
+                    else if (score < ivars->bubble_score) {
                         return false;
                     }
                 }
                 break;
             case COMPARE_BY_SCORE_REV: {
-                    float score = Matcher_Score(self->matcher);
-                    if (*(int32_t*)&score == *(int32_t*)&self->bubble_score) {
+                    float score = Matcher_Score(ivars->matcher);
+                    if (*(int32_t*)&score == *(int32_t*)&ivars->bubble_score) {
                         break;
                     }
-                    if (score < self->bubble_score) {
-                        self->bumped->score = score;
+                    if (score < ivars->bubble_score) {
+                        MatchDoc_IVARS(ivars->bumped)->score = score;
                         return true;
                     }
-                    else if (score > self->bubble_score) {
+                    else if (score > ivars->bubble_score) {
                         return false;
                     }
                 }
                 break;
             case COMPARE_BY_DOC_ID:
-                if (doc_id > self->bubble_doc)      { return false; }
-                else if (doc_id < self->bubble_doc) { return true; }
+                if (doc_id > ivars->bubble_doc)      { return false; }
+                else if (doc_id < ivars->bubble_doc) { return true; }
                 break;
             case COMPARE_BY_DOC_ID_REV:
-                if (doc_id > self->bubble_doc)      { return true; }
-                else if (doc_id < self->bubble_doc) { return false; }
+                if (doc_id > ivars->bubble_doc)      { return true; }
+                else if (doc_id < ivars->bubble_doc) { return false; }
                 break;
             case COMPARE_BY_ORD1: {
                     int32_t comparison
                         = SI_compare_by_ord1(
-                              self, i, SI_validate_doc_id(self, doc_id),
-                              self->bubble_doc);
+                              ivars, i, SI_validate_doc_id(ivars, doc_id),
+                              ivars->bubble_doc);
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -480,8 +496,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD1_REV: {
                     int32_t comparison
                         = SI_compare_by_ord1(
-                              self, i, self->bubble_doc,
-                              SI_validate_doc_id(self, doc_id));
+                              ivars, i, ivars->bubble_doc,
+                              SI_validate_doc_id(ivars, doc_id));
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -489,8 +505,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD2: {
                     int32_t comparison
                         = SI_compare_by_ord2(
-                              self, i, SI_validate_doc_id(self, doc_id),
-                              self->bubble_doc);
+                              ivars, i, SI_validate_doc_id(ivars, doc_id),
+                              ivars->bubble_doc);
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -498,8 +514,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD2_REV: {
                     int32_t comparison
                         = SI_compare_by_ord2(
-                              self, i, self->bubble_doc,
-                              SI_validate_doc_id(self, doc_id));
+                              ivars, i, ivars->bubble_doc,
+                              SI_validate_doc_id(ivars, doc_id));
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -507,8 +523,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD4: {
                     int32_t comparison
                         = SI_compare_by_ord4(
-                              self, i, SI_validate_doc_id(self, doc_id),
-                              self->bubble_doc);
+                              ivars, i, SI_validate_doc_id(ivars, doc_id),
+                              ivars->bubble_doc);
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -516,8 +532,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD4_REV: {
                     int32_t comparison
                         = SI_compare_by_ord4(
-                              self, i, self->bubble_doc,
-                              SI_validate_doc_id(self, doc_id));
+                              ivars, i, ivars->bubble_doc,
+                              SI_validate_doc_id(ivars, doc_id));
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -525,8 +541,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD8: {
                     int32_t comparison
                         = SI_compare_by_ord8(
-                              self, i, SI_validate_doc_id(self, doc_id),
-                              self->bubble_doc);
+                              ivars, i, SI_validate_doc_id(ivars, doc_id),
+                              ivars->bubble_doc);
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -534,8 +550,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD8_REV: {
                     int32_t comparison
                         = SI_compare_by_ord8(
-                              self, i, self->bubble_doc,
-                              SI_validate_doc_id(self, doc_id));
+                              ivars, i, ivars->bubble_doc,
+                              SI_validate_doc_id(ivars, doc_id));
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -543,8 +559,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD16: {
                     int32_t comparison
                         = SI_compare_by_ord16(
-                              self, i, SI_validate_doc_id(self, doc_id),
-                              self->bubble_doc);
+                              ivars, i, SI_validate_doc_id(ivars, doc_id),
+                              ivars->bubble_doc);
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -552,8 +568,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD16_REV: {
                     int32_t comparison
                         = SI_compare_by_ord16(
-                              self, i, self->bubble_doc,
-                              SI_validate_doc_id(self, doc_id));
+                              ivars, i, ivars->bubble_doc,
+                              SI_validate_doc_id(ivars, doc_id));
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -561,8 +577,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD32: {
                     int32_t comparison
                         = SI_compare_by_ord32(
-                              self, i, SI_validate_doc_id(self, doc_id),
-                              self->bubble_doc);
+                              ivars, i, SI_validate_doc_id(ivars, doc_id),
+                              ivars->bubble_doc);
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -570,8 +586,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_ORD32_REV: {
                     int32_t comparison
                         = SI_compare_by_ord32(
-                              self, i, self->bubble_doc,
-                              SI_validate_doc_id(self, doc_id));
+                              ivars, i, ivars->bubble_doc,
+                              SI_validate_doc_id(ivars, doc_id));
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -579,8 +595,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_NATIVE_ORD16: {
                     int32_t comparison
                         = SI_compare_by_native_ord16(
-                              self, i, SI_validate_doc_id(self, doc_id),
-                              self->bubble_doc);
+                              ivars, i, SI_validate_doc_id(ivars, doc_id),
+                              ivars->bubble_doc);
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -588,8 +604,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_NATIVE_ORD16_REV: {
                     int32_t comparison
                         = SI_compare_by_native_ord16(
-                              self, i, self->bubble_doc,
-                              SI_validate_doc_id(self, doc_id));
+                              ivars, i, ivars->bubble_doc,
+                              SI_validate_doc_id(ivars, doc_id));
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -597,8 +613,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_NATIVE_ORD32: {
                     int32_t comparison
                         = SI_compare_by_native_ord32(
-                              self, i, SI_validate_doc_id(self, doc_id),
-                              self->bubble_doc);
+                              ivars, i, SI_validate_doc_id(ivars, doc_id),
+                              ivars->bubble_doc);
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -606,8 +622,8 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             case COMPARE_BY_NATIVE_ORD32_REV: {
                     int32_t comparison
                         = SI_compare_by_native_ord32(
-                              self, i, self->bubble_doc,
-                              SI_validate_doc_id(self, doc_id));
+                              ivars, i, ivars->bubble_doc,
+                              SI_validate_doc_id(ivars, doc_id));
                     if (comparison < 0)      { return true; }
                     else if (comparison > 0) { return false; }
                 }
@@ -615,7 +631,7 @@ SI_competitive(SortCollector *self, int32_t doc_id) {
             default:
                 THROW(ERR, "UNEXPECTED action %u8", actions[i]);
         }
-    } while (++i < self->num_actions);
+    } while (++i < ivars->num_actions);
 
     // If we've made it this far and we're still tied, reject the doc so that
     // we prefer items already in the queue.  This has the effect of

http://git-wip-us.apache.org/repos/asf/lucy/blob/7ba2ba64/core/Lucy/Search/QueryParser/ParserElem.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Search/QueryParser/ParserElem.c b/core/Lucy/Search/QueryParser/ParserElem.c
index 2bedc2d..a0c4e8c 100644
--- a/core/Lucy/Search/QueryParser/ParserElem.c
+++ b/core/Lucy/Search/QueryParser/ParserElem.c
@@ -27,93 +27,100 @@ ParserElem_new(uint32_t type, Obj *value) {
 
 ParserElem*
 ParserElem_init(ParserElem *self, uint32_t type, Obj *value) {
-    self->type  = type;
-    self->value = value;
-    self->occur = LUCY_QPARSER_SHOULD;
+    ParserElemIVARS *const ivars = ParserElem_IVARS(self);
+    ivars->type  = type;
+    ivars->value = value;
+    ivars->occur = LUCY_QPARSER_SHOULD;
     return self;
 }
 
 void
 ParserElem_destroy(ParserElem *self) {
-    DECREF(self->value);
+    ParserElemIVARS *const ivars = ParserElem_IVARS(self);
+    DECREF(ivars->value);
     SUPER_DESTROY(self, PARSERELEM);
 }
 
 void
 ParserElem_set_value(ParserElem *self, Obj *value) {
+    ParserElemIVARS *const ivars = ParserElem_IVARS(self);
     INCREF(value);
-    DECREF(self->value);
-    self->value = value;
+    DECREF(ivars->value);
+    ivars->value = value;
 }
 
 Obj*
 ParserElem_as(ParserElem *self, VTable *metaclass) {
-    if (self->value && Obj_Is_A(self->value, metaclass)) {
-        return self->value;
+    ParserElemIVARS *const ivars = ParserElem_IVARS(self);
+    if (ivars->value && Obj_Is_A(ivars->value, metaclass)) {
+        return ivars->value;
     }
     return NULL;
 }
 
 uint32_t
 ParserElem_get_type(ParserElem *self) {
-    return self->type;
+    return ParserElem_IVARS(self)->type;
 }
 
 void
 ParserElem_require(ParserElem *self) {
-    switch (self->occur) {
+    ParserElemIVARS *const ivars = ParserElem_IVARS(self);
+    switch (ivars->occur) {
         case LUCY_QPARSER_SHOULD:
-            self->occur = LUCY_QPARSER_MUST;
+            ivars->occur = LUCY_QPARSER_MUST;
             break;
         case LUCY_QPARSER_MUST_NOT:
         case LUCY_QPARSER_MUST:
             break;
         default:
-            THROW(ERR, "Internal error in value of occur: %u32", self->occur);
+            THROW(ERR, "Internal error in value of occur: %u32", ivars->occur);
     }
 }
 
 void
 ParserElem_unrequire(ParserElem *self) {
-    switch (self->occur) {
+    ParserElemIVARS *const ivars = ParserElem_IVARS(self);
+    switch (ivars->occur) {
         case LUCY_QPARSER_MUST:
-            self->occur = LUCY_QPARSER_SHOULD;
+            ivars->occur = LUCY_QPARSER_SHOULD;
             break;
         case LUCY_QPARSER_MUST_NOT:
         case LUCY_QPARSER_SHOULD:
             break;
         default:
-            THROW(ERR, "Internal error in value of occur: %u32", self->occur);
+            THROW(ERR, "Internal error in value of occur: %u32", ivars->occur);
     }
 }
 
 void
 ParserElem_negate(ParserElem *self) {
-    switch (self->occur) {
+    ParserElemIVARS *const ivars = ParserElem_IVARS(self);
+    switch (ivars->occur) {
         case LUCY_QPARSER_SHOULD:
         case LUCY_QPARSER_MUST:
-            self->occur = LUCY_QPARSER_MUST_NOT;
+            ivars->occur = LUCY_QPARSER_MUST_NOT;
             break;
         case LUCY_QPARSER_MUST_NOT:
-            self->occur = LUCY_QPARSER_MUST; // Apply double negative.
+            ivars->occur = LUCY_QPARSER_MUST; // Apply double negative.
             break;
         default:
-            THROW(ERR, "Internal error in value of occur: %u32", self->occur);
+            THROW(ERR, "Internal error in value of occur: %u32", ivars->occur);
     }
 }
 
 bool
 ParserElem_optional(ParserElem *self) {
-    return self->occur == LUCY_QPARSER_SHOULD;
+    return ParserElem_IVARS(self)->occur == LUCY_QPARSER_SHOULD;
 }
 
 bool
 ParserElem_required(ParserElem *self) {
-    return self->occur == LUCY_QPARSER_MUST;
+    return ParserElem_IVARS(self)->occur == LUCY_QPARSER_MUST;
 }
 
 bool
 ParserElem_negated(ParserElem *self) {
-    return self->occur == LUCY_QPARSER_MUST_NOT;
+    return ParserElem_IVARS(self)->occur == LUCY_QPARSER_MUST_NOT;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy/blob/7ba2ba64/core/Lucy/Search/QueryParser/QueryLexer.c
----------------------------------------------------------------------
diff --git a/core/Lucy/Search/QueryParser/QueryLexer.c b/core/Lucy/Search/QueryParser/QueryLexer.c
index 851380c..847a69f 100644
--- a/core/Lucy/Search/QueryParser/QueryLexer.c
+++ b/core/Lucy/Search/QueryParser/QueryLexer.c
@@ -55,22 +55,24 @@ QueryLexer_new() {
 
 QueryLexer*
 QueryLexer_init(QueryLexer *self) {
-    self->heed_colons = false;
+    QueryLexerIVARS *const ivars = QueryLexer_IVARS(self);
+    ivars->heed_colons = false;
     return self;
 }
 
 bool
 QueryLexer_heed_colons(QueryLexer *self) {
-    return self->heed_colons;
+    return QueryLexer_IVARS(self)->heed_colons;
 }
 
 void
 QueryLexer_set_heed_colons(QueryLexer *self, bool heed_colons) {
-    self->heed_colons = heed_colons;
+    QueryLexer_IVARS(self)->heed_colons = heed_colons;
 }
 
 VArray*
 QueryLexer_tokenize(QueryLexer *self, const CharBuf *query_string) {
+    QueryLexerIVARS *const ivars = QueryLexer_IVARS(self);
     CharBuf *copy = query_string
                     ? CB_Clone(query_string)
                     : CB_new_from_trusted_utf8("", 0);
@@ -86,7 +88,7 @@ QueryLexer_tokenize(QueryLexer *self, const CharBuf *query_string) {
             continue;
         }
 
-        if (self->heed_colons) {
+        if (ivars->heed_colons) {
             ParserElem *elem = S_consume_field(qstring);
             if (elem) {
                 VA_Push(elems, (Obj*)elem);