30
30
#include " gc/shared/memAllocator.hpp"
31
31
#include " gc/shared/threadLocalAllocBuffer.inline.hpp"
32
32
#include " gc/shared/tlab_globals.hpp"
33
+ #include " jfr/jfrEvents.hpp"
33
34
#include " memory/universe.hpp"
34
35
#include " oops/arrayOop.hpp"
35
36
#include " oops/oop.inline.hpp"
41
42
#include " services/lowMemoryDetector.hpp"
42
43
#include " utilities/align.hpp"
43
44
#include " utilities/copy.hpp"
45
+ #include " utilities/dtrace.hpp"
44
46
#include " utilities/globalDefinitions.hpp"
45
47
46
48
class MemAllocator ::Allocation: StackObj {
@@ -52,7 +54,8 @@ class MemAllocator::Allocation: StackObj {
52
54
bool _overhead_limit_exceeded;
53
55
bool _allocated_outside_tlab;
54
56
size_t _allocated_tlab_size;
55
- bool _tlab_end_reset_for_sample;
57
+ bool _tlab_end_reset_for_jvmti_sample;
58
+ bool _tlab_end_reset_for_jfr_sample;
56
59
57
60
bool check_out_of_memory ();
58
61
void verify_before ();
@@ -76,7 +79,8 @@ class MemAllocator::Allocation: StackObj {
76
79
_overhead_limit_exceeded(false ),
77
80
_allocated_outside_tlab(false ),
78
81
_allocated_tlab_size(0 ),
79
- _tlab_end_reset_for_sample(false )
82
+ _tlab_end_reset_for_jvmti_sample(false ),
83
+ _tlab_end_reset_for_jfr_sample(false )
80
84
{
81
85
assert (Thread::current () == allocator._thread , " do not pass MemAllocator across threads" );
82
86
verify_before ();
@@ -171,7 +175,7 @@ void MemAllocator::Allocation::notify_allocation_jvmti_sampler() {
171
175
return ;
172
176
}
173
177
174
- if (!_allocated_outside_tlab && _allocated_tlab_size == 0 && !_tlab_end_reset_for_sample ) {
178
+ if (!_allocated_outside_tlab && _allocated_tlab_size == 0 && !_tlab_end_reset_for_jvmti_sample ) {
175
179
// Sample if it's a non-TLAB allocation, or a TLAB allocation that either refills the TLAB
176
180
// or expands it due to taking a sampler induced slow path.
177
181
return ;
@@ -181,23 +185,21 @@ void MemAllocator::Allocation::notify_allocation_jvmti_sampler() {
181
185
// before doing the callback. The callback is done in the destructor of
182
186
// the JvmtiSampledObjectAllocEventCollector.
183
187
size_t bytes_since_last = 0 ;
184
-
188
+ size_t bytes_since_allocation = 0 ;
185
189
{
186
190
PreserveObj obj_h (_thread, _obj_ptr);
187
191
JvmtiSampledObjectAllocEventCollector collector;
188
192
size_t size_in_bytes = _allocator._word_size * HeapWordSize;
189
- ThreadLocalAllocBuffer& tlab = _thread->tlab ();
190
193
191
- if (!_allocated_outside_tlab) {
192
- bytes_since_last = tlab.bytes_since_last_sample_point ();
194
+ if (_thread->heap_samplers ().jvmti ().check_for_sampling (&bytes_since_allocation, size_in_bytes, !_allocated_outside_tlab)) {
195
+ // HOTSPOT_GC_ALLOCOBJECT_SAMPLE(obj_h->klass()->name()->as_C_string(), size_in_bytes, bytes_since_allocation);
196
+ JvmtiExport::sampled_object_alloc_event_collector (obj_h ());
193
197
}
194
-
195
- _thread->heap_sampler ().check_for_sampling (obj_h (), size_in_bytes, bytes_since_last);
196
198
}
197
199
198
- if (_tlab_end_reset_for_sample || _allocated_tlab_size != 0 ) {
200
+ if (_tlab_end_reset_for_jvmti_sample || _allocated_tlab_size != 0 ) {
199
201
// Tell tlab to forget bytes_since_last if we passed it to the heap sampler.
200
- _thread->tlab ().set_sample_end (bytes_since_last != 0 );
202
+ _thread->tlab ().set_jvmti_sample_end (!_allocated_outside_tlab );
201
203
}
202
204
}
203
205
@@ -217,6 +219,30 @@ void MemAllocator::Allocation::notify_allocation_jfr_sampler() {
217
219
AllocTracer::send_allocation_in_new_tlab (obj ()->klass (), mem, _allocated_tlab_size * HeapWordSize,
218
220
size_in_bytes, _thread);
219
221
}
222
+
223
+ EventObjectAllocationSample event;
224
+ if (!event.should_commit ()) {
225
+ return ;
226
+ }
227
+
228
+ bool hit_mark = _allocated_tlab_size != 0 || _tlab_end_reset_for_jfr_sample;
229
+ if (!_allocated_outside_tlab && !hit_mark) {
230
+ // Sample if it's a non-TLAB allocation, or a TLAB allocation that either refills the TLAB
231
+ // or expands it due to taking a sampler induced slow path.
232
+ return ;
233
+ }
234
+
235
+ size_t bytes_since_allocation = 0 ;
236
+ if (_thread->heap_samplers ().jfr ().check_for_sampling (&bytes_since_allocation, size_in_bytes, !_allocated_outside_tlab)) {
237
+ size_t weight = bytes_since_allocation == 0 ? size_in_bytes : bytes_since_allocation;
238
+ AllocTracer::send_allocation_sample (obj ()->klass (), mem, size_in_bytes, weight, _allocated_outside_tlab, _thread);
239
+ HOTSPOT_GC_ALLOCOBJECT_SAMPLE (obj ()->klass ()->name ()->as_C_string (), size_in_bytes, weight);
240
+ }
241
+
242
+ if (hit_mark) {
243
+ // Tell tlab to forget bytes_since_last if we passed it to the heap sampler.
244
+ _thread->tlab ().set_jfr_sample_end (!_allocated_outside_tlab);
245
+ }
220
246
}
221
247
222
248
void MemAllocator::Allocation::notify_allocation_dtrace_sampler () {
@@ -264,7 +290,7 @@ HeapWord* MemAllocator::mem_allocate_inside_tlab_slow(Allocation& allocation) co
264
290
265
291
// We set back the allocation sample point to try to allocate this, reset it
266
292
// when done.
267
- allocation._tlab_end_reset_for_sample = true ;
293
+ allocation._tlab_end_reset_for_jvmti_sample = true ;
268
294
269
295
if (mem != nullptr ) {
270
296
return mem;
0 commit comments