altos/lisp: Eliminate compiler warning about array bounds at -O3
[fw/altos] / src / lisp / ao_lisp_mem.c
index b681dbd547f1bd6d4e7f0b0fa873325d0ca075cc..12a5ba5502a32e158f284c8864de7028ef5d18cf 100644 (file)
@@ -252,23 +252,6 @@ static inline uint16_t pool_offset(void *addr) {
        return ((uint8_t *) addr) - ao_lisp_pool;
 }
 
-/*
- * Convert back and forth between 'poly's used
- * as short addresses in the pool and addresses.
- * These are used in the chunk code.
- */
-static inline ao_poly pool_poly(void *addr) {
-#if DBG_MEM
-       if (!AO_LISP_IS_POOL(addr))
-               ao_lisp_abort();
-#endif
-       return ((uint8_t *) addr) - AO_LISP_POOL_BASE;
-}
-
-static inline void *pool_ref(ao_poly p) {
-       return AO_LISP_POOL_BASE + p;
-}
-
 static inline void mark(uint8_t *tag, int offset) {
        int     byte = offset >> 5;
        int     bit = (offset >> 2) & 7;
@@ -314,36 +297,55 @@ static int chunk_busy;
 static void
 note_chunk(uint16_t addr, uint16_t size)
 {
-       int i;
+       int l, r;
 
-       if (addr < chunk_low || chunk_high < addr)
+       if (addr < chunk_low || chunk_high <= addr)
                return;
 
-       for (i = 0; i < chunk_busy; i++) {
-               if (ao_lisp_chunk[i].size && ao_lisp_chunk[i].old_addr == addr) {
-#if DBG_MEM
-                       if (ao_lisp_chunk[i].size != size)
-                               ao_lisp_abort();
-#endif
-                       return;
-               }
-               if (ao_lisp_chunk[i].old_addr > addr) {
-                       int end = min(AO_LISP_NCHUNK, chunk_busy + 1);
-                       memmove(&ao_lisp_chunk[i+1],
-                               &ao_lisp_chunk[i],
-                               (end - (i+1)) * sizeof (struct ao_lisp_chunk));
-                       break;
-               }
-       }
-       if (i < AO_LISP_NCHUNK) {
-               ao_lisp_chunk[i].old_addr = addr;
-               ao_lisp_chunk[i].size = size;
-               if (chunk_busy < AO_LISP_NCHUNK)
-                       chunk_busy++;
+       /* Binary search for the location */
+       l = 0;
+       r = chunk_busy - 1;
+       while (l <= r) {
+               int m = (l + r) >> 1;
+               if (ao_lisp_chunk[m].old_addr < addr)
+                       l = m + 1;
                else
-                       chunk_high = ao_lisp_chunk[AO_LISP_NCHUNK-1].old_addr +
-                               ao_lisp_chunk[AO_LISP_NCHUNK-1].size;
+                       r = m - 1;
        }
+       /*
+        * The correct location is always in 'l', with r = l-1 being
+        * the entry before the right one
+        */
+
+#if DBG_MEM
+       /* Off the right side */
+       if (l >= AO_LISP_NCHUNK)
+               ao_lisp_abort();
+
+       /* Off the left side */
+       if (l == 0 && chunk_busy && addr > ao_lisp_chunk[0].old_addr)
+               ao_lisp_abort();
+#endif
+
+       /* Shuffle existing entries right */
+       int end = min(AO_LISP_NCHUNK, chunk_busy + 1);
+
+       memmove(&ao_lisp_chunk[l+1],
+               &ao_lisp_chunk[l],
+               (end - (l+1)) * sizeof (struct ao_lisp_chunk));
+
+       /* Add new entry */
+       ao_lisp_chunk[l].old_addr = addr;
+       ao_lisp_chunk[l].size = size;
+
+       /* Increment the number of elements up to the size of the array */
+       if (chunk_busy < AO_LISP_NCHUNK)
+               chunk_busy++;
+
+       /* Set the top address if the array is full */
+       if (chunk_busy == AO_LISP_NCHUNK)
+               chunk_high = ao_lisp_chunk[AO_LISP_NCHUNK-1].old_addr +
+                       ao_lisp_chunk[AO_LISP_NCHUNK-1].size;
 }
 
 static void