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