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