Path: blob/master/src/hotspot/share/jfr/writers/jfrEncoders.hpp
41149 views
/*1* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_JFR_WRITERS_JFRENCODERS_HPP25#define SHARE_JFR_WRITERS_JFRENCODERS_HPP2627#include "memory/allocation.hpp"28#include "utilities/bytes.hpp"29#include "utilities/debug.hpp"30#include "utilities/globalDefinitions.hpp"3132//33// The Encoding policy prescribes a template34// method taking a first parameter of type T.35// This is the value to be encoded. The second36// parameter is a memory address - where to write37// the encoded value.38// The encoder method(s) should return the39// number of bytes encoded into that memory address.40//41// template <typename T>42// size_t encoder(T value, u1* dest);43//44// The caller ensures the destination45// address is not null and that T can be fitted46// in encoded form.47//4849// Encoding policy classes5051class BigEndianEncoderImpl {52public:53template <typename T>54static size_t encode(T value, u1* dest);5556template <typename T>57static size_t encode(const T* src, size_t len, u1* dest);5859template <typename T>60static size_t encode_padded(T value, u1* dest);6162template <typename T>63static size_t encode_padded(const T* src, size_t len, u1* dest);6465};6667template <typename T>68inline size_t BigEndianEncoderImpl::encode(T value, u1* dest) {69assert(dest != NULL, "invariant");70switch (sizeof(T)) {71case 1: {72ShouldNotReachHere();73return 0;74}75case 2: {76Bytes::put_Java_u2(dest, value);77return 2;78}79case 4: {80Bytes::put_Java_u4(dest, value);81return 4;82}83case 8: {84Bytes::put_Java_u8(dest, value);85return 8;86}87}88ShouldNotReachHere();89return 0;90}9192template <typename T>93inline size_t BigEndianEncoderImpl::encode(const T* src, size_t len, u1* dest) {94assert(dest != NULL, "invariant");95assert(len >= 1, "invariant");96if (1 == sizeof(T)) {97memcpy(dest, src, len);98return len;99}100size_t size = encode(*src, dest);101if (len > 1) {102for (size_t i = 1; i < len; ++i) {103size += encode(*(src + i), dest + size);104}105}106return size;107}108109template <typename T>110inline size_t BigEndianEncoderImpl::encode_padded(T value, u1* dest) {111return encode(value, dest);112}113114template <typename T>115inline size_t BigEndianEncoderImpl::encode_padded(const T* src, size_t len, u1* dest) {116assert(dest != NULL, "invariant");117assert(len >= 1, "invariant");118if (1 == sizeof(T)) {119memcpy(dest, src, len);120return len;121}122size_t size = encode_padded(*src, dest);123if (len > 1) {124for (size_t i = 1; i < len; ++i) {125size += encode_padded(*(src + i), dest + size);126}127}128return size;129}130131132// The Varint128 encoder implements encoding according to133// msb(it) 128bit encoding (1 encode bit | 7 value bits),134// using least significant byte order.135//136// Example (little endian platform):137// Value: 25674138// Binary: 00000000 0000000 01100100 01001010139// Varint encoded (3 bytes):140// Value: 13289473141// Varint encoded: 11001010 11001000 00000001142//143144class Varint128EncoderImpl {145private:146template <typename T>147static u8 to_u8(T value);148149public:150template <typename T>151static size_t encode(T value, u1* dest);152153template <typename T>154static size_t encode(const T* src, size_t len, u1* dest);155156template <typename T>157static size_t encode_padded(T value, u1* dest);158159template <typename T>160static size_t encode_padded(const T* src, size_t len, u1* dest);161162};163164template <typename T>165inline u8 Varint128EncoderImpl::to_u8(T value) {166switch(sizeof(T)) {167case 1:168return static_cast<u8>(static_cast<u1>(value) & static_cast<u1>(0xff));169case 2:170return static_cast<u8>(static_cast<u2>(value) & static_cast<u2>(0xffff));171case 4:172return static_cast<u8>(static_cast<u4>(value) & static_cast<u4>(0xffffffff));173case 8:174return static_cast<u8>(value);175default:176fatal("unsupported type");177}178return 0;179}180181static const u1 ext_bit = 0x80;182#define GREATER_THAN_OR_EQUAL_TO_128(v) (((u8)(~(ext_bit - 1)) & (v)))183#define LESS_THAN_128(v) !GREATER_THAN_OR_EQUAL_TO_128(v)184185template <typename T>186inline size_t Varint128EncoderImpl::encode(T value, u1* dest) {187assert(dest != NULL, "invariant");188189const u8 v = to_u8(value);190191if (LESS_THAN_128(v)) {192*dest = static_cast<u1>(v); // set bit 0-6, no extension193return 1;194}195*dest = static_cast<u1>(v | ext_bit); // set bit 0-6, with extension196if (LESS_THAN_128(v >> 7)) {197*(dest + 1) = static_cast<u1>(v >> 7); // set bit 7-13, no extension198return 2;199}200*(dest + 1) = static_cast<u1>((v >> 7) | ext_bit); // set bit 7-13, with extension201if (LESS_THAN_128(v >> 14)) {202*(dest + 2) = static_cast<u1>(v >> 14); // set bit 14-20, no extension203return 3;204}205*(dest + 2) = static_cast<u1>((v >> 14) | ext_bit); // set bit 14-20, with extension206if (LESS_THAN_128(v >> 21)) {207*(dest + 3) = static_cast<u1>(v >> 21); // set bit 21-27, no extension208return 4;209}210*(dest + 3) = static_cast<u1>((v >> 21) | ext_bit); // set bit 21-27, with extension211if (LESS_THAN_128(v >> 28)) {212*(dest + 4) = static_cast<u1>(v >> 28); // set bit 28-34, no extension213return 5;214}215*(dest + 4) = static_cast<u1>((v >> 28) | ext_bit); // set bit 28-34, with extension216if (LESS_THAN_128(v >> 35)) {217*(dest + 5) = static_cast<u1>(v >> 35); // set bit 35-41, no extension218return 6;219}220*(dest + 5) = static_cast<u1>((v >> 35) | ext_bit); // set bit 35-41, with extension221if (LESS_THAN_128(v >> 42)) {222*(dest + 6) = static_cast<u1>(v >> 42); // set bit 42-48, no extension223return 7;224}225*(dest + 6) = static_cast<u1>((v >> 42) | ext_bit); // set bit 42-48, with extension226if (LESS_THAN_128(v >> 49)) {227*(dest + 7) = static_cast<u1>(v >> 49); // set bit 49-55, no extension228return 8;229}230*(dest + 7) = static_cast<u1>((v >> 49) | ext_bit); // set bit 49-55, with extension231// no need to extend since only 64 bits allowed.232*(dest + 8) = static_cast<u1>(v >> 56); // set bit 56-63233return 9;234}235236template <typename T>237inline size_t Varint128EncoderImpl::encode(const T* src, size_t len, u1* dest) {238assert(dest != NULL, "invariant");239assert(len >= 1, "invariant");240size_t size = encode(*src, dest);241if (len > 1) {242for (size_t i = 1; i < len; ++i) {243size += encode(*(src + i), dest + size);244}245}246return size;247}248249template <typename T>250inline size_t Varint128EncoderImpl::encode_padded(T value, u1* dest) {251assert(dest != NULL, "invariant");252const u8 v = to_u8(value);253switch (sizeof(T)) {254case 1:255dest[0] = static_cast<u1>(v);256return 1;257case 2:258dest[0] = static_cast<u1>(v | 0x80);259dest[1] = static_cast<u1>(v >> 7);260return 2;261case 4:262dest[0] = static_cast<u1>(v | 0x80);263dest[1] = static_cast<u1>(v >> 7 | 0x80);264dest[2] = static_cast<u1>(v >> 14 | 0x80);265dest[3] = static_cast<u1>(v >> 21);266return 4;267case 8:268dest[0] = static_cast<u1>(v | 0x80);269dest[1] = static_cast<u1>(v >> 7 | 0x80);270dest[2] = static_cast<u1>(v >> 14 | 0x80);271dest[3] = static_cast<u1>(v >> 21 | 0x80);272dest[4] = static_cast<u1>(v >> 28 | 0x80);273dest[5] = static_cast<u1>(v >> 35 | 0x80);274dest[6] = static_cast<u1>(v >> 42 | 0x80);275dest[7] = static_cast<u1>(v >> 49);276return 8;277default:278ShouldNotReachHere();279}280return 0;281}282283284template <typename T>285inline size_t Varint128EncoderImpl::encode_padded(const T* src, size_t len, u1* dest) {286assert(dest != NULL, "invariant");287assert(len >= 1, "invariant");288size_t size = encode_padded(*src, dest);289if (len > 1) {290for (size_t i = 1; i < len; ++i) {291size += encode_padded(*(src + i), dest + size);292}293}294return size;295}296297#endif // SHARE_JFR_WRITERS_JFRENCODERS_HPP298299300