123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- /* Sparse Arrays for Objective C dispatch tables
- Copyright (C) 1993-2015 Free Software Foundation, Inc.
- Contributed by Kresten Krab Thorup.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GCC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
- #ifndef __sarray_INCLUDE_GNU
- #define __sarray_INCLUDE_GNU
- #define OBJC_SPARSE2 /* 2-level sparse array. */
- /* #define OBJC_SPARSE3 */ /* 3-level sparse array. */
- #ifdef OBJC_SPARSE2
- extern const char* __objc_sparse2_id;
- #endif
- #ifdef OBJC_SPARSE3
- extern const char* __objc_sparse3_id;
- #endif
- #include <stddef.h>
- extern int nbuckets; /* for stats */
- extern int nindices;
- extern int narrays;
- extern int idxsize;
- /* An unsigned integer of same size as a pointer. */
- #define SIZET_BITS (sizeof (size_t) * 8)
- #if defined (__sparc__) || defined (OBJC_SPARSE2)
- #define PRECOMPUTE_SELECTORS
- #endif
- #ifdef OBJC_SPARSE3
- /* Buckets are 8 words each. */
- #define BUCKET_BITS 3
- #define BUCKET_SIZE (1 << BUCKET_BITS)
- #define BUCKET_MASK (BUCKET_SIZE - 1)
- /* Indices are 16 words each. */
- #define INDEX_BITS 4
- #define INDEX_SIZE (1 << INDEX_BITS)
- #define INDEX_MASK (INDEX_SIZE - 1)
- #define INDEX_CAPACITY (BUCKET_SIZE * INDEX_SIZE)
- #else /* OBJC_SPARSE2 */
- /* Buckets are 32 words each. */
- #define BUCKET_BITS 5
- #define BUCKET_SIZE (1 << BUCKET_BITS)
- #define BUCKET_MASK (BUCKET_SIZE - 1)
- #endif /* OBJC_SPARSE2 */
- typedef size_t sidx;
- #ifdef PRECOMPUTE_SELECTORS
- struct soffset
- {
- #ifdef OBJC_SPARSE3
- unsigned int unused : SIZET_BITS / 4;
- unsigned int eoffset : SIZET_BITS / 4;
- unsigned int boffset : SIZET_BITS / 4;
- unsigned int ioffset : SIZET_BITS / 4;
- #else /* OBJC_SPARSE2 */
- #ifdef __sparc__
- unsigned long boffset : (SIZET_BITS - 2) - BUCKET_BITS;
- unsigned int eoffset : BUCKET_BITS;
- unsigned int unused : 2;
- #else
- unsigned int boffset : SIZET_BITS / 2;
- unsigned int eoffset : SIZET_BITS / 2;
- #endif
- #endif /* OBJC_SPARSE2 */
- };
- union sofftype
- {
- struct soffset off;
- sidx idx;
- };
- #endif /* not PRECOMPUTE_SELECTORS */
- union sversion
- {
- int version;
- void *next_free;
- };
- struct sbucket
- {
- /* Elements stored in array. */
- void* elems[BUCKET_SIZE];
- /* Used for copy-on-write. */
- union sversion version;
- };
- #ifdef OBJC_SPARSE3
- struct sindex
- {
- struct sbucket* buckets[INDEX_SIZE];
- /* Used for copy-on-write. */
- union sversion version;
- };
- #endif /* OBJC_SPARSE3 */
- struct sarray
- {
- #ifdef OBJC_SPARSE3
- struct sindex** indices;
- struct sindex* empty_index;
- #else /* OBJC_SPARSE2 */
- struct sbucket** buckets;
- #endif /* OBJC_SPARSE2 */
- struct sbucket* empty_bucket;
- /* Used for copy-on-write. */
- union sversion version;
- short ref_count;
- struct sarray* is_copy_of;
- size_t capacity;
- };
- struct sarray* sarray_new (int, void* default_element);
- void sarray_free (struct sarray*);
- struct sarray* sarray_lazy_copy (struct sarray*);
- void sarray_realloc (struct sarray*, int new_size);
- void sarray_at_put (struct sarray*, sidx indx, void* elem);
- void sarray_at_put_safe (struct sarray*, sidx indx, void* elem);
- struct sarray* sarray_hard_copy (struct sarray*); /* ... like the name ? */
- void sarray_remove_garbage (void);
- #ifdef PRECOMPUTE_SELECTORS
- /* Transform soffset values to ints and vice versa. */
- static inline unsigned int
- soffset_decode (sidx indx)
- {
- union sofftype x;
- x.idx = indx;
- #ifdef OBJC_SPARSE3
- return x.off.eoffset
- + (x.off.boffset * BUCKET_SIZE)
- + (x.off.ioffset * INDEX_CAPACITY);
- #else /* OBJC_SPARSE2 */
- return x.off.eoffset + (x.off.boffset * BUCKET_SIZE);
- #endif /* OBJC_SPARSE2 */
- }
- static inline sidx
- soffset_encode (size_t offset)
- {
- union sofftype x;
- x.off.eoffset = offset % BUCKET_SIZE;
- #ifdef OBJC_SPARSE3
- x.off.boffset = (offset / BUCKET_SIZE) % INDEX_SIZE;
- x.off.ioffset = offset / INDEX_CAPACITY;
- #else /* OBJC_SPARSE2 */
- x.off.boffset = offset / BUCKET_SIZE;
- #endif
- return (sidx)x.idx;
- }
- #else /* not PRECOMPUTE_SELECTORS */
- static inline size_t
- soffset_decode (sidx indx)
- {
- return indx;
- }
- static inline sidx
- soffset_encode (size_t offset)
- {
- return offset;
- }
- #endif /* not PRECOMPUTE_SELECTORS */
- /* Get element from the Sparse array `array' at offset `indx'. */
- static inline void* sarray_get (struct sarray* array, sidx indx)
- {
- #ifdef PRECOMPUTE_SELECTORS
- union sofftype x;
- x.idx = indx;
- #ifdef OBJC_SPARSE3
- return array->
- indices[x.off.ioffset]->
- buckets[x.off.boffset]->
- elems[x.off.eoffset];
- #else /* OBJC_SPARSE2 */
- return array->buckets[x.off.boffset]->elems[x.off.eoffset];
- #endif /* OBJC_SPARSE2 */
- #else /* not PRECOMPUTE_SELECTORS */
- #ifdef OBJC_SPARSE3
- return array->
- indices[indx / INDEX_CAPACITY]->
- buckets[(indx / BUCKET_SIZE) % INDEX_SIZE]->
- elems[indx % BUCKET_SIZE];
- #else /* OBJC_SPARSE2 */
- return array->buckets[indx / BUCKET_SIZE]->elems[indx % BUCKET_SIZE];
- #endif /* not OBJC_SPARSE3 */
- #endif /* not PRECOMPUTE_SELECTORS */
- }
- static inline void* sarray_get_safe (struct sarray* array, sidx indx)
- {
- if (soffset_decode (indx) < array->capacity)
- return sarray_get (array, indx);
- else
- return (array->empty_bucket->elems[0]);
- }
- #endif /* __sarray_INCLUDE_GNU */
|