RFR: 8296469: Instrument VMError::report with reentrant iteration step for register and stack printing [v2]

Thomas Stuefe stuefe at openjdk.org
Tue Nov 29 12:18:38 UTC 2022


On Mon, 21 Nov 2022 06:01:39 GMT, Axel Boldt-Christmas <aboldtch at openjdk.org> wrote:

> Added some limitations on reentry of a reentrant step. It will now break the inner loop if:
> 
>     * It is the fourth time reentering this step
> 
>     * It is the eight time reentering any reentrant step
> 
>     * The stack headroom is less than 64K
> 
>     * A timeout has been issued
> 
> 
> The post loop logic of a reentrant step is given another timeout window. Currently all it does is make sure there are line breaks after the step output, but I imagine this can be useful incase some reentrant step logic is used where the loop builds up some data structure and the post logic prints it.
> 
> All of the limit constants are just picked rather ad-hoc. Would be nice to have some extra feedback on this.

I think the approach is better, but I'm not a big fan of the broadened os interface and the fact that error-handling-specifics now leak into the os interface.

How about letting the print function fill in an opaque continuation object instead? Something like:


// Print register information; optionally re-startable. If (*continuation_info) is null,
// register printing starts with the first register, otherwise beyond whatever point
// it had been interrupted before.
void os::print_register_info(const ucontext_t* context, outputStream* st, void** continuation_info);


`continuation_info` can have any shape or form the platform-specific implementation wants. It does not have to be visible or known on the outside. It can exist as a struct only in the os_xxx.cpp file. Or, the platform could just hide an integer in the pointer and use it as restart point.

The standard `os::print_register_info(const ucontext_t*, outputStream*)` can then be implemented with a dummy continuation info that does nothing:


os::print_register_info(const ucontext_t* c, outputStream* st) {
  void* info;
  os_print_register_info(c, st, &info);
}


If that is too C-ish for you, there can be a C++ equivalent via runtime polymorphy. In any case, the charm would be that you can re-start register printing without having to know specific implementation details. You just hand in the continuation object. In a very primitive form, without the need for further STEP macros, that could even look like this:


void* print_reg_continuation_info = nullptr;
...
STEP(print_register_info_attempt_1)
{ os::print_register_info(context, st, &print_reg_continuation_info); }
STEP(print_register_info_attempt_2)
{ os::print_register_info(context, st, &print_reg_continuation_info); }
STEP(print_register_info_attempt_3)
{ os::print_register_info(context, st, &print_reg_continuation_info); }

(for this simple approach to work, os::print_register_info() would have recognize a completed printing by the content of continuation info).

In theory, we could use a similar pattern for call stack printing too.

----

As a side note, I have not been idle since print_register_info() not working bugs me too. I found that many reasons for it not working are caused by only a few bugs. oopDesc::print_on() could do a lot more error checking before printing Klass* for instance. And we also could do more error checking when printing object array elements. I have a patch open, but won't make it before JDK 20 freeze, and probably not before my holidays either. If someone else wants to do it, that would be fine with me too.

Cheers, Thomas

-------------

PR: https://git.openjdk.org/jdk/pull/11017


More information about the hotspot-dev mailing list