Skip to content

Commit

Permalink
8298129: Let checkpoint event sizes grow beyond u4 limit
Browse files Browse the repository at this point in the history
Reviewed-by: phh
Backport-of: ea108f504ccb63fc9651e804e3bbba1c108dcead
  • Loading branch information
Ekaterina Vergizova committed Jan 31, 2023
1 parent 0e98d6a commit 7b39d48
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 36 deletions.
74 changes: 41 additions & 33 deletions src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
Expand Up @@ -230,64 +230,72 @@ BufferPtr JfrCheckpointManager::flush(BufferPtr old, size_t used, size_t request
}

// offsets into the JfrCheckpointEntry
static const juint starttime_offset = sizeof(jlong);
static const juint duration_offset = starttime_offset + sizeof(jlong);
static const juint checkpoint_type_offset = duration_offset + sizeof(jlong);
static const juint types_offset = checkpoint_type_offset + sizeof(juint);
static const juint payload_offset = types_offset + sizeof(juint);
static const size_t starttime_offset = sizeof(int64_t);
static const size_t duration_offset = starttime_offset + sizeof(int64_t);
static const size_t checkpoint_type_offset = duration_offset + sizeof(int64_t);
static const size_t types_offset = checkpoint_type_offset + sizeof(uint32_t);
static const size_t payload_offset = types_offset + sizeof(uint32_t);

template <typename Return>
static Return read_data(const u1* data) {
return JfrBigEndian::read<Return>(data);
}

static jlong total_size(const u1* data) {
return read_data<jlong>(data);
static size_t total_size(const u1* data) {
const int64_t size = read_data<int64_t>(data);
assert(size > 0, "invariant");
return static_cast<size_t>(size);
}

static jlong starttime(const u1* data) {
return read_data<jlong>(data + starttime_offset);
static int64_t starttime(const u1* data) {
return read_data<int64_t>(data + starttime_offset);
}

static jlong duration(const u1* data) {
return read_data<jlong>(data + duration_offset);
static int64_t duration(const u1* data) {
return read_data<int64_t>(data + duration_offset);
}

static u1 checkpoint_type(const u1* data) {
return read_data<u1>(data + checkpoint_type_offset);
static uint8_t checkpoint_type(const u1* data) {
return read_data<uint8_t>(data + checkpoint_type_offset);
}

static juint number_of_types(const u1* data) {
return read_data<juint>(data + types_offset);
static uint32_t number_of_types(const u1* data) {
return read_data<uint32_t>(data + types_offset);
}

static void write_checkpoint_header(JfrChunkWriter& cw, int64_t delta_to_last_checkpoint, const u1* data) {
cw.reserve(sizeof(u4));
cw.write<u8>(EVENT_CHECKPOINT);
cw.write(starttime(data));
cw.write(duration(data));
cw.write(delta_to_last_checkpoint);
cw.write(checkpoint_type(data));
cw.write(number_of_types(data));
static size_t payload_size(const u1* data) {
return total_size(data) - sizeof(JfrCheckpointEntry);
}

static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) {
assert(data != NULL, "invariant");
cw.write_unbuffered(data + payload_offset, size - sizeof(JfrCheckpointEntry));
static uint64_t calculate_event_size_bytes(JfrChunkWriter& cw, const u1* data, int64_t event_begin, int64_t delta_to_last_checkpoint) {
assert(data != nullptr, "invariant");
size_t bytes = cw.size_in_bytes(EVENT_CHECKPOINT);
bytes += cw.size_in_bytes(starttime(data));
bytes += cw.size_in_bytes(duration(data));
bytes += cw.size_in_bytes(delta_to_last_checkpoint);
bytes += cw.size_in_bytes(checkpoint_type(data));
bytes += cw.size_in_bytes(number_of_types(data));
bytes += payload_size(data); // in bytes already.
return bytes + cw.size_in_bytes(bytes + cw.size_in_bytes(bytes));
}

static size_t write_checkpoint_event(JfrChunkWriter& cw, const u1* data) {
assert(data != NULL, "invariant");
const int64_t event_begin = cw.current_offset();
const int64_t last_checkpoint_event = cw.last_checkpoint_offset();
const int64_t delta_to_last_checkpoint = last_checkpoint_event == 0 ? 0 : last_checkpoint_event - event_begin;
const int64_t checkpoint_size = total_size(data);
write_checkpoint_header(cw, delta_to_last_checkpoint, data);
write_checkpoint_content(cw, data, checkpoint_size);
const int64_t event_size = cw.current_offset() - event_begin;
cw.write_padded_at_offset<u4>(event_size, event_begin);
cw.set_last_checkpoint_offset(event_begin);
return (size_t)checkpoint_size;
const int64_t delta_to_last_checkpoint = last_checkpoint_event == 0 ? 0 : last_checkpoint_event - event_begin;
const uint64_t event_size = calculate_event_size_bytes(cw, data, event_begin, delta_to_last_checkpoint);
cw.write(event_size);
cw.write(EVENT_CHECKPOINT);
cw.write(starttime(data));
cw.write(duration(data));
cw.write(delta_to_last_checkpoint);
cw.write(checkpoint_type(data));
cw.write(number_of_types(data));
cw.write_unbuffered(data + payload_offset, payload_size(data));
assert(static_cast<uint64_t>(cw.current_offset() - event_begin) == event_size, "invariant");
return total_size(data);
}

static size_t write_checkpoints(JfrChunkWriter& cw, const u1* data, size_t size) {
Expand Down
49 changes: 48 additions & 1 deletion src/hotspot/share/jfr/writers/jfrEncoders.hpp
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -63,6 +63,9 @@ class BigEndianEncoderImpl {
template <typename T>
static size_t encode_padded(const T* src, size_t len, u1* dest);

template <typename T>
static size_t size_in_bytes(T value);

};

template <typename T>
Expand Down Expand Up @@ -129,6 +132,17 @@ inline size_t BigEndianEncoderImpl::encode_padded(const T* src, size_t len, u1*
return size;
}

template <typename T>
inline size_t BigEndianEncoderImpl::size_in_bytes(T value) {
switch (sizeof(T)) {
case 1: return 1;
case 2: return 2;
case 4: return 4;
case 8:return 8;
}
ShouldNotReachHere();
return 0;
}

// The Varint128 encoder implements encoding according to
// msb(it) 128bit encoding (1 encode bit | 7 value bits),
Expand Down Expand Up @@ -160,6 +174,9 @@ class Varint128EncoderImpl {
template <typename T>
static size_t encode_padded(const T* src, size_t len, u1* dest);

template <typename T>
static size_t size_in_bytes(T value);

};

template <typename T>
Expand Down Expand Up @@ -295,4 +312,34 @@ inline size_t Varint128EncoderImpl::encode_padded(const T* src, size_t len, u1*
return size;
}

template <typename T>
inline size_t Varint128EncoderImpl::size_in_bytes(T value) {
const u8 v = to_u8(value);
if (LESS_THAN_128(v)) {
return 1;
}
if (LESS_THAN_128(v >> 7)) {
return 2;
}
if (LESS_THAN_128(v >> 14)) {
return 3;
}
if (LESS_THAN_128(v >> 21)) {
return 4;
}
if (LESS_THAN_128(v >> 28)) {
return 5;
}
if (LESS_THAN_128(v >> 35)) {
return 6;
}
if (LESS_THAN_128(v >> 42)) {
return 7;
}
if (LESS_THAN_128(v >> 49)) {
return 8;
}
return 9;
}

#endif // SHARE_JFR_WRITERS_JFRENCODERS_HPP
5 changes: 5 additions & 0 deletions src/hotspot/share/jfr/writers/jfrEncoding.hpp
Expand Up @@ -69,6 +69,11 @@ class EncoderHost : public AllStatic {
return pos + IntegerEncoder::encode_padded(value, len, pos);
}

template <typename T>
static size_t size_in_bytes(T value) {
return IntegerEncoder::size_in_bytes(value);
}

template <typename T>
static u1* write(T value, u1* pos) {
return write(&value, 1, pos);
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/jfr/writers/jfrWriterHost.hpp
Expand Up @@ -97,6 +97,8 @@ class WriterHost : public WriterPolicyImpl {
template <typename T>
void write_be_at_offset(T value, int64_t offset);
int64_t reserve(size_t size);
template <typename T>
size_t size_in_bytes(T value);
};

#endif // SHARE_JFR_WRITERS_JFRWRITERHOST_HPP
6 changes: 6 additions & 0 deletions src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp
Expand Up @@ -360,4 +360,10 @@ inline void WriterHost<BE, IE, WriterPolicyImpl>::write_be_at_offset(T value, in
}
}

template <typename BE, typename IE, typename WriterPolicyImpl>
template <typename T>
inline size_t WriterHost<BE, IE, WriterPolicyImpl>::size_in_bytes(T value) {
return IE::size_in_bytes(value);
}

#endif // SHARE_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP
Expand Up @@ -237,7 +237,7 @@ public RecordedEvent readEvent() throws IOException {
long absoluteChunkEnd = chunkHeader.getEnd();
while (input.position() < absoluteChunkEnd) {
long pos = input.position();
int size = input.readInt();
long size = input.readLong();
if (size == 0) {
throw new IOException("Event can't have zero size");
}
Expand Down Expand Up @@ -305,7 +305,7 @@ private void fillConstantPools(long abortCP) throws IOException {
while (thisCP != abortCP && delta != 0) {
input.position(thisCP);
lastCP = thisCP;
int size = input.readInt(); // size
long size = input.readLong(); // size
long typeId = input.readLong();
if (typeId != CONSTANT_POOL_TYPE_ID) {
throw new IOException("Expected check point event (id = 1) at position " + lastCP + ", but found type id = " + typeId);
Expand Down

1 comment on commit 7b39d48

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.