-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8285364: Remove REF_ enum for java.lang.ref.Reference #8332
Conversation
👋 Welcome back ayang! A progress list of the required criteria for merging this PR into |
@albertnetymk The following labels will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
@@ -214,7 +214,7 @@ void MetaspaceObjectTypeConstant::serialize(JfrCheckpointWriter& writer) { | |||
static const char* reference_type_to_string(ReferenceType rt) { | |||
switch (rt) { | |||
case REF_NONE: return "None reference"; | |||
case REF_OTHER: return "Other reference"; | |||
case REF_REFERENCE: return "j.l.r.Reference"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think either "Reference" or "java.lang.ref.Reference" would be better than the abbreviation.
@@ -214,7 +214,7 @@ void MetaspaceObjectTypeConstant::serialize(JfrCheckpointWriter& writer) { | |||
static const char* reference_type_to_string(ReferenceType rt) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function seems misplaced here. Seems like it belongs with the ReferenceType type. (This could be a followup RFE.)
@@ -28,7 +28,7 @@ | |||
|
|||
public enum ReferenceType { | |||
REF_NONE ("None reference"), // Regular class | |||
REF_OTHER ("Other reference"), // Subclass of java/lang/ref/Reference, but not subclass of one of the classes below | |||
REF_REFERENCE ("j.l.r.Reference"), // java/lang/ref/Reference, super class of the following |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again here, don't abbreviate the package path.
Do we even need REF_OTHER / REF_REFERENCE? I see a bunch of ShouldNotReachHeres and then set_reference_type(REF_OTHER). Maybe the latter could be changed to REF_NONE? |
The relevant code is: ClassFileParser::post_process_parsed_stream(...) {
...
_rt = (NULL ==_super_klass) ? REF_NONE : _super_klass->reference_type();
}
InstanceKlass::allocate_instance_klass(...) {
...
if (REF_NONE == parser.reference_type()) {
...
} else {
// reference
ik = new (loader_data, size, THREAD) InstanceRefKlass(parser);
}
} The |
That's unfortunate. The allocate_instance_klass function can easily be changed to also check if class_name == vmSymbols::java_lang_ref_Reference(). But even with that, make images fails. I wasn't a fan of the REF_REFERENCE name, since it isn't really that descriptive to me, and had hoped to fine a way to just get rid of it instead of finding a better name. |
|
Using REF_SOFT seems too hacky. If we rewrite the initialization a bit we can make this work. See suggested change in: |
Just to put all alternatives on the table. The use of // in vmClasses::resolve_all
vmClasses::Reference_klass()->set_reference_type(REF_SOFT);
// setting ref-type of Soft/Weak/Final/Phantom
vmClasses::SoftReference_klass()->set_reference_type(REF_SOFT);
...
vmClasses::Reference_klass()->set_reference_type(REF_NONE); I have no particular preference. What does everyone think? |
I also think using REF_SOFT like that is overly hacky. I think there is still a bootstrapping weirdness, whether using REF_REFERENCE |
Signed-off-by: Albert Yang <albert.m.yang@oracle.com>
I have taken the commit from Stefan and updated the title. |
/contributor add stefank |
@albertnetymk |
I think we can fix the bootstrapping kludge with something like this: With this patch, we'll always have the correct _reference_type after the InstanceRefKlass constructor has run. (Patch has not gone through full testing yet) |
ik = new (loader_data, size, THREAD) InstanceKlass(parser); | ||
} | ||
} else { | ||
if (parser.is_java_lang_ref_Reference_subclass()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm having a really hard time understanding this. java.lang.Reference now doesn't have any REF_OTHER type set. I didn't realize that a java.lang.Reference instance is a plain InstanceKlass, and not an InstanceRefKlass. Is this right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I was also surprised by this. The java.lang.ref.Reference Klass is only an InstanceKlass, not an InstanceRefKlass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, please add a short comment in the is_java_lang_ref_Reference_subclass function that this is the case, now that we've learned this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of documenting this surprise, how about removing it by extending this method to cover all subtypes of j.l.r.Reference
?
bool ClassFileParser::is_java_lang_ref_Reference_or_subclass() const {
if (_super_klass == NULL) {
return false;
}
if (_class_name == vmSymbols::java_lang_ref_Reference()) {
return true;
}
if (_super_klass->name() == vmSymbols::java_lang_ref_Reference()) {
return true;
}
return _super_klass->reference_type() != REF_NONE;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is better.
@albertnetymk This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 111 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
Signed-off-by: Albert Yang <albert.m.yang@oracle.com>
I have taken "Rework reference type initialization" from Stefan and added comments on a potential surprise that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are further cleanups possible if we didn't have REF_NONE and InstanceKlass didn't have a reference type. But there are a number of uses of InstanceKlass::reference_type. Doing anything along those lines (assuming it's deemed worthwhile to do so) can be done in a followup RFE.
return rt; | ||
} | ||
|
||
// Bootstrapping: this is either of the four direct subclasses of java.lang.ref.Reference |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/either of the four/one of the/. In particular remove "four" else, someday, finalization will finally be GC'd and this comment will need to be noticed and updated.
@@ -496,7 +494,7 @@ InstanceKlass::InstanceKlass(const ClassFileParser& parser, KlassKind kind) : | |||
_itable_len(parser.itable_size()), | |||
_nest_host_index(0), | |||
_init_state(allocated), | |||
_reference_type(parser.reference_type()), | |||
_reference_type(REF_NONE), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is initializing _reference_type
to the wrong value for a InstanceRefKlass
object, which then needs to reset it in the derived constructor. Why not get the reference type from the parser? The (currently file-scoped static) determine_reference_type function in instanceRefKlass.cpp doesn't have any dependency on the klass object being constructed, just the parser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current approach limits the knowledge of non-strong ref types to instanceRefKlass
file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The _reference_type
used to be initialized correctly in most cases, but
needed fixing up for a few cases during bootstrapping. With this change it is
never initialized correctly for Reference subtypes and always needs an
initialization kludge for them. That's not an improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_reference_type
always gets the correct value after the constructor is run. The member initializer list just follows the convention of having all fields set. One could move this field inside the constructor body to ensure this field is set only once.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current approach limits the knowledge of non-strong ref types to
instanceRefKlass
file.
The mechanism used to compute the correct reftype is purely derived from the
parser, and to me looks like "parsing". So I think it would be better placed
with the parser. And that would also remove the need for the two-step
initialization of the InstanceKlass member.
With that in mind, I think the file scoped function determine_reference_type
in instanceRefKlass.cpp should instead be an ordinary public member function
ClassFileParser::reference_type() const
(with appropriate adjustment of it's
implementation), called by the InstanceKlass constructor to initialize
_reference_type
.
Associated with that are some other changes:
- The new InstanceRefKlass::set_reference_type is no longer needed.
- The new ClassFileParser::super_reference_type and
ClassFileParser::is_java_lang_ref_Reference_subclass don't need to be public.
(Assuming they exist at all after adjustment of ClassFileParser::reference_type.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The _reference_type used to be initialized correctly in most cases, but
needed fixing up for a few cases during bootstrapping. With this change it is
never initialized correctly for Reference subtypes and always needs an
initialization kludge for them. That's not an improvement.
I don't agree that this is a kludge. This is quite common in HotSpot, and the code is quite understandable. It's far better than the initialization kludge the code had before this patch.
I'd like to suggest that we go with the proposed patch, and consider the Kim's latest proposal as a follow-up RFE. That way we can make progress on this RFE, and then weigh the pros and cons of this suggestion separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talked to Albert. He's already created a patch for this, so I retract my objection to this blocking of the PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revised as Kim suggested.
@@ -574,11 +574,16 @@ class InstanceKlass: public Klass { | |||
|
|||
// reference type | |||
ReferenceType reference_type() const { return (ReferenceType)_reference_type; } | |||
|
|||
protected: | |||
// Only used by the InstanceRefKlass constructor | |||
void set_reference_type(ReferenceType t) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function wouldn't be needed at all if the reference type was properly initialized.
} | ||
|
||
return _super_klass->reference_type() != REF_NONE; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stylistically, I'd prefer an if-ladder here. I might also swap the reference-type check and the name check, so the for-bootstrapping name check case being last (with a comment to that effect).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These if-checks more or less mirror the type hierarchy, Object -> Reference -> Soft|Weak... -> ...
. Then, walking down the type hierarchy using the early-return style here makes more sense to me.
@albertnetymk This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
Just a couple of minor "naming" comments, that you can address or not.
// klass requiring special treatment in ref-processing. The abstract | ||
// j.l.r.Reference cannot be instantiated so doesn't partake in | ||
// ref-processing. | ||
return is_java_lang_ref_Reference_subclass(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be the only call to this function, so the definition could just be inlined here and drop the separate function.
@@ -561,7 +562,9 @@ class ClassFileParser { | |||
const Symbol* class_name() const { return _class_name; } | |||
const InstanceKlass* super_klass() const { return _super_klass; } | |||
|
|||
ReferenceType reference_type() const { return _rt; } | |||
bool is_instance_ref_klass() const; | |||
ReferenceType determine_reference_type() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer this was just called reference_type
. Like much of the API here, this is about a property of the designated klass. That it's no longer just a data member accessor is of no particular importance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. +1 on Kim's latest comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scratch my last comment. This crashes in GHA, because determine_reference_type() now gets called from non-InstanceRefKlass InstanceKlasses, which is wasn't written to support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
Thank you for the help and review. /integrate |
Going to push as commit 2961b7e.
Your commit was automatically rebased without conflicts. |
@albertnetymk Pushed as commit 2961b7e. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
Simple rename and some comments update.
Test: build
Progress
Issue
Reviewers
Contributors
<stefank@openjdk.org>
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/8332/head:pull/8332
$ git checkout pull/8332
Update a local copy of the PR:
$ git checkout pull/8332
$ git pull https://git.openjdk.org/jdk pull/8332/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 8332
View PR using the GUI difftool:
$ git pr show -t 8332
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/8332.diff