/* * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ #ifndef SHARE_VM_MEMORY_METACHUNK_HPP #define SHARE_VM_MEMORY_METACHUNK_HPP #include "memory/metaspace/metabase.hpp" #include "memory/metaspace/metaspaceCommon.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" class MetachunkTest; namespace metaspace { namespace internals { class VirtualSpaceNode; // Metachunk - Quantum of allocation from a Virtualspace // Metachunks are reused (when freed are put on a global freelist) and // have no permanent association to a SpaceManager. // +--------------+ <- end --+ --+ // | | | | // | | | free | // | | | | // | | | | size | capacity // | | | | // | | <- top -- + | // | | | | // | | | used | // | | | | // | | | | // +--------------+ <- bottom --+ --+ 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 merge of smaller chunks origin_merge = 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_merge || origin == origin_split; } class Metachunk : public Metabase { friend class ::MetachunkTest; // The VirtualSpaceNode containing this chunk. VirtualSpaceNode* const _container; // Current allocation top. MetaWord* _top; // A 32bit sentinel for debugging purposes. enum { CHUNK_SENTINEL = 0x4d4554EF, // "MET" CHUNK_SENTINEL_INVALID = 0xFEEEEEEF }; uint32_t _sentinel; 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; ChunkOrigin _origin; int _use_count; MetaWord* initial_top() const { return (MetaWord*)this + overhead(); } MetaWord* top() const { return _top; } public: // Metachunks are allocated out of a MetadataVirtualSpace and // and use some of its space to describe itself (plus alignment // considerations). Metadata is allocated in the rest of the chunk. // This size is the overhead of maintaining the Metachunk within // the space. // Alignment of each allocation in the chunks. static size_t object_alignment(); // Size of the Metachunk header, in words, including alignment. static size_t overhead(); Metachunk(ChunkIndex chunktype, bool is_class, size_t word_size, VirtualSpaceNode* container); MetaWord* allocate(size_t word_size); VirtualSpaceNode* container() const { return _container; } MetaWord* bottom() const { return (MetaWord*) this; } // Reset top to bottom so chunk can be reused. void reset_empty() { _top = initial_top(); clear_next(); clear_prev(); } bool is_empty() { return _top == initial_top(); } // used (has been allocated) // free (available for future allocations) size_t word_size() const { return size(); } size_t used_word_size() const; size_t free_word_size() const; bool is_tagged_free() { return _is_tagged_free; } void set_is_tagged_free(bool v) { _is_tagged_free = v; } bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; } void print_on(outputStream* st) const; bool is_valid_sentinel() const { return _sentinel == CHUNK_SENTINEL; } void remove_sentinel() { _sentinel = CHUNK_SENTINEL_INVALID; } int get_use_count() const { return _use_count; } void inc_use_count() { _use_count ++; } ChunkOrigin get_origin() const { return _origin; } void set_origin(ChunkOrigin orig) { _origin = orig; } ChunkIndex get_chunk_type() const { return _chunk_type; } bool is_class() const { return _is_class; } DEBUG_ONLY(void mangle(juint word_value);) DEBUG_ONLY(void verify() const;) }; // Helper function that does a bunch of checks for a chunk. DEBUG_ONLY(void do_verify_chunk(Metachunk* chunk);) // Given a Metachunk, update its in-use information (both in the // chunk and the occupancy map). void do_update_in_use_info_for_chunk(Metachunk* chunk, bool inuse); } // namespace metaspace } // namespace internals #endif // SHARE_VM_MEMORY_METACHUNK_HPP