1 /*
   2  * Copyright (c) 2015, 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_WRITERS_JFRENCODERS_HPP
  26 #define SHARE_VM_JFR_WRITERS_JFRENCODERS_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "utilities/debug.hpp"
  30 #include "utilities/globalDefinitions.hpp"
  31 #ifdef TARGET_ARCH_x86
  32 # include "bytes_x86.hpp"
  33 #endif
  34 #ifdef TARGET_ARCH_sparc
  35 # include "bytes_sparc.hpp"
  36 #endif
  37 #ifdef TARGET_ARCH_zero
  38 # include "bytes_zero.hpp"
  39 #endif
  40 #ifdef TARGET_ARCH_arm
  41 # include "bytes_arm.hpp"
  42 #endif
  43 #ifdef TARGET_ARCH_ppc
  44 # include "bytes_ppc.hpp"
  45 #endif
  46 #ifdef TARGET_ARCH_aarch64
  47 # include "bytes_aarch64.hpp"
  48 #endif
  49 
  50 //
  51 // The Encoding policy prescribes a template
  52 // method taking a first parameter of type T.
  53 // This is the value to be encoded. The second
  54 // parameter is a memory address - where to write
  55 // the encoded value.
  56 // The encoder method(s) should return the
  57 // number of bytes encoded into that memory address.
  58 //
  59 // template <typename T>
  60 // size_t encoder(T value, u1* dest);
  61 //
  62 // The caller ensures the destination
  63 // address is not null and that T can be fitted
  64 // in encoded form.
  65 //
  66 
  67 // Encoding policy classes
  68 
  69 class BigEndianEncoderImpl {
  70  public:
  71   template <typename T>
  72   static size_t encode(T value, u1* dest);
  73 
  74   template <typename T>
  75   static size_t encode(const T* src, size_t len, u1* dest);
  76 
  77   template <typename T>
  78   static size_t encode_padded(T value, u1* dest);
  79 
  80   template <typename T>
  81   static size_t encode_padded(const T* src, size_t len, u1* dest);
  82 
  83 };
  84 
  85 template <typename T>
  86 inline size_t BigEndianEncoderImpl::encode(T value, u1* dest) {
  87   assert(dest != NULL, "invariant");
  88   switch (sizeof(T)) {
  89     case 1: {
  90       ShouldNotReachHere();
  91        return 0;
  92      }
  93      case 2: {
  94        Bytes::put_Java_u2(dest, value);
  95        return 2;
  96      }
  97      case 4: {
  98        Bytes::put_Java_u4(dest, value);
  99        return 4;
 100      }
 101      case 8: {
 102        Bytes::put_Java_u8(dest, value);
 103        return 8;
 104      }
 105   }
 106   ShouldNotReachHere();
 107   return 0;
 108 }
 109 
 110 template <typename T>
 111 inline size_t BigEndianEncoderImpl::encode(const T* src, size_t len, u1* dest) {
 112   assert(dest != NULL, "invariant");
 113   assert(len >= 1, "invariant");
 114   if (1 == sizeof(T)) {
 115     memcpy(dest, src, len);
 116     return len;
 117   }
 118   size_t size = encode(*src, dest);
 119   if (len > 1) {
 120     for (size_t i = 1; i < len; ++i) {
 121       size += encode(*(src + i), dest + size);
 122     }
 123   }
 124   return size;
 125 }
 126 
 127 template <typename T>
 128 inline size_t BigEndianEncoderImpl::encode_padded(T value, u1* dest) {
 129   return encode(value, dest);
 130 }
 131 
 132 template <typename T>
 133 inline size_t BigEndianEncoderImpl::encode_padded(const T* src, size_t len, u1* dest) {
 134   assert(dest != NULL, "invariant");
 135   assert(len >= 1, "invariant");
 136   if (1 == sizeof(T)) {
 137     memcpy(dest, src, len);
 138     return len;
 139   }
 140   size_t size = encode_padded(*src, dest);
 141   if (len > 1) {
 142     for (size_t i = 1; i < len; ++i) {
 143       size += encode_padded(*(src + i), dest + size);
 144     }
 145   }
 146   return size;
 147 }
 148 
 149 
 150 // The Varint128 encoder implements encoding according to
 151 // msb(it) 128bit encoding (1 encode bit | 7 value bits),
 152 // using least significant byte order.
 153 //
 154 // Example (little endian platform):
 155 // Value: 25674
 156 // Binary: 00000000 0000000 01100100 01001010
 157 // Varint encoded (3 bytes):
 158 // Value: 13289473
 159 // Varint encoded: 11001010 11001000 00000001
 160 //
 161 
 162 class Varint128EncoderImpl {
 163  private:
 164   template <typename T>
 165   static u8 to_u8(T value);
 166 
 167  public:
 168   template <typename T>
 169   static size_t encode(T value, u1* dest);
 170 
 171   template <typename T>
 172   static size_t encode(const T* src, size_t len, u1* dest);
 173 
 174   template <typename T>
 175   static size_t encode_padded(T value, u1* dest);
 176 
 177   template <typename T>
 178   static size_t encode_padded(const T* src, size_t len, u1* dest);
 179 
 180 };
 181 
 182 template <typename T>
 183 inline u8 Varint128EncoderImpl::to_u8(T value) {
 184   switch(sizeof(T)) {
 185     case 1:
 186      return static_cast<u8>(static_cast<u1>(value) & static_cast<u1>(0xff));
 187     case 2:
 188       return static_cast<u8>(static_cast<u2>(value) & static_cast<u2>(0xffff));
 189     case 4:
 190       return static_cast<u8>(static_cast<u4>(value) & static_cast<u4>(0xffffffff));
 191     case 8:
 192       return static_cast<u8>(value);
 193     default:
 194       fatal("unsupported type");
 195   }
 196   return 0;
 197 }
 198 
 199 static const u1 ext_bit = 0x80;
 200 #define GREATER_THAN_OR_EQUAL_TO_128(v) (((u8)(~(ext_bit - 1)) & (v)))
 201 #define LESS_THAN_128(v) !GREATER_THAN_OR_EQUAL_TO_128(v)
 202 
 203 template <typename T>
 204 inline size_t Varint128EncoderImpl::encode(T value, u1* dest) {
 205   assert(dest != NULL, "invariant");
 206 
 207   const u8 v = to_u8(value);
 208 
 209   if (LESS_THAN_128(v)) {
 210     *dest = static_cast<u1>(v); // set bit 0-6, no extension
 211     return 1;
 212   }
 213   *dest = static_cast<u1>(v | ext_bit); // set bit 0-6, with extension
 214   if (LESS_THAN_128(v >> 7)) {
 215     *(dest + 1) = static_cast<u1>(v >> 7); // set bit 7-13, no extension
 216     return 2;
 217   }
 218   *(dest + 1) = static_cast<u1>((v >> 7) | ext_bit); // set bit 7-13, with extension
 219   if (LESS_THAN_128(v >> 14)) {
 220     *(dest + 2) = static_cast<u1>(v >> 14); // set bit 14-20, no extension
 221     return 3;
 222   }
 223   *(dest + 2) = static_cast<u1>((v >> 14) | ext_bit); // set bit 14-20, with extension
 224   if (LESS_THAN_128(v >> 21)) {
 225     *(dest + 3) = static_cast<u1>(v >> 21); // set bit 21-27, no extension
 226     return 4;
 227   }
 228   *(dest + 3) = static_cast<u1>((v >> 21) | ext_bit); // set bit 21-27, with extension
 229   if (LESS_THAN_128(v >> 28)) {
 230     *(dest + 4) = static_cast<u1>(v >> 28); // set bit 28-34, no extension
 231     return 5;
 232   }
 233   *(dest + 4) = static_cast<u1>((v >> 28) | ext_bit); // set bit 28-34, with extension
 234   if (LESS_THAN_128(v >> 35)) {
 235     *(dest + 5) = static_cast<u1>(v >> 35); // set bit 35-41, no extension
 236     return 6;
 237   }
 238   *(dest + 5) = static_cast<u1>((v >> 35) | ext_bit); // set bit 35-41, with extension
 239   if (LESS_THAN_128(v >> 42)) {
 240     *(dest + 6) = static_cast<u1>(v >> 42); // set bit 42-48, no extension
 241     return 7;
 242   }
 243   *(dest + 6) = static_cast<u1>((v >> 42) | ext_bit); // set bit 42-48, with extension
 244   if (LESS_THAN_128(v >> 49)) {
 245     *(dest + 7) = static_cast<u1>(v >> 49); // set bit 49-55, no extension
 246     return 8;
 247   }
 248   *(dest + 7) = static_cast<u1>((v >> 49) | ext_bit); // set bit 49-55, with extension
 249   // no need to extend since only 64 bits allowed.
 250   *(dest + 8) = static_cast<u1>(v >> 56);  // set bit 56-63
 251   return 9;
 252 }
 253 
 254 template <typename T>
 255 inline size_t Varint128EncoderImpl::encode(const T* src, size_t len, u1* dest) {
 256   assert(dest != NULL, "invariant");
 257   assert(len >= 1, "invariant");
 258   size_t size = encode(*src, dest);
 259   if (len > 1) {
 260     for (size_t i = 1; i < len; ++i) {
 261       size += encode(*(src + i), dest + size);
 262     }
 263   }
 264   return size;
 265 }
 266 
 267 template <typename T>
 268 inline size_t Varint128EncoderImpl::encode_padded(T value, u1* dest) {
 269   assert(dest != NULL, "invariant");
 270   const u8 v = to_u8(value);
 271   switch (sizeof(T)) {
 272     case 1:
 273       dest[0] = static_cast<u1>(v);
 274       return 1;
 275     case 2:
 276       dest[0] = static_cast<u1>(v | 0x80);
 277       dest[1] = static_cast<u1>(v >> 7);
 278       return 2;
 279     case 4:
 280       dest[0] = static_cast<u1>(v | 0x80);
 281       dest[1] = static_cast<u1>(v >> 7 | 0x80);
 282       dest[2] = static_cast<u1>(v >> 14 | 0x80);
 283       dest[3] = static_cast<u1>(v >> 21);
 284       return 4;
 285     case 8:
 286       dest[0] = static_cast<u1>(v | 0x80);
 287       dest[1] = static_cast<u1>(v >> 7 | 0x80);
 288       dest[2] = static_cast<u1>(v >> 14 | 0x80);
 289       dest[3] = static_cast<u1>(v >> 21 | 0x80);
 290       dest[4] = static_cast<u1>(v >> 28 | 0x80);
 291       dest[5] = static_cast<u1>(v >> 35 | 0x80);
 292       dest[6] = static_cast<u1>(v >> 42 | 0x80);
 293       dest[7] = static_cast<u1>(v >> 49);
 294       return 8;
 295     default:
 296       ShouldNotReachHere();
 297     }
 298   return 0;
 299 }
 300 
 301 
 302 template <typename T>
 303 inline size_t Varint128EncoderImpl::encode_padded(const T* src, size_t len, u1* dest) {
 304   assert(dest != NULL, "invariant");
 305   assert(len >= 1, "invariant");
 306   size_t size = encode_padded(*src, dest);
 307   if (len > 1) {
 308     for (size_t i = 1; i < len; ++i) {
 309       size += encode_padded(*(src + i), dest + size);
 310     }
 311   }
 312   return size;
 313 }
 314 
 315 #endif // SHARE_VM_JFR_WRITERS_JFRENCODERS_HPP