/* Sun-$Revision: 23.10 $ */ /* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University. See the LICENSE file for license information. */ # pragma interface // A generation is a bunch of spaces of similarly-aged objects class generation: public CHeapObj { friend class rSet; friend class universe; friend class memOopClass; // these call the alloc_ routines directly // friend oopsOop oopsOopClass::copy(fint, bool, oop, bool); // friend oopsOop oopsOopClass::insert(fint, fint, fint, bool, bool); // friend oopsOop oopsOopClass::remove(fint, fint, fint, bool, bool); friend class oopsOopClass; // friend byteVectorOop byteVectorOopClass::copy(fint, bool, oop, bool); // friend byteVectorOop byteVectorOopClass::insert(fint, fint, fint, // bool, bool); // friend byteVectorOop byteVectorOopClass::remove(fint, fint, fint, // bool, bool); friend class byteVectorOopClass; friend class oldGeneration; protected: // allocators; called by Memory and scavenger virtual oop* alloc_objs(fint size, bool mustAllocate= true) = 0; virtual oop* alloc_objs_and_bytes(fint size, fint bsize, char*& bytes, bool mustAllocate= true) = 0; // Minimum and maximum addresses, used by card marking code. // Must not overlap with address ranges of other generation(s). char *low_boundary; char *high_boundary; public: // space enquiries virtual int32 capacity() = 0; virtual int32 oops_used() = 0; virtual int32 bytes_used() = 0; virtual int32 oops_free() = 0; virtual int32 used() = 0; virtual int32 bytes_free() = 0; void print(); }; class MapList : public CHeapObj { public: MapList *next; slotsMapDeps *map; MapList(slotsMapDeps *m, MapList *n) { next= n; map= m; } }; class newGeneration: public generation { friend class rSet; friend class universe; friend class MemoryHistogram; friend class blockOopClass; friend class TrackObjectHeapInMonitor; friend class SelfMonitor; 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 class AllocationMonitor; #ifndef NOASM friend void itrace(fint); #endif private: newSpace* eden_space; newSpace* from_space; newSpace* to_space; // allocators; called by Memory and scavenger oop* alloc_objs(fint size, bool mustAllocate= true) { return eden_space->alloc_objs(size, mustAllocate); } oop* alloc_objs_and_bytes(fint size, fint bsize, char*& bytes, bool mustAllocate= true) { return eden_space->alloc_objs_and_bytes(size, bsize, bytes, mustAllocate); } public: // space enquiries int32 capacity(); int32 oops_used(); int32 bytes_used(); int32 oops_free(); int32 used(); int32 bytes_free(); void print(); void verify(); bool contains(void* p) { return (char*)p >= low_boundary && (char*)p < high_boundary; } bool objs_contains(void* p); private: // these are used to determine if an oop is in the new or old generation // when we have many similar tests to do; the first can be hoisted out of // the loop and then passed as the 2nd arg to is_new (for speed). // friend void OopNCode::check_store(oop, char*); friend class OopNCode; // friend nmethod::nmethod(AbstractCompiler*, nmln*, bool); friend class nmethod; char *boundary() { return high_boundary; } inline bool is_new(memOop p, char *boundary); // inlined in generation.dcl.h inline bool is_new(oop p, char *boundary); // ditto // constructor, called by Memory newGeneration(int32 &eden_size, int32 &surv_size, FILE *snap = NULL); // scavenger-related items oop* objs_scavenge_point; // always within to_space // these are actually called by Memory void prepare_for_scavenge(); bool scavenge_contents(); MapList* map_list; void init_map_list() { while (map_list != NULL) { MapList *n= map_list->next; delete map_list; map_list= n; } } friend class slotsMapDeps; friend class mapMap; // friend Map* Map::init(); // friend bool mapMap::verify(oop); void add_map(slotsMapDeps *m) { // add m to map chain if new if ((char*)m < high_boundary) map_list= new MapList(m, map_list); } bool has_map(slotsMapDeps *m); void adjust_maps(); void verify_new_maps(); void switch_pointers(oop from, oop to); void write_snapshot(FILE* file); }; class oldGeneration: public generation { friend class rSet; friend class universe; friend class SelfMonitor; #ifndef NOASM friend void itrace(fint); #endif friend class TrackObjectHeapInMonitor; friend oop expand_heap_prim(oop, smi); friend class oldSpace; // these alloc_ directly here friend stringOop create_string(fint); // friend stringOop stringOopClass::make_string(char*, fint, bool); friend class stringOopClass; // the following does not work with Metroworks precompiled headers friend oop* newSpace::alloc_more_objs(fint, bool); friend oop* newSpace::alloc_more_objs_and_bytes(fint, fint, char*&, bool); friend oop* oldSpace::alloc_more_objs(fint, oldSpace*&, bool); friend oop* oldSpace::alloc_more_objs_and_bytes(fint, fint, char*&, oldSpace*&, bool); friend bool oldSpace::reserveFree(); friend inline void handlePreemption(); private: unsigned nSpaces; oldSpace *first_space; oldSpace *last_space; oldSpace *reserve_space; // the space (other than first_space) with reserve // memory for scavenge oldSpace *old0; // the first space to be created caddr_t top_of_old_space; // keep track of where old space ends so that // old space addresses are all near each other // for signalling low space int32 VM_reserved_mem; public: int32 get_VM_reserved_mem() { return VM_reserved_mem; } private: int32 cached_free; void update_cached_free() { cached_free= bytes_free(); } int32 lowSpaceThreshold; public: int32 getLowSpaceThreshold() { return lowSpaceThreshold; } void setLowSpaceThreshold(int32 newLST) { assert(newLST >= VM_reserved_mem, "red line too low"); lowSpaceThreshold= newLST; lowOnSpace= false; // let next alloc trip if already over the line needToSignalLowOnSpace= false; } bool lowOnSpace; bool needToSignalLowOnSpace; void check_for_end_of_low_space(); inline void check_for_low_space(); int expand(int32 size); void update_caches(bool postScavenge); // allocators; called by Memory and scavenger oop* alloc_objs(fint size, bool mustAllocate= true) { oop *p= first_space->alloc_objs_first(size, reserve_space, mustAllocate); if (p) { # ifdef GENERATE_ASSERTIONS if (CheckAssertions && p == (oop*)catchThisOne) { warning1("oldGeneration::alloc_objs caught 0x%lx", p); } # endif cached_free -= size*oopSize; check_for_low_space(); } return p; } oop* alloc_objs_and_bytes(fint size, fint bsize, char*& bytes, bool mustAllocate= true) { oop *p= first_space->alloc_objs_and_bytes_first(size, bsize, bytes, reserve_space, mustAllocate); if (p) { # ifdef GENERATE_ASSERTIONS if (CheckAssertions && (p == (oop*)catchThisOne || bytes == (char*)catchThisOne)) { warning1("oldGeneration::alloc_objs_and_bytes caught 0x%lx", catchThisOne); } # endif cached_free -= (size + bsize)*oopSize; check_for_low_space(); } return p; } // constructors, called by Memory oldGeneration( int32 initial_size, int32 reserved_amount); oldGeneration(FILE* snap, int32 initial_size, int32 reserved_amount); // only called at startup friend void create_initial_strings(oop); char* empty_bytes_addr() { assert(first_space != NULL && first_space->next_space == NULL, "empty_bytes_addr called too late"); return first_space->bytesStart(); } public: bool objs_contains(void* p); // space enquiries int32 capacity(); int32 oops_used(); int32 bytes_used(); int32 oops_free(); int32 used(); int32 bytes_free(); void print(); void verify(); bool contains(void* p); private: // scavenger-related items; only meaningful during scavenges. oldSpace *scavenge_space; oop* objs_scavenge_point1; // always within first_space oop* objs_scavenge_point2; // always within scavenge_space oldSpace* biggest_free_space(oldSpace *f); // these are actually called by Memory void prepare_for_scavenge(); bool scavenge_promotions(); void cleanup_after_scavenge(); void switch_pointers(oop from, oop to); void switch_pointers_by_card(oop from, oop to); void reselect_scavenge_space(); void reselect_reserve_space(); bool split_scavenge; // set to true if scavenge goes across two spaces space *scavenge_space_for(fint size, fint bsize) { if (first_space->would_fit(size, bsize)) return first_space; else { assert(scavenge_space->would_fit(size, bsize), "scavenger ran out of space"); split_scavenge= true; return scavenge_space; } } void sorted_space_list(oldSpace *sp[], int (*cmp)(oldSpace**, oldSpace**)); void prepare_for_compaction(); void first_space_full(); void append_space(oldSpace *last); void read_snapshot(FILE* file); bool write_only_old0; void set_write_only_old0(); void write_snapshot(FILE* file); void coalesce_spaces(); void record_new_pointers(); }; int addr_cmp(oldSpace **s1, oldSpace **s2); smi set_memory_low_space_threshold_prim(oop rcvr, smi newLST, void *FH); // ensure that you surround the call with {} to prevent s leaking out! #define FOR_EACH_OLD_SPACE(s) \ for (oldSpace *s= Memory->old_gen->first_space; \ s != NULL; \ s= s->next_space)