/* Sun-$Revision: 23.10 $ */ /* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University. See the LICENSE file for license information. */ # pragma interface // Superclass for all (or most) VM objects. // Used for debugging purposes: objects can can be printed with pp() // (and with C-c C-p in emacs/gdb). -Urs struct VMObj { virtual ~VMObj(){} virtual void print(); virtual void print_short(); void print_zero(); void print_short_zero(); void print_short_null() { if (this != NULL) print_short(); } void print_null() { if (this != NULL) print(); } virtual void oops_do(oopsDoFn f) { Unused((void*)f); } VtblPtr_t vtbl_value() { return *((VtblPtr_t*) this); } void set_vtbl_value(VtblPtr_t v) { *((VtblPtr_t*) this) = v; } void kill_vtbl_value() { set_vtbl_value(0); } }; struct ResourceArea; // Base class for all objects using the resource area. struct ResourceObj: public VMObj { void* operator new(size_t size); void operator delete(void* p); void* new_array(size_t size); }; // Base class for all objects allocated in the c-heap. struct CHeapObj: public VMObj { void* operator new(size_t size); void operator delete(void* p); void* new_array(size_t size); }; // Base class for catching new or delete. // Calling new or delete will result in fatal error. struct NoExplicitAllocationObj: VMObj { void* operator new(size_t size) { Unused(size); ShouldNotCallThis(); return 0; }; void operator delete(void* p) { Unused(p); ShouldNotCallThis(); }; }; // Base class for all objects allocated on the stack only. // Calling new or delete will result in fatal error. struct StackObj: NoExplicitAllocationObj { }; // Base class for all objects allocated as part of another object only. // Added after main framework, dmu 6/96. struct PartObj: NoExplicitAllocationObj { }; // Base class for class that is no general, cannot commit // to whether it is a StackObj, ResourceObj, or whatever. struct AnywhereObj: VMObj { }; // One of the following macros must be used when allocating an array to // determine which area the array should reside in. # define NEW_RESOURCE_ARRAY( type, size )\ (type*) allocateResource( (size) * sizeof(type)) # define NEW_C_HEAP_ARRAY( type, size )\ (type*) AllocateHeap( (size) * sizeof(type), XSTR(type) " in " __FILE__) # define NEW_RESOURCE_OBJ( type ) NEW_RESOURCE_ARRAY( type, 1 ) // The resource area holds temporary data structures of the VM. Things // in the resource area can be deallocated very efficiently using // ResourceMarks. (The destructor of a ResourceMark will deallocate // everything that was created since the ResourceMark was created.) const fint min_resource_chunk_size = 100 * K; const fint min_resource_free_size = 32 * K; class ResourceAreaChunk: VMObj { friend class ResourceMark; friend class ResourceArea; friend class Resources; char* bottom; char* top; char* first_free; ResourceAreaChunk* prev; fint _allocated; // Allocated bytes in this and previous chunks. fint _previous_used; // Used bytes in previous chunks. void clear(char *start, char *endArg) { memset(start, 33, endArg - start); } void clear() { clear(bottom, first_free); } void freeTo(char *new_first_free); public: char* allocate_bytes(fint size) { char* p = first_free; if (first_free + size <= top) { # ifdef DEBUG extern bool PrintResourceAllocation; // to break cycle in includeDB if (PrintResourceAllocation) { lprintf("allocating %ld bytes at 0x%lx\n", (long)size, p); } # endif # ifdef GENERATE_ASSERTIONS if (CheckAssertions && p == (char*)catchThisOne) { warning1("ResourceAreaChunk::allocate_bytes caught 0x%lx", p); } # endif first_free += size; return p; } else return NULL; } ResourceAreaChunk(fint min_capacity, ResourceAreaChunk* previous); ~ResourceAreaChunk(); void initialize(ResourceAreaChunk* previous); fint capacity() { return top - bottom; } fint used() { return first_free - bottom; } bool contains(void* p) { if (p >= (void*) bottom && p < (void*) top) return true; else if (prev) return prev->contains(p); else return false; } void print(); void print_short() { lprintf("ResourceAreaChunk %#lx", this); } }; struct ResourceArea { ResourceAreaChunk* chunk; // current chunk fint nesting; // current # of nested ResourceMarks // (will warn if alloc with nesting == 0) ResourceArea(); ~ResourceArea(); char* allocate_more_bytes(int32 size); char* allocate_bytes(int32 size) { assert(size >= 0, "negative size in allocate_bytes"); assert(nesting >= 0, "memory leak!"); if (size == 0) { // want to return an invalid pointer for a zero-sized allocation, // but not NULL, because routines may want to use NULL for failure. return (char*) 1; } size = roundTo(size, oopSize); if (chunk) { char* p = chunk->allocate_bytes(size); if (p) return p; } return allocate_more_bytes(size); } fint capacity() { return chunk ? chunk->_allocated : 0; } int32 used(); bool contains(void* p) { return chunk != NULL && chunk->contains(p); } }; // A resource mark releases all resources allocated after it was created // when the mark is deleted. Typically used as a local variable. struct ResourceMark: ResourceObj { private: ResourceArea* area; ResourceAreaChunk* chunk; char* top; public: ResourceMark(); ~ResourceMark(); }; struct Resources { private: ResourceAreaChunk* freeChunks; // list of unused chunks fint _allocated; // total number of bytes allocated bool _in_consistent_state; ResourceAreaChunk* getFromFreeList(fint min_capacity); public: Resources(); ResourceAreaChunk* new_chunk(fint min_capacity, ResourceAreaChunk* area); void addToFreeList(ResourceAreaChunk* c); bool in_consistent_state() { return _in_consistent_state; } bool contains(char* p); int32 capacity(); int32 used(); }; extern Resources resources; extern void* selfs_malloc(size_t size); extern void selfs_free(void* ptr); extern void malloc_init(); extern bool MallocInProgress; // allocating on C heap right now? inline char* AllocateHeap(int32 size, char* name, bool mustAllocate= true) { char* b = (char *) selfs_malloc(size); if (mustAllocate && b == NULL) OS::allocate_failed(name); # ifdef GENERATE_ASSERTIONS if (CheckAssertions && b && (char*)catchThisOne == b) warning("AllocateHeap caught one"); # endif return b; } inline void FreeHeap(void* p) { # ifdef GENERATE_ASSERTIONS if (CheckAssertions && (void*)catchThisOne == p) warning("FreeHeap caught one"); # endif selfs_free((char*) p); }