Makefile.am (asm_libgcjgc_sources): Rename to asm_libgcjgc_sources.
[gcc.git] / boehm-gc / tests / test_cpp.cc
1 /****************************************************************************
2 Copyright (c) 1994 by Xerox Corporation. All rights reserved.
3
4 THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5 OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
6
7 Permission is hereby granted to use or copy this program for any
8 purpose, provided the above notices are retained on all copies.
9 Permission to modify the code and to distribute modified code is
10 granted, provided the above notices are retained, and a notice that
11 the code was modified is included with the above copyright notice.
12 ****************************************************************************
13 Last modified on Mon Jul 10 21:06:03 PDT 1995 by ellis
14 modified on December 20, 1994 7:27 pm PST by boehm
15
16 usage: test_cpp number-of-iterations
17
18 This program tries to test the specific C++ functionality provided by
19 gc_c++.h that isn't tested by the more general test routines of the
20 collector.
21
22 A recommended value for number-of-iterations is 10, which will take a
23 few minutes to complete.
24
25 ***************************************************************************/
26
27 #include "gc_cpp.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #define USE_STD_ALLOCATOR
32 #ifdef USE_STD_ALLOCATOR
33 # include "gc_allocator.h"
34 #elif __GNUC__
35 # include "new_gc_alloc.h"
36 #else
37 # include "gc_alloc.h"
38 #endif
39 extern "C" {
40 #include "private/gc_priv.h"
41 }
42 #ifdef MSWIN32
43 # include <windows.h>
44 #endif
45 #ifdef GC_NAME_CONFLICT
46 # define USE_GC UseGC
47 struct foo * GC;
48 #else
49 # define USE_GC GC
50 #endif
51
52
53 #define my_assert( e ) \
54 if (! (e)) { \
55 GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
56 __LINE__ ); \
57 exit( 1 ); }
58
59
60 class A {public:
61 /* An uncollectable class. */
62
63 A( int iArg ): i( iArg ) {}
64 void Test( int iArg ) {
65 my_assert( i == iArg );}
66 int i;};
67
68
69 class B: public gc, public A {public:
70 /* A collectable class. */
71
72 B( int j ): A( j ) {}
73 ~B() {
74 my_assert( deleting );}
75 static void Deleting( int on ) {
76 deleting = on;}
77 static int deleting;};
78
79 int B::deleting = 0;
80
81
82 class C: public gc_cleanup, public A {public:
83 /* A collectable class with cleanup and virtual multiple inheritance. */
84
85 C( int levelArg ): A( levelArg ), level( levelArg ) {
86 nAllocated++;
87 if (level > 0) {
88 left = new C( level - 1 );
89 right = new C( level - 1 );}
90 else {
91 left = right = 0;}}
92 ~C() {
93 this->A::Test( level );
94 nFreed++;
95 my_assert( level == 0 ?
96 left == 0 && right == 0 :
97 level == left->level + 1 && level == right->level + 1 );
98 left = right = 0;
99 level = -123456;}
100 static void Test() {
101 my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
102
103 static int nFreed;
104 static int nAllocated;
105 int level;
106 C* left;
107 C* right;};
108
109 int C::nFreed = 0;
110 int C::nAllocated = 0;
111
112
113 class D: public gc {public:
114 /* A collectable class with a static member function to be used as
115 an explicit clean-up function supplied to ::new. */
116
117 D( int iArg ): i( iArg ) {
118 nAllocated++;}
119 static void CleanUp( void* obj, void* data ) {
120 D* self = (D*) obj;
121 nFreed++;
122 my_assert( self->i == (int) (long) data );}
123 static void Test() {
124 my_assert( nFreed >= .8 * nAllocated );}
125
126 int i;
127 static int nFreed;
128 static int nAllocated;};
129
130 int D::nFreed = 0;
131 int D::nAllocated = 0;
132
133
134 class E: public gc_cleanup {public:
135 /* A collectable class with clean-up for use by F. */
136
137 E() {
138 nAllocated++;}
139 ~E() {
140 nFreed++;}
141
142 static int nFreed;
143 static int nAllocated;};
144
145 int E::nFreed = 0;
146 int E::nAllocated = 0;
147
148
149 class F: public E {public:
150 /* A collectable class with clean-up, a base with clean-up, and a
151 member with clean-up. */
152
153 F() {
154 nAllocated++;}
155 ~F() {
156 nFreed++;}
157 static void Test() {
158 my_assert( nFreed >= .8 * nAllocated );
159 my_assert( 2 * nFreed == E::nFreed );}
160
161 E e;
162 static int nFreed;
163 static int nAllocated;};
164
165 int F::nFreed = 0;
166 int F::nAllocated = 0;
167
168
169 long Disguise( void* p ) {
170 return ~ (long) p;}
171
172 void* Undisguise( long i ) {
173 return (void*) ~ i;}
174
175
176 #ifdef MSWIN32
177 int APIENTRY WinMain(
178 HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow )
179 {
180 int argc;
181 char* argv[ 3 ];
182
183 for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
184 argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
185 if (0 == argv[ argc ]) break;}
186
187 #else
188 # ifdef MACOS
189 int main() {
190 # else
191 int main( int argc, char* argv[] ) {
192 # endif
193 #endif
194
195 GC_INIT();
196
197 # if defined(MACOS) // MacOS
198 char* argv_[] = {"test_cpp", "10"}; // doesn't
199 argv = argv_; // have a
200 argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
201 # endif
202 int i, iters, n;
203 # ifdef USE_STD_ALLOCATOR
204 int *x = gc_allocator<int>().allocate(1);
205 int **xptr = traceable_allocator<int *>().allocate(1);
206 # else
207 # ifdef __GNUC__
208 int *x = (int *)gc_alloc::allocate(sizeof(int));
209 # else
210 int *x = (int *)alloc::allocate(sizeof(int));
211 # endif
212 # endif
213 *x = 29;
214 # ifdef USE_STD_ALLOCATOR
215 *xptr = x;
216 x = 0;
217 # endif
218 if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
219 GC_printf0( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" );
220 n = 10;}
221
222 for (iters = 1; iters <= n; iters++) {
223 GC_printf1( "Starting iteration %d\n", iters );
224
225 /* Allocate some uncollectable As and disguise their pointers.
226 Later we'll check to see if the objects are still there. We're
227 checking to make sure these objects really are uncollectable. */
228 long as[ 1000 ];
229 long bs[ 1000 ];
230 for (i = 0; i < 1000; i++) {
231 as[ i ] = Disguise( new (NoGC) A( i ) );
232 bs[ i ] = Disguise( new (NoGC) B( i ) );}
233
234 /* Allocate a fair number of finalizable Cs, Ds, and Fs.
235 Later we'll check to make sure they've gone away. */
236 for (i = 0; i < 1000; i++) {
237 C* c = new C( 2 );
238 C c1( 2 ); /* stack allocation should work too */
239 D* d = ::new (USE_GC, D::CleanUp, (void*)(long)i) D( i );
240 F* f = new F;
241 if (0 == i % 10) delete c;}
242
243 /* Allocate a very large number of collectable As and Bs and
244 drop the references to them immediately, forcing many
245 collections. */
246 for (i = 0; i < 1000000; i++) {
247 A* a = new (USE_GC) A( i );
248 B* b = new B( i );
249 b = new (USE_GC) B( i );
250 if (0 == i % 10) {
251 B::Deleting( 1 );
252 delete b;
253 B::Deleting( 0 );}
254 # ifdef FINALIZE_ON_DEMAND
255 GC_invoke_finalizers();
256 # endif
257 }
258
259 /* Make sure the uncollectable As and Bs are still there. */
260 for (i = 0; i < 1000; i++) {
261 A* a = (A*) Undisguise( as[ i ] );
262 B* b = (B*) Undisguise( bs[ i ] );
263 a->Test( i );
264 delete a;
265 b->Test( i );
266 B::Deleting( 1 );
267 delete b;
268 B::Deleting( 0 );
269 # ifdef FINALIZE_ON_DEMAND
270 GC_invoke_finalizers();
271 # endif
272
273 }
274
275 /* Make sure most of the finalizable Cs, Ds, and Fs have
276 gone away. */
277 C::Test();
278 D::Test();
279 F::Test();}
280
281 # ifdef USE_STD_ALLOCATOR
282 x = *xptr;
283 # endif
284 my_assert (29 == x[0]);
285 GC_printf0( "The test appears to have succeeded.\n" );
286 return( 0 );}
287
288