]> git.ipfire.org Git - thirdparty/gcc.git/blame - libobjc/objc-private/sarray.h
Update copyright years.
[thirdparty/gcc.git] / libobjc / objc-private / sarray.h
CommitLineData
5d3b14bd 1/* Sparse Arrays for Objective C dispatch tables
8d9254fc 2 Copyright (C) 1993-2020 Free Software Foundation, Inc.
5d3b14bd
NP
3 Contributed by Kresten Krab Thorup.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
25
26#ifndef __sarray_INCLUDE_GNU
27#define __sarray_INCLUDE_GNU
28
9fd553cc
NP
29#define OBJC_SPARSE2 /* 2-level sparse array. */
30/* #define OBJC_SPARSE3 */ /* 3-level sparse array. */
5d3b14bd
NP
31
32#ifdef OBJC_SPARSE2
33extern const char* __objc_sparse2_id;
34#endif
35
36#ifdef OBJC_SPARSE3
37extern const char* __objc_sparse3_id;
38#endif
39
40#include <stddef.h>
41
5d3b14bd
NP
42extern int nbuckets; /* for stats */
43extern int nindices;
44extern int narrays;
45extern int idxsize;
46
9fd553cc
NP
47/* An unsigned integer of same size as a pointer. */
48#define SIZET_BITS (sizeof (size_t) * 8)
5d3b14bd 49
9fd553cc 50#if defined (__sparc__) || defined (OBJC_SPARSE2)
5d3b14bd
NP
51#define PRECOMPUTE_SELECTORS
52#endif
53
54#ifdef OBJC_SPARSE3
55
9fd553cc 56/* Buckets are 8 words each. */
5d3b14bd 57#define BUCKET_BITS 3
9fd553cc
NP
58#define BUCKET_SIZE (1 << BUCKET_BITS)
59#define BUCKET_MASK (BUCKET_SIZE - 1)
5d3b14bd 60
9fd553cc 61/* Indices are 16 words each. */
5d3b14bd 62#define INDEX_BITS 4
9fd553cc
NP
63#define INDEX_SIZE (1 << INDEX_BITS)
64#define INDEX_MASK (INDEX_SIZE - 1)
5d3b14bd 65
9fd553cc 66#define INDEX_CAPACITY (BUCKET_SIZE * INDEX_SIZE)
5d3b14bd
NP
67
68#else /* OBJC_SPARSE2 */
69
9fd553cc 70/* Buckets are 32 words each. */
5d3b14bd 71#define BUCKET_BITS 5
9fd553cc
NP
72#define BUCKET_SIZE (1 << BUCKET_BITS)
73#define BUCKET_MASK (BUCKET_SIZE - 1)
5d3b14bd
NP
74
75#endif /* OBJC_SPARSE2 */
76
77typedef size_t sidx;
78
79#ifdef PRECOMPUTE_SELECTORS
80
9fd553cc
NP
81struct soffset
82{
5d3b14bd 83#ifdef OBJC_SPARSE3
9fd553cc
NP
84 unsigned int unused : SIZET_BITS / 4;
85 unsigned int eoffset : SIZET_BITS / 4;
86 unsigned int boffset : SIZET_BITS / 4;
87 unsigned int ioffset : SIZET_BITS / 4;
5d3b14bd
NP
88#else /* OBJC_SPARSE2 */
89#ifdef __sparc__
90 unsigned long boffset : (SIZET_BITS - 2) - BUCKET_BITS;
91 unsigned int eoffset : BUCKET_BITS;
92 unsigned int unused : 2;
93#else
9fd553cc
NP
94 unsigned int boffset : SIZET_BITS / 2;
95 unsigned int eoffset : SIZET_BITS / 2;
5d3b14bd
NP
96#endif
97#endif /* OBJC_SPARSE2 */
98};
99
9fd553cc
NP
100union sofftype
101{
5d3b14bd
NP
102 struct soffset off;
103 sidx idx;
104};
105
106#endif /* not PRECOMPUTE_SELECTORS */
107
9fd553cc
NP
108union sversion
109{
5d3b14bd
NP
110 int version;
111 void *next_free;
112};
113
9fd553cc
NP
114struct sbucket
115{
116 /* Elements stored in array. */
117 void* elems[BUCKET_SIZE];
118
119 /* Used for copy-on-write. */
120 union sversion version;
5d3b14bd
NP
121};
122
123#ifdef OBJC_SPARSE3
124
9fd553cc
NP
125struct sindex
126{
5d3b14bd 127 struct sbucket* buckets[INDEX_SIZE];
9fd553cc
NP
128
129 /* Used for copy-on-write. */
130 union sversion version;
5d3b14bd
NP
131};
132
133#endif /* OBJC_SPARSE3 */
134
9fd553cc
NP
135struct sarray
136{
5d3b14bd
NP
137#ifdef OBJC_SPARSE3
138 struct sindex** indices;
139 struct sindex* empty_index;
140#else /* OBJC_SPARSE2 */
141 struct sbucket** buckets;
142#endif /* OBJC_SPARSE2 */
143 struct sbucket* empty_bucket;
9fd553cc
NP
144
145 /* Used for copy-on-write. */
146 union sversion version;
147
5d3b14bd
NP
148 short ref_count;
149 struct sarray* is_copy_of;
150 size_t capacity;
151};
152
9fd553cc
NP
153struct sarray* sarray_new (int, void* default_element);
154void sarray_free (struct sarray*);
155struct sarray* sarray_lazy_copy (struct sarray*);
156void sarray_realloc (struct sarray*, int new_size);
157void sarray_at_put (struct sarray*, sidx indx, void* elem);
158void sarray_at_put_safe (struct sarray*, sidx indx, void* elem);
5d3b14bd 159
9fd553cc
NP
160struct sarray* sarray_hard_copy (struct sarray*); /* ... like the name ? */
161void sarray_remove_garbage (void);
5d3b14bd
NP
162\f
163
164#ifdef PRECOMPUTE_SELECTORS
9fd553cc 165/* Transform soffset values to ints and vice versa. */
5d3b14bd 166static inline unsigned int
9fd553cc 167soffset_decode (sidx indx)
5d3b14bd
NP
168{
169 union sofftype x;
170 x.idx = indx;
171#ifdef OBJC_SPARSE3
172 return x.off.eoffset
9fd553cc
NP
173 + (x.off.boffset * BUCKET_SIZE)
174 + (x.off.ioffset * INDEX_CAPACITY);
5d3b14bd 175#else /* OBJC_SPARSE2 */
9fd553cc 176 return x.off.eoffset + (x.off.boffset * BUCKET_SIZE);
5d3b14bd
NP
177#endif /* OBJC_SPARSE2 */
178}
179
180static inline sidx
9fd553cc 181soffset_encode (size_t offset)
5d3b14bd
NP
182{
183 union sofftype x;
9fd553cc 184 x.off.eoffset = offset % BUCKET_SIZE;
5d3b14bd 185#ifdef OBJC_SPARSE3
9fd553cc
NP
186 x.off.boffset = (offset / BUCKET_SIZE) % INDEX_SIZE;
187 x.off.ioffset = offset / INDEX_CAPACITY;
5d3b14bd 188#else /* OBJC_SPARSE2 */
9fd553cc 189 x.off.boffset = offset / BUCKET_SIZE;
5d3b14bd
NP
190#endif
191 return (sidx)x.idx;
192}
193
194#else /* not PRECOMPUTE_SELECTORS */
195
196static inline size_t
9fd553cc 197soffset_decode (sidx indx)
5d3b14bd
NP
198{
199 return indx;
200}
201
202static inline sidx
9fd553cc 203soffset_encode (size_t offset)
5d3b14bd
NP
204{
205 return offset;
206}
207#endif /* not PRECOMPUTE_SELECTORS */
208
9fd553cc
NP
209/* Get element from the Sparse array `array' at offset `indx'. */
210static inline void* sarray_get (struct sarray* array, sidx indx)
5d3b14bd
NP
211{
212#ifdef PRECOMPUTE_SELECTORS
213 union sofftype x;
214 x.idx = indx;
215#ifdef OBJC_SPARSE3
9fd553cc
NP
216 return array->
217 indices[x.off.ioffset]->
218 buckets[x.off.boffset]->
219 elems[x.off.eoffset];
5d3b14bd
NP
220#else /* OBJC_SPARSE2 */
221 return array->buckets[x.off.boffset]->elems[x.off.eoffset];
222#endif /* OBJC_SPARSE2 */
223#else /* not PRECOMPUTE_SELECTORS */
224#ifdef OBJC_SPARSE3
225 return array->
9fd553cc
NP
226 indices[indx / INDEX_CAPACITY]->
227 buckets[(indx / BUCKET_SIZE) % INDEX_SIZE]->
228 elems[indx % BUCKET_SIZE];
5d3b14bd 229#else /* OBJC_SPARSE2 */
9fd553cc 230 return array->buckets[indx / BUCKET_SIZE]->elems[indx % BUCKET_SIZE];
5d3b14bd
NP
231#endif /* not OBJC_SPARSE3 */
232#endif /* not PRECOMPUTE_SELECTORS */
233}
234
9fd553cc 235static inline void* sarray_get_safe (struct sarray* array, sidx indx)
5d3b14bd 236{
9fd553cc
NP
237 if (soffset_decode (indx) < array->capacity)
238 return sarray_get (array, indx);
5d3b14bd
NP
239 else
240 return (array->empty_bucket->elems[0]);
241}
242
5d3b14bd 243#endif /* __sarray_INCLUDE_GNU */