1 /* 2 * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_JFR_UTILITIES_JFRBIGENDIAN_HPP 26 #define SHARE_JFR_UTILITIES_JFRBIGENDIAN_HPP 27 28 #include "memory/allocation.hpp" 29 #include "utilities/bytes.hpp" 30 #include "utilities/macros.hpp" 31 32 #ifndef VM_LITTLE_ENDIAN 33 # define bigendian_16(x) (x) 34 # define bigendian_32(x) (x) 35 # define bigendian_64(x) (x) 36 #else 37 # define bigendian_16(x) Bytes::swap_u2(x) 38 # define bigendian_32(x) Bytes::swap_u4(x) 39 # define bigendian_64(x) Bytes::swap_u8(x) 40 #endif 41 42 class JfrBigEndian : AllStatic { 43 private: 44 template <typename T> 45 static T read_bytes(const address location); 46 template <typename T> 47 static T read_unaligned(const address location); 48 public: 49 static bool platform_supports_unaligned_reads(void); 50 static bool is_aligned(const void* location, size_t size); 51 template <typename T> 52 static T read(const void* location); 53 }; 54 55 inline bool JfrBigEndian::is_aligned(const void* location, size_t size) { 56 assert(size <= sizeof(u8), "just checking"); 57 if (size == sizeof(u1)) { 58 return true; 59 } 60 // check address alignment for datum access 61 return (((uintptr_t)location & (size -1)) == 0); 62 } 63 64 template <> 65 inline u1 JfrBigEndian::read_bytes(const address location) { 66 return (*location & 0xFF); 67 } 68 69 template <> 70 inline u2 JfrBigEndian::read_bytes(const address location) { 71 return Bytes::get_Java_u2(location); 72 } 73 74 template <> 75 inline u4 JfrBigEndian::read_bytes(const address location) { 76 return Bytes::get_Java_u4(location); 77 } 78 79 template <> 80 inline u8 JfrBigEndian::read_bytes(const address location) { 81 return Bytes::get_Java_u8(location); 82 } 83 84 template <typename T> 85 inline T JfrBigEndian::read_unaligned(const address location) { 86 assert(location != NULL, "just checking"); 87 switch (sizeof(T)) { 88 case sizeof(u1) : 89 return read_bytes<u1>(location); 90 case sizeof(u2): 91 return read_bytes<u2>(location); 92 case sizeof(u4): 93 return read_bytes<u4>(location); 94 case sizeof(u8): 95 return read_bytes<u8>(location); 96 default: 97 assert(false, "not reach"); 98 } 99 return 0; 100 } 101 102 inline bool JfrBigEndian::platform_supports_unaligned_reads(void) { 103 #if defined(IA32) || defined(AMD64) || defined(PPC) || defined(S390) 104 return true; 105 #elif defined(ARM) || defined(AARCH64) || defined(RISCV) 106 return false; 107 #else 108 #warning "Unconfigured platform" 109 return false; 110 #endif 111 } 112 113 template<typename T> 114 inline T JfrBigEndian::read(const void* location) { 115 assert(location != NULL, "just checking"); 116 assert(sizeof(T) <= sizeof(u8), "no support for arbitrary sizes"); 117 if (sizeof(T) == sizeof(u1)) { 118 return *(T*)location; 119 } 120 if (is_aligned(location, sizeof(T)) || platform_supports_unaligned_reads()) { 121 // fastest case 122 switch (sizeof(T)) { 123 case sizeof(u1): 124 return *(T*)location; 125 case sizeof(u2): 126 return bigendian_16(*(T*)(location)); 127 case sizeof(u4): 128 return bigendian_32(*(T*)(location)); 129 case sizeof(u8): 130 return bigendian_64(*(T*)(location)); 131 } 132 } 133 return read_unaligned<T>((const address)location); 134 } 135 136 #endif // SHARE_JFR_UTILITIES_JFRBIGENDIAN_HPP