RFR(10)(XS): JDK-8171365: nsk/jvmti/scenarios/events/EM04/em04t001: many errors for missed events
Chris Plummer
chris.plummer at oracle.com
Mon Jun 5 20:30:05 UTC 2017
On 6/5/17 8:56 AM, Ioi Lam wrote:
> Hi Chris,
>
>
> On 6/2/17 11:54 AM, Chris Plummer wrote:
>> Hello,
>>
>> [I'd like a compiler team member to comment on this, in addition to
>> runtime or svc]
>>
>> Please review the following:
>>
>> https://bugs.openjdk.java.net/browse/JDK-8171365
>> http://cr.openjdk.java.net/~cjplummer/8171365/webrev.00/
>>
>> The CR is closed, so I'll describe the issue here:
>>
>> The test is making sure that all |JVMTI_EVENT_DYNAMIC_CODE_GENERATED|
>> events that occur during the agent's OnLoad phase also occur when
>> later GenerateEvents() is called. GenerateEvents() is generating some
>> of the events, but most are not sent. The problem is
>> CodeCache::blobs_do() is only iterating over NMethod code heaps, not
>> all of the code heaps, so many code blobs are missed. I changed it to
>> iterate over all the code heaps, and now all the
>> |JVMTI_EVENT_DYNAMIC_CODE_GENERATED|events are sent.
>>
>> Note there is another version of CodeCache::blobs_do() that takes a
>> closure object instead of a function pointer. It is used by GC and I
>> assume is working properly by only iterating over NMethod code heaps,
>> so I did not change it. The version that takes a function pointer is
>> only used by JVMTI for implementing GenerateEvents(), so this change
>> should not impact any other part of the VM. However, I do wonder if
>> these blobs_do() methods should be renamed to avoid confusion since
>> they don't (and haven't in the past) iterated over the same set of
>> code blobs.
>>
> Yes, I think these two function would indeed be confusing. The second
> variant also does a liveness check which is missing from the first one:
>
> 621 void CodeCache::blobs_do(void f(CodeBlob* nm)) {
> 622 assert_locked_or_safepoint(CodeCache_lock);
> 623 FOR_ALL_HEAPS(heap) {
> 624 FOR_ALL_BLOBS(cb, *heap) {
> 625 f(cb);
> 626 }
> 627 }
> 628 }
>
> 664 void CodeCache::blobs_do(CodeBlobClosure* f) {
> 665 assert_locked_or_safepoint(CodeCache_lock);
> 666 FOR_ALL_NMETHOD_HEAPS(heap) {
> 667 FOR_ALL_BLOBS(cb, *heap) {
> 668 if (cb->is_alive()) {
> 669 f->do_code_blob(cb);
> 670 #ifdef ASSERT
> 671 if (cb->is_nmethod())
> 672 ((nmethod*)cb)->verify_scavenge_root_oops();
> 673 #endif //ASSERT
> 674 }
> 675 }
> 676 }
> 677 }
>
> The two function's APIs are equivalent, since CodeBlobClosure has a
> single function, so I think it's better to stick with one API, i.e.
> replace the function pointer with CodeBlobClosure
>
> class CodeBlobClosure : public Closure {
> public:
> // Called for each code blob.
> virtual void do_code_blob(CodeBlob* cb) = 0;
> };
>
> For consistency, maybe we should change the first version to
>
> CodeCache::all_blobs_do(CodeBlobClosure* f)
>
> and the second to
>
> CodeCache::live_nmethod_blobs_do(CodeBlobClosure* f)
>
> Thanks
> - Ioi
Hi Ioi,
Thanks for the review.
I don't see a good reason why a closure should be used here. There's no
state belonging to the iteration that needs to be accessed by the
callback. It's just a simple functional callback, so it seems converting
this to use a closure is overkill. I'd have to say the same is true of
the closure version of do_blobs also. Why use a closure for that?
BTW, there also:
void CodeCache::nmethods_do(void f(nmethod* nm)) {
assert_locked_or_safepoint(CodeCache_lock);
NMethodIterator iter;
while(iter.next()) {
f(iter.method());
}
}
So another functional version of a blob iterator. It's not real clear to
me all the ways this differs from the closure version of blobs_do(),
other than it allows you to provide an nmethod as a starting point for
the iteration.
Chris
>
>> thanks,
>>
>> Chris
>>
>> https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html#DynamicCodeGenerated
>>
>
More information about the hotspot-dev
mailing list