--- old/src/hotspot/share/memory/metachunk.hpp 2018-02-26 14:42:49.364178000 +0100 +++ new/src/hotspot/share/memory/metachunk.hpp 2018-02-26 14:42:48.985148000 +0100 @@ -94,16 +94,89 @@ // | | | | // +--------------+ <- bottom --+ --+ +// ChunkIndex (todo: rename?) defines the type of chunk. Chunk types +// differ by size: specialized < small < medium, chunks larger than +// medium are humongous chunks of varying size. +enum ChunkIndex { + ZeroIndex = 0, + SpecializedIndex = ZeroIndex, + SmallIndex = SpecializedIndex + 1, + MediumIndex = SmallIndex + 1, + HumongousIndex = MediumIndex + 1, + NumberOfFreeLists = 3, + NumberOfInUseLists = 4 +}; + +// Utility functions. +size_t get_size_for_nonhumongous_chunktype(ChunkIndex chunk_type, bool is_class); +ChunkIndex get_chunk_type_by_size(size_t size, bool is_class); + +// Returns a descriptive name for a chunk type. +const char* chunk_size_name(ChunkIndex index); + +// Verify chunk type. +inline bool is_valid_chunktype(ChunkIndex index) { + return index == SpecializedIndex || index == SmallIndex || + index == MediumIndex || index == HumongousIndex; +} + +inline bool is_valid_nonhumongous_chunktype(ChunkIndex index) { + return is_valid_chunktype(index) && index != HumongousIndex; +} + +#ifdef ASSERT + +enum ChunkOrigin { + // Chunk normally born (via take_from_committed) + origin_normal = 1, + // Chunk was born as padding chunk + origin_pad = 2, + // Chunk was born as leftover chunk in VirtualSpaceNode::retire + origin_leftover = 3, + // Chunk was born as result of a coalescation of smaller chunks + origin_coalescation = 4, + // Chunk was born as result of a split of a larger chunk + origin_split = 5, + + origin_minimum = origin_normal, + origin_maximum = origin_split, + origins_count = origin_maximum + 1 +}; + +inline bool is_valid_chunkorigin(ChunkOrigin origin) { + return origin == origin_normal || + origin == origin_pad || + origin == origin_leftover || + origin == origin_coalescation || + origin == origin_split; +} + +#endif + class Metachunk : public Metabase { friend class MetachunkTest; // The VirtualSpaceNode containing this chunk. - VirtualSpaceNode* _container; + VirtualSpaceNode* const _container; // Current allocation top. MetaWord* _top; +#ifdef ASSERT + // A 32bit sentinel for debugging purposes. +#define CHUNK_SENTINEL 0x4d4554EF // "MET" +#define CHUNK_SENTINEL_INVALID 0xFEEEEEEF + uint32_t _sentinel; +#endif + const ChunkIndex _chunk_type; + const bool _is_class; + // Whether the chunk is free (in freelist) or in use by some class loader. bool _is_tagged_free; +#ifdef ASSERT + ChunkOrigin _origin; + int _use_count; +#endif + MetaWord* initial_top() const { return (MetaWord*)this + overhead(); } MetaWord* top() const { return _top; } @@ -120,7 +193,7 @@ // Size of the Metachunk header, including alignment. static size_t overhead(); - Metachunk(size_t word_size , VirtualSpaceNode* container); + Metachunk(ChunkIndex chunktype, bool is_class, size_t word_size, VirtualSpaceNode* container); MetaWord* allocate(size_t word_size); @@ -143,12 +216,28 @@ bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; } -#ifndef PRODUCT +#ifdef ASSERT void mangle(juint word_value); #endif void print_on(outputStream* st) const; + +#ifdef ASSERT void verify(); + + bool is_valid_sentinel() const { return _sentinel == CHUNK_SENTINEL; } + void remove_sentinel() { _sentinel = CHUNK_SENTINEL_INVALID; } + + ChunkOrigin get_origin() const { return _origin; } + void set_origin(ChunkOrigin orig) { _origin = orig; } + + int get_use_count() const { return _use_count; } + void inc_use_count() { _use_count ++; } +#endif + + ChunkIndex get_chunk_type() const { return _chunk_type; } + bool is_class() const { return _is_class; } + }; // Metablock is the unit of allocation from a Chunk.