Path: blob/master/src/hotspot/share/utilities/align.hpp
40950 views
/*1* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_UTILITIES_ALIGN_HPP25#define SHARE_UTILITIES_ALIGN_HPP2627#include "metaprogramming/enableIf.hpp"28#include "utilities/debug.hpp"29#include "utilities/globalDefinitions.hpp"30#include "utilities/powerOfTwo.hpp"31#include <type_traits>3233// Compute mask to use for aligning to or testing alignment.34// The alignment must be a power of 2. Returns alignment - 1, which is35// a mask with all bits set below alignment's single bit.36template<typename T, ENABLE_IF(std::is_integral<T>::value)>37static constexpr T alignment_mask(T alignment) {38assert(is_power_of_2(alignment),39"must be a power of 2: " UINT64_FORMAT, (uint64_t)alignment);40return alignment - 1;41}4243// Some "integral" constant alignments are defined via enum.44template<typename T, ENABLE_IF(std::is_enum<T>::value)>45static constexpr auto alignment_mask(T alignment) {46return alignment_mask(static_cast<std::underlying_type_t<T>>(alignment));47}4849// Align integers and check for alignment.50// The is_integral filtering here is not for disambiguation with the T*51// overloads; if those match then they are a better match. Rather, the52// is_integral filtering is to prevent back-sliding on the use of enums53// as "integral" constants that need aligning.5455template<typename T, typename A, ENABLE_IF(std::is_integral<T>::value)>56constexpr bool is_aligned(T size, A alignment) {57return (size & alignment_mask(alignment)) == 0;58}5960template<typename T, typename A, ENABLE_IF(std::is_integral<T>::value)>61constexpr T align_down(T size, A alignment) {62// Convert mask to T before logical_not. Otherwise, if alignment is unsigned63// and smaller than T, the result of the logical_not will be zero-extended64// by integral promotion, and upper bits of size will be discarded.65T result = size & ~T(alignment_mask(alignment));66assert(is_aligned(result, alignment),67"must be aligned: " UINT64_FORMAT, (uint64_t)result);68return result;69}7071template<typename T, typename A, ENABLE_IF(std::is_integral<T>::value)>72constexpr T align_up(T size, A alignment) {73T adjusted = size + alignment_mask(alignment);74return align_down(adjusted, alignment);75}7677// Align down with a lower bound. If the aligning results in 0, return 'alignment'.78template <typename T, typename A>79constexpr T align_down_bounded(T size, A alignment) {80T aligned_size = align_down(size, alignment);81return (aligned_size > 0) ? aligned_size : T(alignment);82}8384// Align pointers and check for alignment.8586template <typename T, typename A>87inline T* align_up(T* ptr, A alignment) {88return (T*)align_up((uintptr_t)ptr, alignment);89}9091template <typename T, typename A>92inline T* align_down(T* ptr, A alignment) {93return (T*)align_down((uintptr_t)ptr, alignment);94}9596template <typename T, typename A>97inline bool is_aligned(T* ptr, A alignment) {98return is_aligned((uintptr_t)ptr, alignment);99}100101// Align metaspace objects by rounding up to natural word boundary102template <typename T>103inline T align_metadata_size(T size) {104return align_up(size, 1);105}106107// Align objects in the Java Heap by rounding up their size, in HeapWord units.108template <typename T>109inline T align_object_size(T word_size) {110return align_up(word_size, MinObjAlignment);111}112113inline bool is_object_aligned(size_t word_size) {114return is_aligned(word_size, MinObjAlignment);115}116117inline bool is_object_aligned(const void* addr) {118return is_aligned(addr, MinObjAlignmentInBytes);119}120121// Pad out certain offsets to jlong alignment, in HeapWord units.122template <typename T>123constexpr T align_object_offset(T offset) {124return align_up(offset, HeapWordsPerLong);125}126127// Clamp an address to be within a specific page128// 1. If addr is on the page it is returned as is129// 2. If addr is above the page_address the start of the *next* page will be returned130// 3. Otherwise, if addr is below the page_address the start of the page will be returned131template <typename T>132inline T* clamp_address_in_page(T* addr, T* page_address, size_t page_size) {133if (align_down(addr, page_size) == align_down(page_address, page_size)) {134// address is in the specified page, just return it as is135return addr;136} else if (addr > page_address) {137// address is above specified page, return start of next page138return align_down(page_address, page_size) + page_size;139} else {140// address is below specified page, return start of page141return align_down(page_address, page_size);142}143}144145#endif // SHARE_UTILITIES_ALIGN_HPP146147148