source: trunk/src/gcc/libobjc/sarray.c@ 46

Last change on this file since 46 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 13.9 KB
Line 
1/* Sparse Arrays for Objective C dispatch tables
2 Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
20
21/* As a special exception, if you link this library with files
22 compiled with GCC to produce an executable, this does not cause
23 the resulting executable to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why
25 the executable file might be covered by the GNU General Public License. */
26
27#include "sarray.h"
28#include "runtime.h"
29#include <stdio.h>
30#include "assert.h"
31
32int nbuckets = 0; /* !T:MUTEX */
33int nindices = 0; /* !T:MUTEX */
34int narrays = 0; /* !T:MUTEX */
35int idxsize = 0; /* !T:MUTEX */
36
37static void * first_free_data = NULL; /* !T:MUTEX */
38
39#ifdef OBJC_SPARSE2
40const char* __objc_sparse2_id = "2 level sparse indices";
41#endif
42
43#ifdef OBJC_SPARSE3
44const char* __objc_sparse3_id = "3 level sparse indices";
45#endif
46
47/* This function removes any structures left over from free operations
48 that were not safe in a multi-threaded environment. */
49void
50sarray_remove_garbage(void)
51{
52 void **vp;
53 void *np;
54
55 objc_mutex_lock(__objc_runtime_mutex);
56
57 vp = first_free_data;
58 first_free_data = NULL;
59
60 while (vp) {
61 np = *vp;
62 objc_free(vp);
63 vp = np;
64 }
65
66 objc_mutex_unlock(__objc_runtime_mutex);
67}
68
69/* Free a block of dynamically allocated memory. If we are in multi-threaded
70 mode, it is ok to free it. If not, we add it to the garbage heap to be
71 freed later. */
72
73static void
74sarray_free_garbage(void *vp)
75{
76 objc_mutex_lock(__objc_runtime_mutex);
77
78 if (__objc_runtime_threads_alive == 1) {
79 objc_free(vp);
80 if (first_free_data)
81 sarray_remove_garbage();
82 }
83 else {
84 *(void **)vp = first_free_data;
85 first_free_data = vp;
86 }
87
88 objc_mutex_unlock(__objc_runtime_mutex);
89}
90
91/* sarray_at_put : copies data in such a way as to be thread reader safe. */
92void
93sarray_at_put(struct sarray* array, sidx index, void* element)
94{
95#ifdef OBJC_SPARSE3
96 struct sindex** the_index;
97 struct sindex* new_index;
98#endif
99 struct sbucket** the_bucket;
100 struct sbucket* new_bucket;
101#ifdef OBJC_SPARSE3
102 size_t ioffset;
103#endif
104 size_t boffset;
105 size_t eoffset;
106#ifdef PRECOMPUTE_SELECTORS
107 union sofftype xx;
108 xx.idx = index;
109#ifdef OBJC_SPARSE3
110 ioffset = xx.off.ioffset;
111#endif
112 boffset = xx.off.boffset;
113 eoffset = xx.off.eoffset;
114#else /* not PRECOMPUTE_SELECTORS */
115#ifdef OBJC_SPARSE3
116 ioffset = index/INDEX_CAPACITY;
117 boffset = (index/BUCKET_SIZE)%INDEX_SIZE;
118 eoffset = index%BUCKET_SIZE;
119#else
120 boffset = index/BUCKET_SIZE;
121 eoffset = index%BUCKET_SIZE;
122#endif
123#endif /* not PRECOMPUTE_SELECTORS */
124
125 assert(soffset_decode(index) < array->capacity); /* Range check */
126
127#ifdef OBJC_SPARSE3
128 the_index = &(array->indices[ioffset]);
129 the_bucket = &((*the_index)->buckets[boffset]);
130#else
131 the_bucket = &(array->buckets[boffset]);
132#endif
133
134 if ((*the_bucket)->elems[eoffset] == element)
135 return; /* great! we just avoided a lazy copy */
136
137#ifdef OBJC_SPARSE3
138
139 /* First, perform lazy copy/allocation of index if needed */
140
141 if ((*the_index) == array->empty_index) {
142
143 /* The index was previously empty, allocate a new */
144 new_index = (struct sindex*)objc_malloc(sizeof(struct sindex));
145 memcpy(new_index, array->empty_index, sizeof(struct sindex));
146 new_index->version.version = array->version.version;
147 *the_index = new_index; /* Prepared for install. */
148 the_bucket = &((*the_index)->buckets[boffset]);
149
150 nindices += 1;
151 } else if ((*the_index)->version.version != array->version.version) {
152
153 /* This index must be lazy copied */
154 struct sindex* old_index = *the_index;
155 new_index = (struct sindex*)objc_malloc(sizeof(struct sindex));
156 memcpy( new_index, old_index, sizeof(struct sindex));
157 new_index->version.version = array->version.version;
158 *the_index = new_index; /* Prepared for install. */
159 the_bucket = &((*the_index)->buckets[boffset]);
160
161 nindices += 1;
162 }
163
164#endif /* OBJC_SPARSE3 */
165
166 /* next, perform lazy allocation/copy of the bucket if needed */
167
168 if ((*the_bucket) == array->empty_bucket) {
169
170 /* The bucket was previously empty (or something like that), */
171 /* allocate a new. This is the effect of `lazy' allocation */
172 new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket));
173 memcpy((void *) new_bucket, (const void*)array->empty_bucket,
174 sizeof(struct sbucket));
175 new_bucket->version.version = array->version.version;
176 *the_bucket = new_bucket; /* Prepared for install. */
177
178 nbuckets += 1;