Fix creation/initialization of TR::Options objects - #6580
Conversation
|
Jenkins build all |
|
See the CI failure. This PR is intended to address that failure, no? |
|
|
@0xdaryl The failure that occurs here is a separate issue that's still being investigated. But the issue linked in the description is solved, since |
|
@gita-omr I initialized it the same way the options are initialized in processOptionsJIT() ( But if it would be more appropriate in this particular situation to only initialize the |
Right, but that code does not seem safe to me... On another hand I agree that it should be consistent. @0xdaryl @mpirvu what do you think about initializing just the _options[] array in both places? |
|
is it ok for the linux_ppc-64_le to fail? |
Yup, that's being caused by a separate separate failure that's under investigation elsewhere |
|
I share @gita-omr's concerns about safety and correctness. I think we should do the correct and safe C++ thing here and either use a member initialization list or explicitly initialize them in the constructor. |
47923f5 to
b527932
Compare
|
@0xdaryl I've modified the constructor so that only the _options[] array (which holds the flag that was causing the problem due to being uninitialized) is being explicitly initialized to 0, rather than the entire TR::Options object. When you have a chance, could you review, and if everything is ok, please merge? |
b527932 to
58ff214
Compare
While I am not opposed to this, I would like to say that this solutions makes the code incrementally better, and allows a particular test to pass. I am guessing that the exact same issue can happen with one of the many other fields of TR_Options. |
58ff214 to
75efda9
Compare
|
|
||
| if (_jitCmdLineOptions) | ||
| memset(_jitCmdLineOptions, 0, sizeof(TR::Options)); | ||
| memset(_jitCmdLineOptions->_options, 0, sizeof(_options)); |
There was a problem hiding this comment.
Before this change the code was initializing the entire Options object to 0 (thus, all fields were set to 0).
After this change, only the _options array is initialized to 0 and the other fields may receive random values.
We need to keep this line or write a full constructor that initializes all fields to 0, not just the _options array.
There was a problem hiding this comment.
Yup, I can confirm that it's not enough to just initialize the _options array or even to use the default constructor. If we don't want to use memset we'll have to create a new constructor as you say.
The default constructor is actually used in the other branch of this if statement:
https://github.com/eclipse/omr/blob/a57ad601d6664d97958c59884c4d34a0ce2f960a/compiler/control/OMROptions.cpp#L2405
and it seems to work perfectly fine, but given how finnicky this bug was, I'm not sure if it's intentional or just a fluke.
There was a problem hiding this comment.
This memset is also not needed, because the contructor does it now inside.
There was a problem hiding this comment.
Do we not need to reset the _options array to all 0's? I thought that was the original purpose of using memset there in the first place. Otherwise there would have been no need for the if(_jitCmdLineOptions) branch at all
There was a problem hiding this comment.
The constructor with no arguments TR::Options() initializes the options array:
memset(_options, 0, sizeof(_options));.
Because of this, when we execute: _jitCmdLineOptions = new (PERSISTENT_NEW) TR::Options(); all fields are correctly initialized to 0, including the _options array.
There was a problem hiding this comment.
I am also not sure about this code. If processOptionsJIT is called only once , we don't need that memset. If it's called more than once and we would like to reinitialize the whole TR::Options object why do we only reinitialize _options[] ?
There was a problem hiding this comment.
To address the possibility of processOptionsJIT() being called more than once and perserve the original intended functionality of this part of the code, I have created an init() function for TR::Options that can be used both by the default constructor and in procesOptionsJIT() when _jitCmdLineOptions has already been allocated but needs to be reinitialized.
It ends up looking like this:
if (!_jitCmdLineOptions)
{
_jitCmdLineOptions = new (PERSISTENT_NEW) TR::Options();
_cmdLineOptions = _jitCmdLineOptions;
}
else
_jitCmdLineOptions->init();
c1cf564 to
0c9b608
Compare
|
I am wondering whether c++11 class memory initialization is supported on all our platforms. If it is, we could simplify the initialization code like this: |
|
@mpirvu unfortunately C++11 class memory initialization works for everything except AIX (for java 8 specifically) or zOS. So unless there's a workaround for that, it looks like we'll have to stick with an initialization list for the default constructor |
0c9b608 to
a78ba2f
Compare
a78ba2f to
d520cce
Compare
d520cce to
f6ec41d
Compare
f6ec41d to
fe5e0cc
Compare
b458e10 to
e1a87f2
Compare
There was a problem hiding this comment.
Sorry, I don't mean to cause so much churn. However, thinking more on this, I don't think doing self()->init() is safe.
Normally calling a member method using self()-> is the way to go. However, this is kind of special in that init() is being called from the constructor. If a downstream project was to extend OMR::Options and define its own init(), we'd technically end up calling the overriding init() before that subtype's constructor. I don't know what the consequence of something like that is, but we probably shouldn't allow that.
My recommendation is, In OMROptions.hpp, define the empty constructor as:
Options() { OMR::Options::init(); }
This way there's no ambiguity, and we're not initializing the part of the object that hasn't technically been constructed yet. You can see an example of this in OMR::Compilation:
https://github.com/eclipse/omr/blob/0db5d7c559b8b47754f1264f73f54c7ca8c7b374/compiler/compile/OMRCompilation.hpp#L857
e1a87f2 to
6075d72
Compare
|
@dsouzai no worries, it's a valid consideration that I haven't thought of. Just made the change now |
|
jenkins build all |
|
jenkins build zos |
gita-omr
left a comment
There was a problem hiding this comment.
We could replace memset with init() in processOptionsAOT as well.
|
Please also make sure that new members have not been added to TR::Options since this code was developed. |
- Create init() function that initializes all non-static data members of TR::Options and is called by default TR::Options constructor - Ensure constructors or init() are used to initialize TR::Options objects (rather than memset) Signed-off-by: midronij <jackie.midroni@ibm.com>
6075d72 to
697942d
Compare
|
Jenkins build all |
|
riscv failure is a timeout, similar to #6665 |
This contribution includes the following changes:
Additionally, this contribution fixes #6556