/* Sun-$Revision: 23.9 $ */ /* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University. See the LICENSE file for license information. */ # pragma interface class space: public CHeapObj { friend class universe; friend class generation; friend class newGeneration; friend class oldGeneration; friend class Monitor; friend class abstract_monitor; friend class byteVectorOopClass; // friend oopsOop oopsOopClass::scavenge(fint); friend class oopsOopClass; // friend void nmethod::printDeps(); friend class nmethod; // instance variables protected: // invariant: objs_bottom and bytes_top are on page_size boundaries oop* objs_bottom; oop* objs_top; oop* bytes_bottom; // invariant: keep at least one word free between // object and byte areas, for sentinels, // ie, objs_top < bytes_bottom. oop* bytes_top; oop* old_objs_bottom; // these are used after a snapshot is read in oop* old_objs_top; oop* old_bytes_bottom; oop* old_bytes_top; int32 old_size_bytes() { // the extra 1 is for the invariant return oopSize * (1 + (old_bytes_top - old_bytes_bottom) + (old_objs_top - old_objs_bottom)); } friend bool rSet::verify(bool); public: char* name; // constructors; none allocate object space space(char *nm, int32 &size) { Unused(size); name= nm; } // dummy just for oldSpace space(char* nm, int32 &size, char *bottom) { init_space(nm, size, bottom); }; space(char* nm, char *bottom, char *top); space(char* nm, FILE *snap); void read_snapshot(FILE* snap, char *bottom, char *top); // destructor ~space() { delete [] name; } protected: void init_space(char* nm, int32 &size, char *bottom); public: // allocation test bool would_fit(fint size, fint bsize = 0) { return objs_top + size < bytes_bottom - bsize; } protected: // allocators; called by new,oldGeneration, and by string and block // allocators. oop* alloc_objs_local(fint size) { oop* p = objs_top; oop* p1 = p + size; if (p1 < bytes_bottom) { objs_top = p1; return p; } else { return NULL; } } void unalloc_objs_local(fint size) { objs_top -= size; } oop* alloc_objs_and_bytes_local(fint size, fint bsize, char*& bytes) { oop* p = objs_top; oop* p1 = p + size; oop* bp = bytes_bottom; oop* bp1 = bp - bsize; if (bp1 > p1 && bp1 <= bp) { objs_top = p1; bytes_bottom = bp1; bytes = (char*) bp1; return p; } else { return NULL; } } void unalloc_objs_and_bytes_local(fint size, fint bsize) { objs_top -= size; bytes_bottom += bsize; } public: oop* oopsStart() { return objs_bottom; } oop* oopsEnd() { return objs_top; } char* bytesStart() { return (char*) bytes_bottom; } char* spaceStart() { return (char*) objs_bottom; } char* spaceEnd() { return (char*) bytes_top; } int32 capacity() { return (char*) bytes_top - (char*) objs_bottom - oopSize; } int32 oops_used() { return objs_top - objs_bottom; } int32 bytes_used() { return (char*) bytes_top - (char*) bytes_bottom; } int32 oops_free() { return bytes_bottom - objs_top - 1; } int32 used() { return (char*) objs_top - (char*) objs_bottom + (char*) bytes_top - (char*) bytes_bottom; } int32 bytes_free() { return (char*) bytes_bottom - (char*) objs_top - oopSize; } bool contains(void* p) { return (oop*) p >= objs_bottom && (oop*) p <= bytes_top; } bool objs_contains(void* p) { return (oop*) p >= objs_bottom && (oop*) p < objs_top; } bool in_objs_bounds(void* p) { return (oop*) p >= objs_bottom && (oop*) p <= objs_top; } bool bytes_contains(void* p) { return (oop*) p >= bytes_bottom && (oop*) p <= bytes_top; } bool really_contains(void *p) { return objs_contains(p) || bytes_contains(p);} bool old_objs_contains(void* p) { return (oop*) p >= old_objs_bottom && (oop*) p < old_objs_top; } bool old_bytes_contains(void* p) { return (oop*) p >= old_bytes_bottom && (oop*) p <= old_bytes_top; } oop get_allocation_vector(); protected: void set_objs_top_sentinel(oop s) { *objs_top= s; } // operations inline void clear(); // inlined below void compact(mapOop unmarked_map_map, space*& copySpace, oop*& d, oop*& bd); virtual void gc_unmark_contents(); void verify(); // for debugging & fun oop find_oop_backwards(void* start); void oops_do(oopsDoFn f); void switch_pointers_in_region(oop from, oop to, oop* bottom, oop* top); void switch_pointers(oop from, oop to) { switch_pointers_in_region(from, to, objs_bottom, objs_top); } void write_snapshot_header(FILE* file); void write_snapshot(FILE* file); void relocate(); void relocate_bytes(); void fixup_maps(); void fixup_killables(); void canonicalize_maps(); bool need_to_relocate() { return objs_bottom != old_objs_bottom || bytes_bottom != old_bytes_bottom; } bool need_to_relocate_objs() { return objs_bottom != old_objs_bottom; } memOop relocate_objs(memOop p) { assert(old_objs_contains(p), "not correctly relocating"); return memOop((oop*) p + (objs_bottom - old_objs_bottom)); } char* relocate_bytes(char* p) { assert(old_bytes_contains(p), "not correctly relocating"); return (char*) ((oop*) p + (bytes_bottom - old_bytes_bottom)); } public: void enumerate_matches(enumeration *e); void enumerate_maps(enumeration *e); void enumerate_families(enumeration *e); void enumerate_all_objs(enumeration *e); protected: void enumerate_families_small(enumeration *e); public: void print(); }; inline void space::clear() { objs_top = objs_bottom; bytes_bottom = bytes_top; # ifdef GENERATE_ASSERTIONS if (CheckAssertions) { // to detect scavenging bugs set_oops(objs_bottom, oops_free(), oop(1)); } # endif } class newSpace: public space { friend class universe; friend class generation; friend class newGeneration; friend class oldGeneration; // these allocate directly in a newSpace // friend oop blockOopClass::clone_block(oop); friend class blockOopClass; friend oop clone0_prim(slotsOop rcvr); friend oop clone1_prim(slotsOop rcvr); friend oop clone2_prim(slotsOop rcvr); friend oop clone3_prim(slotsOop rcvr); friend oop clone4_prim(slotsOop rcvr); friend oop clone5_prim(slotsOop rcvr); friend oop clone6_prim(slotsOop rcvr); friend oop clone7_prim(slotsOop rcvr); friend oop clone8_prim(slotsOop rcvr); friend oop clone9_prim(slotsOop rcvr); // friend byteVectorOop byteVectorOopClass::scavenge(fint); friend class ::byteVectorOopClass; newSpace* next_space; private: // see friends for other callers oop* alloc_objs(fint size, bool mustAllocate= true) { assert(size > 0, "should be a positive allocation"); oop* p= alloc_objs_local(size); if (p) { # ifdef GENERATE_ASSERTIONS if (CheckAssertions && p == (oop*)catchThisOne) { warning1("space::alloc_objs caught 0x%lx", p); } # endif return p; } else { return alloc_more_objs(size, mustAllocate); } } oop* alloc_more_objs(fint size, bool mustAllocate); oop* alloc_objs_and_bytes(fint size, fint bsize, char*& bytes, bool mustAllocate= true) { assert(size > 0, "should be a positive allocation"); assert(bsize >= 0, "should be a non-negative allocation"); oop* p= alloc_objs_and_bytes_local(size, bsize, bytes); if (p) { # ifdef GENERATE_ASSERTIONS if (CheckAssertions && (p == (oop*)catchThisOne || bytes == (char*)catchThisOne)) { warning1("space::alloc_objs_and_bytes caught 0x%lx", catchThisOne); } # endif return p; } else { return alloc_more_objs_and_bytes(size, bsize, bytes, mustAllocate); } } oop* alloc_more_objs_and_bytes(fint size, fint bsize, char*& bytes, bool mustAllocate); bool scavenge_contents(oop*& start); // called by Memory newSpace(char* n, int32 &size, char* bottom) : space(n, size, bottom) {} newSpace(char* n, int32 &size, FILE* snap); }; class oldSpace: public space { friend class universe; friend class generation; friend class newGeneration; friend class oldGeneration; friend class Monitor; friend class SelfMonitor; friend class abstract_monitor; friend class rSet; friend void space::compact(mapOop, space*&, oop*&, oop*&); private: oldSpace *next_space; inline bool reserveFree(); // called by oldGeneration oop* alloc_objs_first(fint size, oldSpace*& reserve_space, bool mustAllocate) { oop *p= alloc_objs_local(size); if (p) { if (mustAllocate || reserve_space || reserveFree()) return p; unalloc_objs_local(size); } return alloc_objs_second(size, reserve_space, mustAllocate); } oop* alloc_objs_and_bytes_first(fint size, fint bsize, char*& bytes, oldSpace*& reserve_space, bool mustAllocate) { oop *p= alloc_objs_and_bytes_local(size, bsize, bytes); if (p) { if (mustAllocate || reserve_space || reserveFree()) return p; unalloc_objs_and_bytes_local(size, bsize); } return alloc_objs_and_bytes_second(size, bsize, bytes, reserve_space, mustAllocate); } oop* alloc_objs_second(fint size, oldSpace*& reserve_space, bool mustAllocate); oop* alloc_objs_and_bytes_second(fint size, fint bsize, char*& bytes, oldSpace*& reserve_space, bool mustAllocate); oop* alloc_more_objs(fint size, oldSpace*& reserve_space, bool mustAllocate); oop* alloc_more_objs_and_bytes(fint size, fint bsize, char*& bytes, oldSpace*& reserve_space, bool mustAllocate); // constructors // allocates object space too; sets size to amount allocated, 0 if none // tries to start space at desiredAddress if non-zero. oldSpace(char* nm, int32 &size, caddr_t desiredAddress); // constructors which do not allocate object space oldSpace(char *nm, FILE *snap) : space(nm, snap) { next_space= NULL; } oldSpace(char *nm, char *bottom, char *top) : space(nm, bottom, top) { next_space= NULL; } bool scavenge_promotions(oop*&); bool scavenge_recorded_stores(); virtual void gc_unmark_contents(); void switch_pointers_by_card(oop from, oop to); void record_new_pointers(); };