Path: blob/master/src/hotspot/share/code/compressedStream.hpp
40931 views
/*1* Copyright (c) 1997, 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_CODE_COMPRESSEDSTREAM_HPP25#define SHARE_CODE_COMPRESSEDSTREAM_HPP2627#include "memory/allocation.hpp"2829// Simple interface for filing out and filing in basic types30// Used for writing out and reading in debugging information.3132class CompressedStream : public ResourceObj {33friend class VMStructs;34protected:35u_char* _buffer;36int _position;3738enum {39// Constants for UNSIGNED5 coding of Pack20040lg_H = 6, H = 1<<lg_H, // number of high codes (64)41L = (1<<BitsPerByte)-H, // number of low codes (192)42MAX_i = 4 // bytes are numbered in (0..4), max 5 bytes43};4445// 32-bit one-to-one sign encoding taken from Pack20046// converts leading sign bits into leading zeroes with trailing sign bit47static juint encode_sign(jint value) { return (value << 1) ^ (value >> 31); }48static jint decode_sign(juint value) { return (value >> 1) ^ -(jint)(value & 1); }49static juint reverse_int(juint i); // to trim trailing float 0's50public:51CompressedStream(u_char* buffer, int position = 0) {52_buffer = buffer;53_position = position;54}5556u_char* buffer() const { return _buffer; }5758// Positioning59int position() const { return _position; }60void set_position(int position) { _position = position; }61};626364class CompressedReadStream : public CompressedStream {65private:66inline u_char read() { return _buffer[_position++]; }6768// This encoding, called UNSIGNED5, is taken from J2SE Pack200.69// It assumes that most values have lots of leading zeroes.70// Very small values, in the range [0..191], code in one byte.71// Any 32-bit value (including negatives) can be coded, in72// up to five bytes. The grammar is:73// low_byte = [0..191]74// high_byte = [192..255]75// any_byte = low_byte | high_byte76// coding = low_byte77// | high_byte low_byte78// | high_byte high_byte low_byte79// | high_byte high_byte high_byte low_byte80// | high_byte high_byte high_byte high_byte any_byte81// Each high_byte contributes six bits of payload.82// The encoding is one-to-one (except for integer overflow)83// and easy to parse and unparse.8485jint read_int_mb(jint b0) {86int pos = position() - 1;87u_char* buf = buffer() + pos;88assert(buf[0] == b0 && b0 >= L, "correctly called");89jint sum = b0;90// must collect more bytes: b[1]...b[4]91int lg_H_i = lg_H;92for (int i = 0; ; ) {93jint b_i = buf[++i]; // b_i = read(); ++i;94sum += b_i << lg_H_i; // sum += b[i]*(64**i)95if (b_i < L || i == MAX_i) {96set_position(pos+i+1);97return sum;98}99lg_H_i += lg_H;100}101}102103public:104CompressedReadStream(u_char* buffer, int position = 0)105: CompressedStream(buffer, position) {}106107jboolean read_bool() { return (jboolean) read(); }108jbyte read_byte() { return (jbyte ) read(); }109jchar read_char() { return (jchar ) read_int(); }110jshort read_short() { return (jshort ) read_signed_int(); }111jint read_int() { jint b0 = read();112if (b0 < L) return b0;113else return read_int_mb(b0);114}115jint read_signed_int();116jfloat read_float(); // jfloat_cast(reverse_int(read_int()))117jdouble read_double(); // jdouble_cast(2*reverse_int(read_int))118jlong read_long(); // jlong_from(2*read_signed_int())119};120121122class CompressedWriteStream : public CompressedStream {123private:124bool full() {125return _position >= _size;126}127void store(u_char b) {128_buffer[_position++] = b;129}130void write(u_char b) {131if (full()) grow();132store(b);133}134void grow();135136// UNSIGNED5 coding, 1-5 byte cases137void write_int_mb(jint value) {138juint sum = value;139for (int i = 0; ; ) {140if (sum < L || i == MAX_i) {141// remainder is either a "low code" or the 5th byte142assert(sum == (u_char)sum, "valid byte");143write((u_char)sum);144break;145}146sum -= L;147int b_i = L + (sum % H); // this is a "high code"148sum >>= lg_H; // extracted 6 bits149write(b_i); ++i;150}151}152153protected:154int _size;155156public:157CompressedWriteStream(int initial_size);158CompressedWriteStream(u_char* buffer, int initial_size, int position = 0)159: CompressedStream(buffer, position) { _size = initial_size; }160161void write_bool(jboolean value) { write(value); }162void write_byte(jbyte value) { write(value); }163void write_char(jchar value) { write_int(value); }164void write_short(jshort value) { write_signed_int(value); }165void write_int(jint value) { if ((juint)value < L && !full())166store((u_char)value);167else write_int_mb(value); }168void write_signed_int(jint value) { write_int(encode_sign(value)); }169void write_float(jfloat value); // write_int(reverse_int(jint_cast(v)))170void write_double(jdouble value); // write_int(reverse_int(<low,high>))171void write_long(jlong value); // write_signed_int(<low,high>)172};173174#endif // SHARE_CODE_COMPRESSEDSTREAM_HPP175176177