1 /* 2 * Copyright (c) 2012, 2018, 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_VM_JFR_UTILITIES_JFRBIGENDIAN_HPP 26 #define SHARE_VM_JFR_UTILITIES_JFRBIGENDIAN_HPP 27 28 #include "memory/allocation.hpp" 29 #include "utilities/macros.hpp" 30 #ifdef TARGET_ARCH_x86 31 # include "bytes_x86.hpp" 32 #endif 33 #ifdef TARGET_ARCH_sparc 34 # include "bytes_sparc.hpp" 35 #endif 36 #ifdef TARGET_ARCH_zero 37 # include "bytes_zero.hpp" 38 #endif 39 #ifdef TARGET_ARCH_arm 40 # include "bytes_arm.hpp" 41 #endif 42 #ifdef TARGET_ARCH_ppc 43 # include "bytes_ppc.hpp" 44 #endif 45 46 #ifndef VM_LITTLE_ENDIAN 47 # define bigendian_16(x) (x) 48 # define bigendian_32(x) (x) 49 # define bigendian_64(x) (x) 50 #else 51 # define bigendian_16(x) Bytes::swap_u2(x) 52 # define bigendian_32(x) Bytes::swap_u4(x) 53 # define bigendian_64(x) Bytes::swap_u8(x) 54 #endif 55 56 class JfrBigEndian : AllStatic { 57 private: 58 template <typename T> 59 static T read_bytes(const address location); 60 template <typename T> 61 static T read_unaligned(const address location); 62 public: 63 static bool platform_supports_unaligned_reads(void); 64 static bool is_aligned(const void* location, size_t size); 65 template <typename T> 66 static T read(const void* location); 67 }; 68 69 inline bool JfrBigEndian::is_aligned(const void* location, size_t size) { 70 assert(size <= sizeof(u8), "just checking"); 71 if (size == sizeof(u1)) { 72 return true; 73 } 74 // check address alignment for datum access 75 return (((uintptr_t)location & (size -1)) == 0); 76 } 77 78 template <> 79 inline u1 JfrBigEndian::read_bytes(const address location) { 80 return (*location & 0xFF); 81 } 82 83 template <> 84 inline u2 JfrBigEndian::read_bytes(const address location) { 85 return Bytes::get_Java_u2(location); 86 } 87 88 template <> 89 inline u4 JfrBigEndian::read_bytes(const address location) { 90 return Bytes::get_Java_u4(location); 91 } 92 93 template <> 94 inline u8 JfrBigEndian::read_bytes(const address location) { 95 return Bytes::get_Java_u8(location); 96 } 97 98 template <typename T> 99 inline T JfrBigEndian::read_unaligned(const address location) { 100 assert(location != NULL, "just checking"); 101 switch (sizeof(T)) { 102 case sizeof(u1) : 103 return read_bytes<u1>(location); 104 case sizeof(u2): 105 return read_bytes<u2>(location); 106 case sizeof(u4): 107 return read_bytes<u4>(location); 108 case sizeof(u8): 109 return read_bytes<u8>(location); 110 default: 111 assert(false, "not reach"); 112 } 113 return 0; 114 } 115 116 inline bool JfrBigEndian::platform_supports_unaligned_reads(void) { 117 #if defined(IA32) || defined(AMD64) || defined(PPC) || defined(S390) 118 return true; 119 #elif defined(SPARC) || defined(ARM) || defined(AARCH64) 120 return false; 121 #else 122 #warning "Unconfigured platform" 123 return false; 124 #endif 125 } 126 127 template<typename T> 128 inline T JfrBigEndian::read(const void* location) { 129 assert(location != NULL, "just checking"); 130 assert(sizeof(T) <= sizeof(u8), "no support for arbitrary sizes"); 131 if (sizeof(T) == sizeof(u1)) { 132 return *(T*)location; 133 } 134 if (is_aligned(location, sizeof(T)) || platform_supports_unaligned_reads()) { 135 // fastest case 136 switch (sizeof(T)) { 137 case sizeof(u1): 138 return *(T*)location; 139 case sizeof(u2): 140 return bigendian_16(*(T*)(location)); 141 case sizeof(u4): 142 return bigendian_32(*(T*)(location)); 143 case sizeof(u8): 144 return bigendian_64(*(T*)(location)); 145 } 146 } 147 return read_unaligned<T>((const address)location); 148 } 149 150 #endif // SHARE_VM_JFR_UTILITIES_JFRBIGENDIAN_HPP