Skip to content

Fix creation/initialization of TR::Options objects - #6580

Merged
dsouzai merged 1 commit into
eclipse-omr:masterfrom
midronij:compunittest_fix
Sep 2, 2022
Merged

Fix creation/initialization of TR::Options objects#6580
dsouzai merged 1 commit into
eclipse-omr:masterfrom
midronij:compunittest_fix

Conversation

@midronij

@midronij midronij commented Jun 20, 2022

Copy link
Copy Markdown
Contributor

This contribution includes the following changes:

  • Add all non-static data members to TR::Options default constructor's initializer list
  • Ensure _options array is initialized in all TR::Options constructors
  • Ensure constructors are used to create new TR::Options objects (rather than memset)

Additionally, this contribution fixes #6556

@midronij

Copy link
Copy Markdown
Contributor Author

@gita-omr

@0xdaryl

0xdaryl commented Jun 20, 2022

Copy link
Copy Markdown
Contributor

Jenkins build all

@0xdaryl

0xdaryl commented Jun 21, 2022

Copy link
Copy Markdown
Contributor

See the CI failure. This PR is intended to address that failure, no?

@babsingh

Copy link
Copy Markdown
Contributor

@midronij

Copy link
Copy Markdown
Contributor Author

@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 AbsVPValueTest passes

@gita-omr gita-omr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would not it be better to initialize just _options[] array instead of the whole TR::Options object which might include internal C++ metadata like vft pointer?

@midronij

midronij commented Jun 23, 2022

Copy link
Copy Markdown
Contributor Author

@gita-omr I initialized it the same way the options are initialized in processOptionsJIT() (_jitCmdLineOptions is a TR::Options pointer): https://github.com/eclipse/omr/blob/a57ad601d6664d97958c59884c4d34a0ce2f960a/compiler/control/OMROptions.cpp#L2410

But if it would be more appropriate in this particular situation to only initialize the _options[] array, I can do that instead

@gita-omr

Copy link
Copy Markdown
Contributor

@gita-omr I initialized it the same way the options are initialized in processOptionsJIT() (_jitCmdLineOptions is a TR::Options pointer):

https://github.com/eclipse/omr/blob/a57ad601d6664d97958c59884c4d34a0ce2f960a/compiler/control/OMROptions.cpp#L2410

But if it would be more appropriate in this particular situation to only initialize the _options[] array, I can do that instead

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?

@midronij midronij left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

Comment thread compiler/control/OMROptions.hpp Outdated
@midronij midronij changed the title Initialize all options to false in default TR::Options contructor Initialize all options to false in default TR::Options constructor Jul 13, 2022
@mpirvu

mpirvu commented Jul 13, 2022

Copy link
Copy Markdown
Contributor

is it ok for the linux_ppc-64_le to fail?

@mpirvu mpirvu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment thread compiler/control/OMROptions.hpp Outdated
@midronij

midronij commented Jul 13, 2022

Copy link
Copy Markdown
Contributor Author

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

@0xdaryl

0xdaryl commented Jul 18, 2022

Copy link
Copy Markdown
Contributor

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.

@midronij

midronij commented Aug 3, 2022

Copy link
Copy Markdown
Contributor Author

@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?

@mpirvu

mpirvu commented Aug 3, 2022

Copy link
Copy Markdown
Contributor

I've modified the constructor so that only the _options[] array

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.

Comment thread compiler/control/OMROptions.cpp Outdated

if (_jitCmdLineOptions)
memset(_jitCmdLineOptions, 0, sizeof(TR::Options));
memset(_jitCmdLineOptions->_options, 0, sizeof(_options));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This memset is also not needed, because the contructor does it now inside.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@gita-omr gita-omr Aug 31, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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[] ?

@midronij midronij Aug 31, 2022

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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();

@midronij
midronij force-pushed the compunittest_fix branch 3 times, most recently from c1cf564 to 0c9b608 Compare August 3, 2022 23:38
@mpirvu

mpirvu commented Aug 4, 2022

Copy link
Copy Markdown
Contributor

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:

         TR::OptionSet  *_optionSets {NULL};
          char *         _startOptions {NULL};
          char *         _envOptions {NULL};
          uint32_t      _options[TR_OWM+1] {0};
          ...

@midronij

midronij commented Aug 9, 2022

Copy link
Copy Markdown
Contributor Author

@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

@midronij midronij changed the title Initialize all options to false in default TR::Options constructor Fix creation/initialization of TR::Options objects Aug 11, 2022
@midronij

Copy link
Copy Markdown
Contributor Author

@mpirvu @0xdaryl I've corrected my changes to use an initialization list in the default TR::Options constructor instead of memset. When you have a chance, could you please review and (if everything looks ok) merge?

Comment thread compiler/control/OMROptions.cpp Outdated
Comment thread compiler/control/OMROptions.cpp Outdated
Comment thread compiler/control/OMROptions.cpp Outdated
Comment thread compiler/control/OMROptions.hpp Outdated
Comment thread compiler/control/OMROptions.cpp
@dsouzai dsouzai self-assigned this Aug 31, 2022
Comment thread compiler/control/OMROptions.hpp Outdated
@midronij
midronij force-pushed the compunittest_fix branch 2 times, most recently from b458e10 to e1a87f2 Compare August 31, 2022 20:19

@dsouzai dsouzai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@midronij

Copy link
Copy Markdown
Contributor Author

@dsouzai no worries, it's a valid consideration that I haven't thought of. Just made the change now

@dsouzai

dsouzai commented Aug 31, 2022

Copy link
Copy Markdown
Contributor

jenkins build all

@AdamBrousseau

Copy link
Copy Markdown
Contributor

jenkins build zos

@gita-omr gita-omr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could replace memset with init() in processOptionsAOT as well.

Comment thread compiler/control/OMROptions.cpp
@gita-omr

gita-omr commented Sep 1, 2022

Copy link
Copy Markdown
Contributor

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>
@gita-omr

gita-omr commented Sep 1, 2022

Copy link
Copy Markdown
Contributor

Jenkins build all

@dsouzai

dsouzai commented Sep 2, 2022

Copy link
Copy Markdown
Contributor

riscv failure is a timeout, similar to #6665

@dsouzai
dsouzai merged commit 26f101a into eclipse-omr:master Sep 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

compunittest AbsVPValueTest segfaults

7 participants