OSDN Git Service

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