duke@435: /* trims@1907: * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: duke@435: #define ARENA_ALIGN_M1 (((size_t)(ARENA_AMALLOC_ALIGNMENT)) - 1) duke@435: #define ARENA_ALIGN_MASK (~((size_t)ARENA_ALIGN_M1)) duke@435: #define ARENA_ALIGN(x) ((((size_t)(x)) + ARENA_ALIGN_M1) & ARENA_ALIGN_MASK) duke@435: duke@435: // All classes in the virtual machine must be subclassed duke@435: // by one of the following allocation classes: duke@435: // duke@435: // For objects allocated in the resource area (see resourceArea.hpp). duke@435: // - ResourceObj duke@435: // duke@435: // For objects allocated in the C-heap (managed by: free & malloc). duke@435: // - CHeapObj duke@435: // duke@435: // For objects allocated on the stack. duke@435: // - StackObj duke@435: // duke@435: // For embedded objects. duke@435: // - ValueObj duke@435: // duke@435: // For classes used as name spaces. duke@435: // - AllStatic duke@435: // duke@435: // The printable subclasses are used for debugging and define virtual duke@435: // member functions for printing. Classes that avoid allocating the duke@435: // vtbl entries in the objects should therefore not be the printable duke@435: // subclasses. duke@435: // duke@435: // The following macros and function should be used to allocate memory duke@435: // directly in the resource area or in the C-heap: duke@435: // duke@435: // NEW_RESOURCE_ARRAY(type,size) duke@435: // NEW_RESOURCE_OBJ(type) duke@435: // NEW_C_HEAP_ARRAY(type,size) duke@435: // NEW_C_HEAP_OBJ(type) duke@435: // char* AllocateHeap(size_t size, const char* name); duke@435: // void FreeHeap(void* p); duke@435: // duke@435: // C-heap allocation can be traced using +PrintHeapAllocation. duke@435: // malloc and free should therefore never called directly. duke@435: duke@435: // Base class for objects allocated in the C-heap. duke@435: duke@435: // In non product mode we introduce a super class for all allocation classes duke@435: // that supports printing. duke@435: // We avoid the superclass in product mode since some C++ compilers add duke@435: // a word overhead for empty super classes. duke@435: duke@435: #ifdef PRODUCT duke@435: #define ALLOCATION_SUPER_CLASS_SPEC duke@435: #else duke@435: #define ALLOCATION_SUPER_CLASS_SPEC : public AllocatedObj duke@435: class AllocatedObj { duke@435: public: duke@435: // Printing support duke@435: void print() const; duke@435: void print_value() const; duke@435: duke@435: virtual void print_on(outputStream* st) const; duke@435: virtual void print_value_on(outputStream* st) const; duke@435: }; duke@435: #endif duke@435: duke@435: class CHeapObj ALLOCATION_SUPER_CLASS_SPEC { duke@435: public: duke@435: void* operator new(size_t size); duke@435: void operator delete(void* p); duke@435: void* new_array(size_t size); duke@435: }; duke@435: duke@435: // Base class for objects allocated on the stack only. duke@435: // Calling new or delete will result in fatal error. duke@435: duke@435: class StackObj ALLOCATION_SUPER_CLASS_SPEC { duke@435: public: duke@435: void* operator new(size_t size); duke@435: void operator delete(void* p); duke@435: }; duke@435: duke@435: // Base class for objects used as value objects. duke@435: // Calling new or delete will result in fatal error. duke@435: // duke@435: // Portability note: Certain compilers (e.g. gcc) will duke@435: // always make classes bigger if it has a superclass, even duke@435: // if the superclass does not have any virtual methods or duke@435: // instance fields. The HotSpot implementation relies on this duke@435: // not to happen. So never make a ValueObj class a direct subclass duke@435: // of this object, but use the VALUE_OBJ_CLASS_SPEC class instead, e.g., duke@435: // like this: duke@435: // duke@435: // class A VALUE_OBJ_CLASS_SPEC { duke@435: // ... duke@435: // } duke@435: // duke@435: // With gcc and possible other compilers the VALUE_OBJ_CLASS_SPEC can duke@435: // be defined as a an empty string "". duke@435: // duke@435: class _ValueObj { duke@435: public: duke@435: void* operator new(size_t size); duke@435: void operator delete(void* p); duke@435: }; duke@435: duke@435: // Base class for classes that constitute name spaces. duke@435: duke@435: class AllStatic { duke@435: public: duke@435: AllStatic() { ShouldNotCallThis(); } duke@435: ~AllStatic() { ShouldNotCallThis(); } duke@435: }; duke@435: duke@435: duke@435: //------------------------------Chunk------------------------------------------ duke@435: // Linked list of raw memory chunks duke@435: class Chunk: public CHeapObj { duke@435: protected: duke@435: Chunk* _next; // Next Chunk in list duke@435: const size_t _len; // Size of this Chunk duke@435: public: duke@435: void* operator new(size_t size, size_t length); duke@435: void operator delete(void* p); duke@435: Chunk(size_t length); duke@435: duke@435: enum { duke@435: // default sizes; make them slightly smaller than 2**k to guard against duke@435: // buddy-system style malloc implementations duke@435: #ifdef _LP64 duke@435: slack = 40, // [RGV] Not sure if this is right, but make it duke@435: // a multiple of 8. duke@435: #else duke@435: slack = 20, // suspected sizeof(Chunk) + internal malloc headers duke@435: #endif duke@435: duke@435: init_size = 1*K - slack, // Size of first chunk duke@435: medium_size= 10*K - slack, // Size of medium-sized chunk duke@435: size = 32*K - slack, // Default size of an Arena chunk (following the first) duke@435: non_pool_size = init_size + 32 // An initial size which is not one of above duke@435: }; duke@435: duke@435: void chop(); // Chop this chunk duke@435: void next_chop(); // Chop next chunk duke@435: static size_t aligned_overhead_size(void) { return ARENA_ALIGN(sizeof(Chunk)); } duke@435: duke@435: size_t length() const { return _len; } duke@435: Chunk* next() const { return _next; } duke@435: void set_next(Chunk* n) { _next = n; } duke@435: // Boundaries of data area (possibly unused) duke@435: char* bottom() const { return ((char*) this) + aligned_overhead_size(); } duke@435: char* top() const { return bottom() + _len; } duke@435: bool contains(char* p) const { return bottom() <= p && p <= top(); } duke@435: duke@435: // Start the chunk_pool cleaner task duke@435: static void start_chunk_pool_cleaner_task(); duke@435: }; duke@435: duke@435: duke@435: //------------------------------Arena------------------------------------------ duke@435: // Fast allocation of memory duke@435: class Arena: public CHeapObj { duke@435: protected: duke@435: friend class ResourceMark; duke@435: friend class HandleMark; duke@435: friend class NoHandleMark; duke@435: Chunk *_first; // First chunk duke@435: Chunk *_chunk; // current chunk duke@435: char *_hwm, *_max; // High water mark and max in current chunk duke@435: void* grow(size_t x); // Get a new Chunk of at least size x duke@435: NOT_PRODUCT(size_t _size_in_bytes;) // Size of arena (used for memory usage tracing) duke@435: NOT_PRODUCT(static size_t _bytes_allocated;) // total #bytes allocated since start duke@435: friend class AllocStats; duke@435: debug_only(void* malloc(size_t size);) duke@435: debug_only(void* internal_malloc_4(size_t x);) duke@435: public: duke@435: Arena(); duke@435: Arena(size_t init_size); duke@435: Arena(Arena *old); duke@435: ~Arena(); duke@435: void destruct_contents(); duke@435: char* hwm() const { return _hwm; } duke@435: duke@435: // Fast allocate in the arena. Common case is: pointer test + increment. duke@435: void* Amalloc(size_t x) { duke@435: assert(is_power_of_2(ARENA_AMALLOC_ALIGNMENT) , "should be a power of 2"); duke@435: x = ARENA_ALIGN(x); duke@435: debug_only(if (UseMallocOnly) return malloc(x);) duke@435: NOT_PRODUCT(_bytes_allocated += x); duke@435: if (_hwm + x > _max) { duke@435: return grow(x); duke@435: } else { duke@435: char *old = _hwm; duke@435: _hwm += x; duke@435: return old; duke@435: } duke@435: } duke@435: // Further assume size is padded out to words duke@435: void *Amalloc_4(size_t x) { duke@435: assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); duke@435: debug_only(if (UseMallocOnly) return malloc(x);) duke@435: NOT_PRODUCT(_bytes_allocated += x); duke@435: if (_hwm + x > _max) { duke@435: return grow(x); duke@435: } else { duke@435: char *old = _hwm; duke@435: _hwm += x; duke@435: return old; duke@435: } duke@435: } duke@435: duke@435: // Allocate with 'double' alignment. It is 8 bytes on sparc. duke@435: // In other cases Amalloc_D() should be the same as Amalloc_4(). duke@435: void* Amalloc_D(size_t x) { duke@435: assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); duke@435: debug_only(if (UseMallocOnly) return malloc(x);) duke@435: #if defined(SPARC) && !defined(_LP64) duke@435: #define DALIGN_M1 7 duke@435: size_t delta = (((size_t)_hwm + DALIGN_M1) & ~DALIGN_M1) - (size_t)_hwm; duke@435: x += delta; duke@435: #endif duke@435: NOT_PRODUCT(_bytes_allocated += x); duke@435: if (_hwm + x > _max) { duke@435: return grow(x); // grow() returns a result aligned >= 8 bytes. duke@435: } else { duke@435: char *old = _hwm; duke@435: _hwm += x; duke@435: #if defined(SPARC) && !defined(_LP64) duke@435: old += delta; // align to 8-bytes duke@435: #endif duke@435: return old; duke@435: } duke@435: } duke@435: duke@435: // Fast delete in area. Common case is: NOP (except for storage reclaimed) duke@435: void Afree(void *ptr, size_t size) { duke@435: #ifdef ASSERT duke@435: if (ZapResourceArea) memset(ptr, badResourceValue, size); // zap freed memory duke@435: if (UseMallocOnly) return; duke@435: #endif duke@435: if (((char*)ptr) + size == _hwm) _hwm = (char*)ptr; duke@435: } duke@435: duke@435: void *Arealloc( void *old_ptr, size_t old_size, size_t new_size ); duke@435: duke@435: // Move contents of this arena into an empty arena duke@435: Arena *move_contents(Arena *empty_arena); duke@435: duke@435: // Determine if pointer belongs to this Arena or not. duke@435: bool contains( const void *ptr ) const; duke@435: duke@435: // Total of all chunks in use (not thread-safe) duke@435: size_t used() const; duke@435: duke@435: // Total # of bytes used duke@435: size_t size_in_bytes() const NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0; duke@435: void set_size_in_bytes(size_t size) NOT_PRODUCT({ _size_in_bytes = size; }) PRODUCT_RETURN; duke@435: static void free_malloced_objects(Chunk* chunk, char* hwm, char* max, char* hwm2) PRODUCT_RETURN; duke@435: static void free_all(char** start, char** end) PRODUCT_RETURN; duke@435: duke@435: private: duke@435: // Reset this Arena to empty, access will trigger grow if necessary duke@435: void reset(void) { duke@435: _first = _chunk = NULL; duke@435: _hwm = _max = NULL; duke@435: } duke@435: }; duke@435: duke@435: // One of the following macros must be used when allocating duke@435: // an array or object from an arena duke@435: #define NEW_ARENA_ARRAY(arena, type, size)\ duke@435: (type*) arena->Amalloc((size) * sizeof(type)) duke@435: duke@435: #define REALLOC_ARENA_ARRAY(arena, type, old, old_size, new_size)\ duke@435: (type*) arena->Arealloc((char*)(old), (old_size) * sizeof(type), (new_size) * sizeof(type) ) duke@435: duke@435: #define FREE_ARENA_ARRAY(arena, type, old, size)\ duke@435: arena->Afree((char*)(old), (size) * sizeof(type)) duke@435: duke@435: #define NEW_ARENA_OBJ(arena, type)\ duke@435: NEW_ARENA_ARRAY(arena, type, 1) duke@435: duke@435: duke@435: //%note allocation_1 duke@435: extern char* resource_allocate_bytes(size_t size); duke@435: extern char* resource_allocate_bytes(Thread* thread, size_t size); duke@435: extern char* resource_reallocate_bytes( char *old, size_t old_size, size_t new_size); duke@435: extern void resource_free_bytes( char *old, size_t size ); duke@435: duke@435: //---------------------------------------------------------------------- duke@435: // Base class for objects allocated in the resource area per default. duke@435: // Optionally, objects may be allocated on the C heap with duke@435: // new(ResourceObj::C_HEAP) Foo(...) or in an Arena with new (&arena) duke@435: // ResourceObj's can be allocated within other objects, but don't use duke@435: // new or delete (allocation_type is unknown). If new is used to allocate, duke@435: // use delete to deallocate. duke@435: class ResourceObj ALLOCATION_SUPER_CLASS_SPEC { duke@435: public: duke@435: enum allocation_type { UNKNOWN = 0, C_HEAP, RESOURCE_AREA, ARENA }; duke@435: #ifdef ASSERT duke@435: private: duke@435: allocation_type _allocation; duke@435: public: duke@435: bool allocated_on_C_heap() { return _allocation == C_HEAP; } duke@435: #endif // ASSERT duke@435: duke@435: public: duke@435: void* operator new(size_t size, allocation_type type); duke@435: void* operator new(size_t size, Arena *arena) { duke@435: address res = (address)arena->Amalloc(size); duke@435: // Set allocation type in the resource object duke@435: DEBUG_ONLY(((ResourceObj *)res)->_allocation = ARENA;) duke@435: return res; duke@435: } duke@435: void* operator new(size_t size) { duke@435: address res = (address)resource_allocate_bytes(size); duke@435: // Set allocation type in the resource object duke@435: DEBUG_ONLY(((ResourceObj *)res)->_allocation = RESOURCE_AREA;) duke@435: return res; duke@435: } ysr@777: void* operator new(size_t size, void* where, allocation_type type) { ysr@777: void* res = where; ysr@777: // Set allocation type in the resource object ysr@777: DEBUG_ONLY(((ResourceObj *)res)->_allocation = type;) ysr@777: return res; ysr@777: } duke@435: void operator delete(void* p); duke@435: }; duke@435: duke@435: // One of the following macros must be used when allocating an array duke@435: // or object to determine whether it should reside in the C heap on in duke@435: // the resource area. duke@435: duke@435: #define NEW_RESOURCE_ARRAY(type, size)\ duke@435: (type*) resource_allocate_bytes((size) * sizeof(type)) duke@435: duke@435: #define NEW_RESOURCE_ARRAY_IN_THREAD(thread, type, size)\ duke@435: (type*) resource_allocate_bytes(thread, (size) * sizeof(type)) duke@435: duke@435: #define REALLOC_RESOURCE_ARRAY(type, old, old_size, new_size)\ duke@435: (type*) resource_reallocate_bytes((char*)(old), (old_size) * sizeof(type), (new_size) * sizeof(type) ) duke@435: duke@435: #define FREE_RESOURCE_ARRAY(type, old, size)\ duke@435: resource_free_bytes((char*)(old), (size) * sizeof(type)) duke@435: duke@435: #define FREE_FAST(old)\ duke@435: /* nop */ duke@435: duke@435: #define NEW_RESOURCE_OBJ(type)\ duke@435: NEW_RESOURCE_ARRAY(type, 1) duke@435: duke@435: #define NEW_C_HEAP_ARRAY(type, size)\ duke@435: (type*) (AllocateHeap((size) * sizeof(type), XSTR(type) " in " __FILE__)) duke@435: duke@435: #define REALLOC_C_HEAP_ARRAY(type, old, size)\ duke@435: (type*) (ReallocateHeap((char*)old, (size) * sizeof(type), XSTR(type) " in " __FILE__)) duke@435: duke@435: #define FREE_C_HEAP_ARRAY(type,old) \ duke@435: FreeHeap((char*)(old)) duke@435: duke@435: #define NEW_C_HEAP_OBJ(type)\ duke@435: NEW_C_HEAP_ARRAY(type, 1) duke@435: duke@435: extern bool warn_new_operator; duke@435: duke@435: // for statistics duke@435: #ifndef PRODUCT duke@435: class AllocStats : StackObj { duke@435: int start_mallocs, start_frees; duke@435: size_t start_malloc_bytes, start_res_bytes; duke@435: public: duke@435: AllocStats(); duke@435: duke@435: int num_mallocs(); // since creation of receiver duke@435: size_t alloc_bytes(); duke@435: size_t resource_bytes(); duke@435: int num_frees(); duke@435: void print(); duke@435: }; duke@435: #endif duke@435: duke@435: duke@435: //------------------------------ReallocMark--------------------------------- duke@435: // Code which uses REALLOC_RESOURCE_ARRAY should check an associated duke@435: // ReallocMark, which is declared in the same scope as the reallocated duke@435: // pointer. Any operation that could __potentially__ cause a reallocation duke@435: // should check the ReallocMark. duke@435: class ReallocMark: public StackObj { duke@435: protected: duke@435: NOT_PRODUCT(int _nesting;) duke@435: duke@435: public: duke@435: ReallocMark() PRODUCT_RETURN; duke@435: void check() PRODUCT_RETURN; duke@435: };