Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Commit 7aac4dc

Browse files
author
Markus Grönlund
committed
8257621: JFR StringPool misses cached items across consecutive recordings
Reviewed-by: egahlin
1 parent 61390d8 commit 7aac4dc

File tree

14 files changed

+106
-152
lines changed

14 files changed

+106
-152
lines changed

src/hotspot/share/jfr/jni/jfrJniMethod.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,6 @@ NO_TRANSITION(jboolean, jfr_is_available(JNIEnv* env, jclass jvm))
160160
return !Jfr::is_disabled() ? JNI_TRUE : JNI_FALSE;
161161
NO_TRANSITION_END
162162

163-
NO_TRANSITION(jlong, jfr_get_epoch_address(JNIEnv* env, jobject jvm))
164-
return JfrTraceIdEpoch::epoch_address();
165-
NO_TRANSITION_END
166-
167163
NO_TRANSITION(jlong, jfr_get_unloaded_event_classes_count(JNIEnv* env, jobject jvm))
168164
return JfrKlassUnloading::event_class_count();
169165
NO_TRANSITION_END
@@ -327,8 +323,8 @@ JVM_ENTRY_NO_ENV(jlong, jfr_type_id(JNIEnv* env, jobject jvm, jclass jc))
327323
return JfrTraceId::load_raw(jc);
328324
JVM_END
329325

330-
JVM_ENTRY_NO_ENV(jboolean, jfr_add_string_constant(JNIEnv* env, jclass jvm, jboolean epoch, jlong id, jstring string))
331-
return JfrStringPool::add(epoch == JNI_TRUE, id, string, thread) ? JNI_TRUE : JNI_FALSE;
326+
JVM_ENTRY_NO_ENV(jboolean, jfr_add_string_constant(JNIEnv* env, jclass jvm, jlong id, jstring string))
327+
return JfrStringPool::add(id, string, thread);
332328
JVM_END
333329

334330
JVM_ENTRY_NO_ENV(void, jfr_set_force_instrumentation(JNIEnv* env, jobject jvm, jboolean force_instrumentation))

src/hotspot/share/jfr/jni/jfrJniMethod.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,7 @@ jboolean JNICALL jfr_event_writer_flush(JNIEnv* env, jclass cls, jobject writer,
120120
void JNICALL jfr_flush(JNIEnv* env, jobject jvm);
121121
void JNICALL jfr_abort(JNIEnv* env, jobject jvm, jstring errorMsg);
122122

123-
jlong JNICALL jfr_get_epoch_address(JNIEnv* env, jobject jvm);
124-
125-
jboolean JNICALL jfr_add_string_constant(JNIEnv* env, jclass jvm, jboolean epoch, jlong id, jstring string);
123+
jboolean JNICALL jfr_add_string_constant(JNIEnv* env, jclass jvm, jlong id, jstring string);
126124

127125
void JNICALL jfr_uncaught_exception(JNIEnv* env, jobject jvm, jobject thread, jthrowable throwable);
128126

src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) {
7575
(char*)"flush", (char*)"()V", (void*)jfr_flush,
7676
(char*)"setRepositoryLocation", (char*)"(Ljava/lang/String;)V", (void*)jfr_set_repository_location,
7777
(char*)"abort", (char*)"(Ljava/lang/String;)V", (void*)jfr_abort,
78-
(char*)"getEpochAddress", (char*)"()J",(void*)jfr_get_epoch_address,
79-
(char*)"addStringConstant", (char*)"(ZJLjava/lang/String;)Z", (void*)jfr_add_string_constant,
78+
(char*)"addStringConstant", (char*)"(JLjava/lang/String;)Z", (void*)jfr_add_string_constant,
8079
(char*)"uncaughtException", (char*)"(Ljava/lang/Thread;Ljava/lang/Throwable;)V", (void*)jfr_uncaught_exception,
8180
(char*)"setForceInstrumentation", (char*)"(Z)V", (void*)jfr_set_force_instrumentation,
8281
(char*)"getUnloadedEventClassCount", (char*)"()J", (void*)jfr_get_unloaded_event_classes_count,

src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "jfr/utilities/jfrBigEndian.hpp"
4343
#include "jfr/utilities/jfrIterator.hpp"
4444
#include "jfr/utilities/jfrLinkedList.inline.hpp"
45+
#include "jfr/utilities/jfrSignal.hpp"
4546
#include "jfr/utilities/jfrThreadIterator.hpp"
4647
#include "jfr/utilities/jfrTypes.hpp"
4748
#include "jfr/writers/jfrJavaEventWriter.hpp"
@@ -57,22 +58,7 @@
5758

5859
typedef JfrCheckpointManager::BufferPtr BufferPtr;
5960

60-
static volatile bool constant_pending = false;
61-
62-
static bool is_constant_pending() {
63-
if (Atomic::load_acquire(&constant_pending)) {
64-
Atomic::release_store(&constant_pending, false); // reset
65-
return true;
66-
}
67-
return false;
68-
}
69-
70-
static void set_constant_pending() {
71-
if (!Atomic::load_acquire(&constant_pending)) {
72-
Atomic::release_store(&constant_pending, true);
73-
}
74-
}
75-
61+
static JfrSignal _new_checkpoint;
7662
static JfrCheckpointManager* _instance = NULL;
7763

7864
JfrCheckpointManager& JfrCheckpointManager::instance() {
@@ -231,7 +217,7 @@ BufferPtr JfrCheckpointManager::flush(BufferPtr old, size_t used, size_t request
231217
// indicates a lease is being returned
232218
release(old);
233219
// signal completion of a new checkpoint
234-
set_constant_pending();
220+
_new_checkpoint.signal();
235221
return NULL;
236222
}
237223
BufferPtr new_buffer = lease(old, thread, used + requested);
@@ -474,7 +460,7 @@ size_t JfrCheckpointManager::flush_type_set() {
474460
elements = ::flush_type_set(thread);
475461
}
476462
}
477-
if (is_constant_pending()) {
463+
if (_new_checkpoint.is_signaled()) {
478464
WriteOperation wo(_chunkwriter);
479465
MutexedWriteOperation mwo(wo);
480466
_thread_local_mspace->iterate(mwo); // current epoch list

src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
2727
#include "runtime/safepoint.hpp"
2828

29+
JfrSignal JfrTraceIdEpoch::_tag_state;
2930
bool JfrTraceIdEpoch::_epoch_state = false;
3031
bool JfrTraceIdEpoch::_synchronizing = false;
31-
volatile bool JfrTraceIdEpoch::_changed_tag_state = false;
3232

3333
void JfrTraceIdEpoch::begin_epoch_shift() {
3434
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
@@ -43,3 +43,4 @@ void JfrTraceIdEpoch::end_epoch_shift() {
4343
OrderAccess::storestore();
4444
_synchronizing = false;
4545
}
46+

src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#ifndef SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDEPOCH_HPP
2626
#define SHARE_JFR_RECORDER_CHECKPOINT_TYPES_TRACEID_JFRTRACEIDEPOCH_HPP
2727

28+
#include "jfr/utilities/jfrSignal.hpp"
2829
#include "jfr/utilities/jfrTypes.hpp"
2930
#include "memory/allocation.hpp"
3031
#include "runtime/atomic.hpp"
@@ -54,21 +55,13 @@
5455
class JfrTraceIdEpoch : AllStatic {
5556
friend class JfrCheckpointManager;
5657
private:
58+
static JfrSignal _tag_state;
5759
static bool _epoch_state;
5860
static bool _synchronizing;
59-
static volatile bool _changed_tag_state;
6061

6162
static void begin_epoch_shift();
6263
static void end_epoch_shift();
6364

64-
static bool changed_tag_state() {
65-
return Atomic::load_acquire(&_changed_tag_state);
66-
}
67-
68-
static void set_tag_state(bool value) {
69-
Atomic::release_store(&_changed_tag_state, value);
70-
}
71-
7265
public:
7366
static bool epoch() {
7467
return _epoch_state;
@@ -115,17 +108,11 @@ class JfrTraceIdEpoch : AllStatic {
115108
}
116109

117110
static bool has_changed_tag_state() {
118-
if (changed_tag_state()) {
119-
set_tag_state(false);
120-
return true;
121-
}
122-
return false;
111+
return _tag_state.is_signaled();
123112
}
124113

125114
static void set_changed_tag_state() {
126-
if (!changed_tag_state()) {
127-
set_tag_state(true);
128-
}
115+
_tag_state.signal();
129116
}
130117
};
131118

src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,7 @@ static size_t write_storage(JfrStorage& storage, JfrChunkWriter& chunkwriter) {
314314
}
315315

316316
typedef Content<JfrStringPool, &JfrStringPool::write> StringPool;
317-
typedef Content<JfrStringPool, &JfrStringPool::write_at_safepoint> StringPoolSafepoint;
318317
typedef WriteCheckpointEvent<StringPool> WriteStringPool;
319-
typedef WriteCheckpointEvent<StringPoolSafepoint> WriteStringPoolSafepoint;
320318

321319
static u4 flush_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
322320
StringPool sp(string_pool);
@@ -330,12 +328,6 @@ static u4 write_stringpool(JfrStringPool& string_pool, JfrChunkWriter& chunkwrit
330328
return invoke(wsp);
331329
}
332330

333-
static u4 write_stringpool_safepoint(JfrStringPool& string_pool, JfrChunkWriter& chunkwriter) {
334-
StringPoolSafepoint sps(string_pool);
335-
WriteStringPoolSafepoint wsps(chunkwriter, sps, TYPE_STRING);
336-
return invoke(wsps);
337-
}
338-
339331
typedef Content<JfrCheckpointManager, &JfrCheckpointManager::flush_type_set> FlushTypeSetFunctor;
340332
typedef WriteContent<FlushTypeSetFunctor> FlushTypeSet;
341333

@@ -569,7 +561,7 @@ void JfrRecorderService::safepoint_write() {
569561
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
570562
_checkpoint_manager.begin_epoch_shift();
571563
if (_string_pool.is_modified()) {
572-
write_stringpool_safepoint(_string_pool, _chunkwriter);
564+
write_stringpool(_string_pool, _chunkwriter);
573565
}
574566
_checkpoint_manager.on_rotation();
575567
_storage.write_at_safepoint();

src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "jfr/recorder/stringpool/jfrStringPool.hpp"
3333
#include "jfr/recorder/stringpool/jfrStringPoolWriter.hpp"
3434
#include "jfr/utilities/jfrLinkedList.inline.hpp"
35+
#include "jfr/utilities/jfrSignal.hpp"
3536
#include "jfr/utilities/jfrTypes.hpp"
3637
#include "logging/log.hpp"
3738
#include "runtime/atomic.hpp"
@@ -40,44 +41,19 @@
4041

4142
typedef JfrStringPool::BufferPtr BufferPtr;
4243

43-
static JfrStringPool* _instance = NULL;
44-
static uint64_t store_generation = 0;
45-
static uint64_t serialized_generation = 0;
46-
47-
inline void set_generation(uint64_t value, uint64_t* const dest) {
48-
assert(dest != NULL, "invariant");
49-
Atomic::release_store(dest, value);
50-
}
51-
52-
static void increment_store_generation() {
53-
const uint64_t current_serialized = Atomic::load_acquire(&serialized_generation);
54-
const uint64_t current_stored = Atomic::load_acquire(&store_generation);
55-
if (current_serialized == current_stored) {
56-
set_generation(current_serialized + 1, &store_generation);
57-
}
58-
}
59-
60-
static bool increment_serialized_generation() {
61-
const uint64_t current_stored = Atomic::load_acquire(&store_generation);
62-
const uint64_t current_serialized = Atomic::load_acquire(&serialized_generation);
63-
if (current_stored != current_serialized) {
64-
set_generation(current_stored, &serialized_generation);
65-
return true;
66-
}
67-
return false;
68-
}
44+
static JfrSignal _new_string;
6945

7046
bool JfrStringPool::is_modified() {
71-
return increment_serialized_generation();
47+
return _new_string.is_signaled();
7248
}
7349

50+
static JfrStringPool* _instance = NULL;
51+
7452
JfrStringPool& JfrStringPool::instance() {
7553
return *_instance;
7654
}
7755

7856
JfrStringPool* JfrStringPool::create(JfrChunkWriter& cw) {
79-
store_generation = 0;
80-
serialized_generation = 0;
8157
assert(_instance == NULL, "invariant");
8258
_instance = new JfrStringPool(cw);
8359
return _instance;
@@ -155,20 +131,16 @@ BufferPtr JfrStringPool::lease(Thread* thread, size_t size /* 0 */) {
155131
return buffer;
156132
}
157133

158-
bool JfrStringPool::add(bool epoch, jlong id, jstring string, JavaThread* jt) {
134+
jboolean JfrStringPool::add(jlong id, jstring string, JavaThread* jt) {
159135
assert(jt != NULL, "invariant");
160-
const bool current_epoch = JfrTraceIdEpoch::epoch();
161-
if (current_epoch != epoch) {
162-
return current_epoch;
163-
}
164136
{
165137
JfrStringPoolWriter writer(jt);
166138
writer.write(id);
167139
writer.write(string);
168140
writer.inc_nof_strings();
169141
}
170-
increment_store_generation();
171-
return current_epoch;
142+
_new_string.signal();
143+
return JNI_TRUE;
172144
}
173145

174146
template <template <typename> class Operation>
@@ -224,13 +196,7 @@ size_t JfrStringPool::write() {
224196
return wo.processed();
225197
}
226198

227-
size_t JfrStringPool::write_at_safepoint() {
228-
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
229-
return write();
230-
}
231-
232199
size_t JfrStringPool::clear() {
233-
increment_serialized_generation();
234200
DiscardOperation discard_operation;
235201
ExclusiveDiscardOperation edo(discard_operation);
236202
assert(_mspace->free_list_is_empty(), "invariant");

src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ typedef JfrMemorySpace<JfrStringPool, JfrMspaceRetrieval, JfrLinkedList<JfrStrin
4545
//
4646
class JfrStringPool : public JfrCHeapObj {
4747
public:
48-
static bool add(bool epoch, jlong id, jstring string, JavaThread* jt);
4948
size_t write();
50-
size_t write_at_safepoint();
5149
size_t clear();
50+
static jboolean add(jlong id, jstring string, JavaThread* jt);
51+
5252
typedef JfrStringPoolMspace::Node Buffer;
5353
typedef JfrStringPoolMspace::NodePtr BufferPtr;
5454

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2020, 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_JFR_UTILITIES_JFRSIGNAL_HPP
26+
#define SHARE_JFR_UTILITIES_JFRSIGNAL_HPP
27+
28+
#include "runtime/atomic.hpp"
29+
30+
class JfrSignal {
31+
private:
32+
mutable volatile bool _signaled;
33+
public:
34+
JfrSignal() : _signaled(false) {}
35+
36+
void signal() const {
37+
if (!Atomic::load_acquire(&_signaled)) {
38+
Atomic::release_store(&_signaled, true);
39+
}
40+
}
41+
42+
bool is_signaled() const {
43+
if (Atomic::load_acquire(&_signaled)) {
44+
Atomic::release_store(&_signaled, false); // auto-reset
45+
return true;
46+
}
47+
return false;
48+
}
49+
};
50+
51+
#endif // SHARE_JFR_UTILITIES_JFRSIGNAL_HPP

0 commit comments

Comments
 (0)