/* 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);
}