30c3de1ffb
* BCC_MAKEFILE: Merge with GC 6.3alpha1 release. * ChangeLog: Likewise. * Makefile.am: Likewise. * Makefile.direct: Likewise. * Makefile.dj: Likewise. * allchblk.c: Likewise. * alloc.c: Likewise. * backgraph.c: Likewise. * configure.host: Likewise. * configure.in: Likewise. * dbg_mlc.c: Likewise. * dyn_load.c: Likewise. * finalize.c: Likewise. * gc_cpp.cc: Likewise. * gc_dlopen.c: Likewise. * gcj_mlc.c: Likewise. * if_mach.c: Likewise. * mach_dep.c: Likewise. * malloc.c: Likewise. * mallocx.c: Likewise. * mark.c: Likewise. * mark_rts.c: Likewise. * misc.c: Likewise. * os_dep.c: Likewise. * ptr_chck.c: Likewise. * reclaim.c: Likewise. * solaris_pthreads.c: Likewise. * solaris_threads.c: Likewise. * sparc_mach_dep.S: Likewise. * threadlibs.c: Likewise. * typd_mlc.c: Likewise. * version.h: Likewise. * win32_threads.c: Likewise. * Mac_files/MacOS_Test_config.h: Likewise. * Mac_files/MacOS_config.h: Likewise. * cord/cordbscs.c: Likewise. * cord/cordprnt.c: Likewise. * cord/de_win.c: Likewise. * doc/README: Likewise. * doc/README.MacOSX: Likewise. * doc/README.changes: Likewise. * doc/README.environment: Likewise. * doc/README.ews4800: Likewise. * doc/README.linux: Likewise. * doc/README.macros: Likewise. * doc/README.win32: Likewise. * doc/debugging.html: Likewise. * doc/gcdescr.html: Likewise. * doc/tree.html: Likewise. * include/Makefile.in: Likewise. * include/gc.h: Likewise. * include/gc_cpp.h: Likewise. * include/gc_local_alloc.h: Likewise. * include/gc_mark.h: Likewise. * include/gc_pthread_redirects.h: Likewise. * include/gc_typed.h: Likewise. * include/new_gc_alloc.h: Likewise. * include/private/dbg_mlc.h: Likewise. * include/private/gc_hdrs.h: Likewise. * include/private/gc_locks.h: Likewise. * include/private/gc_pmark.h: Likewise. * include/private/gc_priv.h: Likewise. * include/private/gcconfig.h: Likewise. * include/private/solaris_threads.h: Likewise. * include/private/specific.h: Likewise. * tests/test.c: Likewise. * tests/test_cpp.cc: Likewise. * configure: Rebuild. * Makefile.in: Rebuild. * mips_sgi_mach_dep.s: Add. * alpha_mach_dep.s: Remove. * irix_threads.c: Remove. * linux_threads.c: Remove. * mips_sgi_mach_dep.S: Remove. * missing: Remove. * powerpc_macosx_mach_dep.s: Remove. * doc/Makefile.am: Remove. * doc/Makefile.in: Remove. From-SVN: r69880
289 lines
7.7 KiB
C++
289 lines
7.7 KiB
C++
/****************************************************************************
|
|
Copyright (c) 1994 by Xerox Corporation. All rights reserved.
|
|
|
|
THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
|
OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
|
|
|
Permission is hereby granted to use or copy this program for any
|
|
purpose, provided the above notices are retained on all copies.
|
|
Permission to modify the code and to distribute modified code is
|
|
granted, provided the above notices are retained, and a notice that
|
|
the code was modified is included with the above copyright notice.
|
|
****************************************************************************
|
|
Last modified on Mon Jul 10 21:06:03 PDT 1995 by ellis
|
|
modified on December 20, 1994 7:27 pm PST by boehm
|
|
|
|
usage: test_cpp number-of-iterations
|
|
|
|
This program tries to test the specific C++ functionality provided by
|
|
gc_c++.h that isn't tested by the more general test routines of the
|
|
collector.
|
|
|
|
A recommended value for number-of-iterations is 10, which will take a
|
|
few minutes to complete.
|
|
|
|
***************************************************************************/
|
|
|
|
#include "gc_cpp.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#define USE_STD_ALLOCATOR
|
|
#ifdef USE_STD_ALLOCATOR
|
|
# include "gc_allocator.h"
|
|
#elif __GNUC__
|
|
# include "new_gc_alloc.h"
|
|
#else
|
|
# include "gc_alloc.h"
|
|
#endif
|
|
extern "C" {
|
|
#include "private/gc_priv.h"
|
|
}
|
|
#ifdef MSWIN32
|
|
# include <windows.h>
|
|
#endif
|
|
#ifdef GC_NAME_CONFLICT
|
|
# define USE_GC UseGC
|
|
struct foo * GC;
|
|
#else
|
|
# define USE_GC GC
|
|
#endif
|
|
|
|
|
|
#define my_assert( e ) \
|
|
if (! (e)) { \
|
|
GC_printf1( "Assertion failure in " __FILE__ ", line %d: " #e "\n", \
|
|
__LINE__ ); \
|
|
exit( 1 ); }
|
|
|
|
|
|
class A {public:
|
|
/* An uncollectable class. */
|
|
|
|
A( int iArg ): i( iArg ) {}
|
|
void Test( int iArg ) {
|
|
my_assert( i == iArg );}
|
|
int i;};
|
|
|
|
|
|
class B: public gc, public A {public:
|
|
/* A collectable class. */
|
|
|
|
B( int j ): A( j ) {}
|
|
~B() {
|
|
my_assert( deleting );}
|
|
static void Deleting( int on ) {
|
|
deleting = on;}
|
|
static int deleting;};
|
|
|
|
int B::deleting = 0;
|
|
|
|
|
|
class C: public gc_cleanup, public A {public:
|
|
/* A collectable class with cleanup and virtual multiple inheritance. */
|
|
|
|
C( int levelArg ): A( levelArg ), level( levelArg ) {
|
|
nAllocated++;
|
|
if (level > 0) {
|
|
left = new C( level - 1 );
|
|
right = new C( level - 1 );}
|
|
else {
|
|
left = right = 0;}}
|
|
~C() {
|
|
this->A::Test( level );
|
|
nFreed++;
|
|
my_assert( level == 0 ?
|
|
left == 0 && right == 0 :
|
|
level == left->level + 1 && level == right->level + 1 );
|
|
left = right = 0;
|
|
level = -123456;}
|
|
static void Test() {
|
|
my_assert( nFreed <= nAllocated && nFreed >= .8 * nAllocated );}
|
|
|
|
static int nFreed;
|
|
static int nAllocated;
|
|
int level;
|
|
C* left;
|
|
C* right;};
|
|
|
|
int C::nFreed = 0;
|
|
int C::nAllocated = 0;
|
|
|
|
|
|
class D: public gc {public:
|
|
/* A collectable class with a static member function to be used as
|
|
an explicit clean-up function supplied to ::new. */
|
|
|
|
D( int iArg ): i( iArg ) {
|
|
nAllocated++;}
|
|
static void CleanUp( void* obj, void* data ) {
|
|
D* self = (D*) obj;
|
|
nFreed++;
|
|
my_assert( self->i == (int) (long) data );}
|
|
static void Test() {
|
|
my_assert( nFreed >= .8 * nAllocated );}
|
|
|
|
int i;
|
|
static int nFreed;
|
|
static int nAllocated;};
|
|
|
|
int D::nFreed = 0;
|
|
int D::nAllocated = 0;
|
|
|
|
|
|
class E: public gc_cleanup {public:
|
|
/* A collectable class with clean-up for use by F. */
|
|
|
|
E() {
|
|
nAllocated++;}
|
|
~E() {
|
|
nFreed++;}
|
|
|
|
static int nFreed;
|
|
static int nAllocated;};
|
|
|
|
int E::nFreed = 0;
|
|
int E::nAllocated = 0;
|
|
|
|
|
|
class F: public E {public:
|
|
/* A collectable class with clean-up, a base with clean-up, and a
|
|
member with clean-up. */
|
|
|
|
F() {
|
|
nAllocated++;}
|
|
~F() {
|
|
nFreed++;}
|
|
static void Test() {
|
|
my_assert( nFreed >= .8 * nAllocated );
|
|
my_assert( 2 * nFreed == E::nFreed );}
|
|
|
|
E e;
|
|
static int nFreed;
|
|
static int nAllocated;};
|
|
|
|
int F::nFreed = 0;
|
|
int F::nAllocated = 0;
|
|
|
|
|
|
long Disguise( void* p ) {
|
|
return ~ (long) p;}
|
|
|
|
void* Undisguise( long i ) {
|
|
return (void*) ~ i;}
|
|
|
|
|
|
#ifdef MSWIN32
|
|
int APIENTRY WinMain(
|
|
HINSTANCE instance, HINSTANCE prev, LPSTR cmd, int cmdShow )
|
|
{
|
|
int argc;
|
|
char* argv[ 3 ];
|
|
|
|
for (argc = 1; argc < sizeof( argv ) / sizeof( argv[ 0 ] ); argc++) {
|
|
argv[ argc ] = strtok( argc == 1 ? cmd : 0, " \t" );
|
|
if (0 == argv[ argc ]) break;}
|
|
|
|
#else
|
|
# ifdef MACOS
|
|
int main() {
|
|
# else
|
|
int main( int argc, char* argv[] ) {
|
|
# endif
|
|
#endif
|
|
|
|
GC_init();
|
|
|
|
# if defined(MACOS) // MacOS
|
|
char* argv_[] = {"test_cpp", "10"}; // doesn't
|
|
argv = argv_; // have a
|
|
argc = sizeof(argv_)/sizeof(argv_[0]); // commandline
|
|
# endif
|
|
int i, iters, n;
|
|
# ifdef USE_STD_ALLOCATOR
|
|
int *x = gc_allocator<int>().allocate(1);
|
|
int **xptr = traceable_allocator<int *>().allocate(1);
|
|
# else
|
|
# ifdef __GNUC__
|
|
int *x = (int *)gc_alloc::allocate(sizeof(int));
|
|
# else
|
|
int *x = (int *)alloc::allocate(sizeof(int));
|
|
# endif
|
|
# endif
|
|
*x = 29;
|
|
# ifdef USE_STD_ALLOCATOR
|
|
*xptr = x;
|
|
x = 0;
|
|
# endif
|
|
if (argc != 2 || (0 >= (n = atoi( argv[ 1 ] )))) {
|
|
GC_printf0( "usage: test_cpp number-of-iterations\nAssuming 10 iters\n" );
|
|
n = 10;}
|
|
|
|
for (iters = 1; iters <= n; iters++) {
|
|
GC_printf1( "Starting iteration %d\n", iters );
|
|
|
|
/* Allocate some uncollectable As and disguise their pointers.
|
|
Later we'll check to see if the objects are still there. We're
|
|
checking to make sure these objects really are uncollectable. */
|
|
long as[ 1000 ];
|
|
long bs[ 1000 ];
|
|
for (i = 0; i < 1000; i++) {
|
|
as[ i ] = Disguise( new (NoGC) A( i ) );
|
|
bs[ i ] = Disguise( new (NoGC) B( i ) );}
|
|
|
|
/* Allocate a fair number of finalizable Cs, Ds, and Fs.
|
|
Later we'll check to make sure they've gone away. */
|
|
for (i = 0; i < 1000; i++) {
|
|
C* c = new C( 2 );
|
|
C c1( 2 ); /* stack allocation should work too */
|
|
D* d = ::new (USE_GC, D::CleanUp, (void*)(long)i) D( i );
|
|
F* f = new F;
|
|
if (0 == i % 10) delete c;}
|
|
|
|
/* Allocate a very large number of collectable As and Bs and
|
|
drop the references to them immediately, forcing many
|
|
collections. */
|
|
for (i = 0; i < 1000000; i++) {
|
|
A* a = new (USE_GC) A( i );
|
|
B* b = new B( i );
|
|
b = new (USE_GC) B( i );
|
|
if (0 == i % 10) {
|
|
B::Deleting( 1 );
|
|
delete b;
|
|
B::Deleting( 0 );}
|
|
# ifdef FINALIZE_ON_DEMAND
|
|
GC_invoke_finalizers();
|
|
# endif
|
|
}
|
|
|
|
/* Make sure the uncollectable As and Bs are still there. */
|
|
for (i = 0; i < 1000; i++) {
|
|
A* a = (A*) Undisguise( as[ i ] );
|
|
B* b = (B*) Undisguise( bs[ i ] );
|
|
a->Test( i );
|
|
delete a;
|
|
b->Test( i );
|
|
B::Deleting( 1 );
|
|
delete b;
|
|
B::Deleting( 0 );
|
|
# ifdef FINALIZE_ON_DEMAND
|
|
GC_invoke_finalizers();
|
|
# endif
|
|
|
|
}
|
|
|
|
/* Make sure most of the finalizable Cs, Ds, and Fs have
|
|
gone away. */
|
|
C::Test();
|
|
D::Test();
|
|
F::Test();}
|
|
|
|
# ifdef USE_STD_ALLOCATOR
|
|
x = *xptr;
|
|
# endif
|
|
my_assert (29 == x[0]);
|
|
GC_printf0( "The test appears to have succeeded.\n" );
|
|
return( 0 );}
|
|
|
|
|