xref: /netbsd-src/external/gpl3/gcc.old/dist/libobjc/objc-private/sarray.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
136ac495dSmrg /* Sparse Arrays for Objective C dispatch tables
2*8feb0f0bSmrg    Copyright (C) 1993-2020 Free Software Foundation, Inc.
336ac495dSmrg    Contributed by Kresten Krab Thorup.
436ac495dSmrg 
536ac495dSmrg This file is part of GCC.
636ac495dSmrg 
736ac495dSmrg GCC is free software; you can redistribute it and/or modify
836ac495dSmrg it under the terms of the GNU General Public License as published by
936ac495dSmrg the Free Software Foundation; either version 3, or (at your option)
1036ac495dSmrg any later version.
1136ac495dSmrg 
1236ac495dSmrg GCC is distributed in the hope that it will be useful,
1336ac495dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
1436ac495dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1536ac495dSmrg GNU General Public License for more details.
1636ac495dSmrg 
1736ac495dSmrg Under Section 7 of GPL version 3, you are granted additional
1836ac495dSmrg permissions described in the GCC Runtime Library Exception, version
1936ac495dSmrg 3.1, as published by the Free Software Foundation.
2036ac495dSmrg 
2136ac495dSmrg You should have received a copy of the GNU General Public License and
2236ac495dSmrg a copy of the GCC Runtime Library Exception along with this program;
2336ac495dSmrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2436ac495dSmrg <http://www.gnu.org/licenses/>.  */
2536ac495dSmrg 
2636ac495dSmrg #ifndef __sarray_INCLUDE_GNU
2736ac495dSmrg #define __sarray_INCLUDE_GNU
2836ac495dSmrg 
2936ac495dSmrg #define OBJC_SPARSE2		/* 2-level sparse array.  */
3036ac495dSmrg /* #define OBJC_SPARSE3 */      /* 3-level sparse array.  */
3136ac495dSmrg 
3236ac495dSmrg #ifdef OBJC_SPARSE2
3336ac495dSmrg extern const char* __objc_sparse2_id;
3436ac495dSmrg #endif
3536ac495dSmrg 
3636ac495dSmrg #ifdef OBJC_SPARSE3
3736ac495dSmrg extern const char* __objc_sparse3_id;
3836ac495dSmrg #endif
3936ac495dSmrg 
4036ac495dSmrg #include <stddef.h>
4136ac495dSmrg 
4236ac495dSmrg extern int nbuckets;		/* for stats */
4336ac495dSmrg extern int nindices;
4436ac495dSmrg extern int narrays;
4536ac495dSmrg extern int idxsize;
4636ac495dSmrg 
4736ac495dSmrg /* An unsigned integer of same size as a pointer.  */
4836ac495dSmrg #define SIZET_BITS (sizeof (size_t) * 8)
4936ac495dSmrg 
5036ac495dSmrg #if defined (__sparc__) || defined (OBJC_SPARSE2)
5136ac495dSmrg #define PRECOMPUTE_SELECTORS
5236ac495dSmrg #endif
5336ac495dSmrg 
5436ac495dSmrg #ifdef OBJC_SPARSE3
5536ac495dSmrg 
5636ac495dSmrg /* Buckets are 8 words each.  */
5736ac495dSmrg #define BUCKET_BITS 3
5836ac495dSmrg #define BUCKET_SIZE (1 << BUCKET_BITS)
5936ac495dSmrg #define BUCKET_MASK (BUCKET_SIZE - 1)
6036ac495dSmrg 
6136ac495dSmrg /* Indices are 16 words each.  */
6236ac495dSmrg #define INDEX_BITS 4
6336ac495dSmrg #define INDEX_SIZE (1 << INDEX_BITS)
6436ac495dSmrg #define INDEX_MASK (INDEX_SIZE - 1)
6536ac495dSmrg 
6636ac495dSmrg #define INDEX_CAPACITY (BUCKET_SIZE * INDEX_SIZE)
6736ac495dSmrg 
6836ac495dSmrg #else /* OBJC_SPARSE2 */
6936ac495dSmrg 
7036ac495dSmrg /* Buckets are 32 words each.  */
7136ac495dSmrg #define BUCKET_BITS 5
7236ac495dSmrg #define BUCKET_SIZE (1 << BUCKET_BITS)
7336ac495dSmrg #define BUCKET_MASK (BUCKET_SIZE - 1)
7436ac495dSmrg 
7536ac495dSmrg #endif /* OBJC_SPARSE2 */
7636ac495dSmrg 
7736ac495dSmrg typedef size_t sidx;
7836ac495dSmrg 
7936ac495dSmrg #ifdef PRECOMPUTE_SELECTORS
8036ac495dSmrg 
8136ac495dSmrg struct soffset
8236ac495dSmrg {
8336ac495dSmrg #ifdef OBJC_SPARSE3
8436ac495dSmrg   unsigned int unused : SIZET_BITS / 4;
8536ac495dSmrg   unsigned int eoffset : SIZET_BITS / 4;
8636ac495dSmrg   unsigned int boffset : SIZET_BITS / 4;
8736ac495dSmrg   unsigned int ioffset : SIZET_BITS / 4;
8836ac495dSmrg #else /* OBJC_SPARSE2 */
8936ac495dSmrg #ifdef __sparc__
9036ac495dSmrg   unsigned long boffset : (SIZET_BITS - 2) - BUCKET_BITS;
9136ac495dSmrg   unsigned int eoffset : BUCKET_BITS;
9236ac495dSmrg   unsigned int unused  : 2;
9336ac495dSmrg #else
9436ac495dSmrg   unsigned int boffset : SIZET_BITS / 2;
9536ac495dSmrg   unsigned int eoffset : SIZET_BITS / 2;
9636ac495dSmrg #endif
9736ac495dSmrg #endif /* OBJC_SPARSE2 */
9836ac495dSmrg };
9936ac495dSmrg 
10036ac495dSmrg union sofftype
10136ac495dSmrg {
10236ac495dSmrg   struct soffset off;
10336ac495dSmrg   sidx idx;
10436ac495dSmrg };
10536ac495dSmrg 
10636ac495dSmrg #endif /* not PRECOMPUTE_SELECTORS */
10736ac495dSmrg 
10836ac495dSmrg union sversion
10936ac495dSmrg {
11036ac495dSmrg   int	version;
11136ac495dSmrg   void *next_free;
11236ac495dSmrg };
11336ac495dSmrg 
11436ac495dSmrg struct sbucket
11536ac495dSmrg {
11636ac495dSmrg   /* Elements stored in array.  */
11736ac495dSmrg   void* elems[BUCKET_SIZE];
11836ac495dSmrg 
11936ac495dSmrg   /* Used for copy-on-write.  */
12036ac495dSmrg   union sversion version;
12136ac495dSmrg };
12236ac495dSmrg 
12336ac495dSmrg #ifdef OBJC_SPARSE3
12436ac495dSmrg 
12536ac495dSmrg struct sindex
12636ac495dSmrg {
12736ac495dSmrg   struct sbucket* buckets[INDEX_SIZE];
12836ac495dSmrg 
12936ac495dSmrg   /* Used for copy-on-write. */
13036ac495dSmrg   union sversion version;
13136ac495dSmrg };
13236ac495dSmrg 
13336ac495dSmrg #endif /* OBJC_SPARSE3 */
13436ac495dSmrg 
13536ac495dSmrg struct sarray
13636ac495dSmrg {
13736ac495dSmrg #ifdef OBJC_SPARSE3
13836ac495dSmrg   struct sindex** indices;
13936ac495dSmrg   struct sindex* empty_index;
14036ac495dSmrg #else /* OBJC_SPARSE2 */
14136ac495dSmrg   struct sbucket** buckets;
14236ac495dSmrg #endif  /* OBJC_SPARSE2 */
14336ac495dSmrg   struct sbucket* empty_bucket;
14436ac495dSmrg 
14536ac495dSmrg   /* Used for copy-on-write. */
14636ac495dSmrg   union sversion version;
14736ac495dSmrg 
14836ac495dSmrg   short ref_count;
14936ac495dSmrg   struct sarray* is_copy_of;
15036ac495dSmrg   size_t capacity;
15136ac495dSmrg };
15236ac495dSmrg 
15336ac495dSmrg struct sarray* sarray_new (int, void* default_element);
15436ac495dSmrg void sarray_free (struct sarray*);
15536ac495dSmrg struct sarray* sarray_lazy_copy (struct sarray*);
15636ac495dSmrg void sarray_realloc (struct sarray*, int new_size);
15736ac495dSmrg void sarray_at_put (struct sarray*, sidx indx, void* elem);
15836ac495dSmrg void sarray_at_put_safe (struct sarray*, sidx indx, void* elem);
15936ac495dSmrg 
16036ac495dSmrg struct sarray* sarray_hard_copy (struct sarray*); /* ... like the name ?  */
16136ac495dSmrg void sarray_remove_garbage (void);
16236ac495dSmrg 
16336ac495dSmrg 
16436ac495dSmrg #ifdef PRECOMPUTE_SELECTORS
16536ac495dSmrg /* Transform soffset values to ints and vice versa.  */
16636ac495dSmrg static inline unsigned int
soffset_decode(sidx indx)16736ac495dSmrg soffset_decode (sidx indx)
16836ac495dSmrg {
16936ac495dSmrg   union sofftype x;
17036ac495dSmrg   x.idx = indx;
17136ac495dSmrg #ifdef OBJC_SPARSE3
17236ac495dSmrg   return x.off.eoffset
17336ac495dSmrg     + (x.off.boffset * BUCKET_SIZE)
17436ac495dSmrg     + (x.off.ioffset * INDEX_CAPACITY);
17536ac495dSmrg #else /* OBJC_SPARSE2 */
17636ac495dSmrg   return x.off.eoffset + (x.off.boffset * BUCKET_SIZE);
17736ac495dSmrg #endif /* OBJC_SPARSE2 */
17836ac495dSmrg }
17936ac495dSmrg 
18036ac495dSmrg static inline sidx
soffset_encode(size_t offset)18136ac495dSmrg soffset_encode (size_t offset)
18236ac495dSmrg {
18336ac495dSmrg   union sofftype x;
18436ac495dSmrg   x.off.eoffset = offset % BUCKET_SIZE;
18536ac495dSmrg #ifdef OBJC_SPARSE3
18636ac495dSmrg   x.off.boffset = (offset / BUCKET_SIZE) % INDEX_SIZE;
18736ac495dSmrg   x.off.ioffset = offset / INDEX_CAPACITY;
18836ac495dSmrg #else /* OBJC_SPARSE2 */
18936ac495dSmrg   x.off.boffset = offset / BUCKET_SIZE;
19036ac495dSmrg #endif
19136ac495dSmrg   return (sidx)x.idx;
19236ac495dSmrg }
19336ac495dSmrg 
19436ac495dSmrg #else /* not PRECOMPUTE_SELECTORS */
19536ac495dSmrg 
19636ac495dSmrg static inline size_t
soffset_decode(sidx indx)19736ac495dSmrg soffset_decode (sidx indx)
19836ac495dSmrg {
19936ac495dSmrg   return indx;
20036ac495dSmrg }
20136ac495dSmrg 
20236ac495dSmrg static inline sidx
soffset_encode(size_t offset)20336ac495dSmrg soffset_encode (size_t offset)
20436ac495dSmrg {
20536ac495dSmrg   return offset;
20636ac495dSmrg }
20736ac495dSmrg #endif /* not PRECOMPUTE_SELECTORS */
20836ac495dSmrg 
20936ac495dSmrg /* Get element from the Sparse array `array' at offset `indx'.  */
sarray_get(struct sarray * array,sidx indx)21036ac495dSmrg static inline void* sarray_get (struct sarray* array, sidx indx)
21136ac495dSmrg {
21236ac495dSmrg #ifdef PRECOMPUTE_SELECTORS
21336ac495dSmrg   union sofftype x;
21436ac495dSmrg   x.idx = indx;
21536ac495dSmrg #ifdef OBJC_SPARSE3
21636ac495dSmrg   return array->
21736ac495dSmrg     indices[x.off.ioffset]->
21836ac495dSmrg     buckets[x.off.boffset]->
21936ac495dSmrg     elems[x.off.eoffset];
22036ac495dSmrg #else /* OBJC_SPARSE2 */
22136ac495dSmrg   return array->buckets[x.off.boffset]->elems[x.off.eoffset];
22236ac495dSmrg #endif /* OBJC_SPARSE2 */
22336ac495dSmrg #else /* not PRECOMPUTE_SELECTORS */
22436ac495dSmrg #ifdef OBJC_SPARSE3
22536ac495dSmrg   return array->
22636ac495dSmrg     indices[indx / INDEX_CAPACITY]->
22736ac495dSmrg     buckets[(indx / BUCKET_SIZE) % INDEX_SIZE]->
22836ac495dSmrg     elems[indx % BUCKET_SIZE];
22936ac495dSmrg #else /* OBJC_SPARSE2 */
23036ac495dSmrg   return array->buckets[indx / BUCKET_SIZE]->elems[indx % BUCKET_SIZE];
23136ac495dSmrg #endif /* not OBJC_SPARSE3 */
23236ac495dSmrg #endif /* not PRECOMPUTE_SELECTORS */
23336ac495dSmrg }
23436ac495dSmrg 
sarray_get_safe(struct sarray * array,sidx indx)23536ac495dSmrg static inline void* sarray_get_safe (struct sarray* array, sidx indx)
23636ac495dSmrg {
23736ac495dSmrg   if (soffset_decode (indx) < array->capacity)
23836ac495dSmrg     return sarray_get (array, indx);
23936ac495dSmrg   else
24036ac495dSmrg     return (array->empty_bucket->elems[0]);
24136ac495dSmrg }
24236ac495dSmrg 
24336ac495dSmrg #endif /* __sarray_INCLUDE_GNU */
244