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