-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Generalize barrier info on nodes. Figure out GC specific properties i… #1015
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
Conversation
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.
Should this be named BarrierUtils?
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, that is a good point! I will change it.
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 could be a static method on enum BarrierPrecision, but it could just as easily be with the BarrierType code.
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.
Putting it in the enum sounds good. I'd rather not put it in the BarrierType class, because this is exposed everywhere.
I also have an idea how to reliably determine object vs. primitive. Stay tuned.
|
I just pushed a change that is closer to the original design, but renames and adds BarrierType values: IMPRECISE becomes FIELD, PRECISE becomes ARRAY, UNKNOWN means we don't know (and GCs treat it as array/precise) and REFERENT denotes a Reference.referent access. Initializing stores and useDeferredInitBarriers are now handled in the GC backends, rather than in the compiler. This still doesn't provide the implementation for load barriers, but it can easily be used for that. I'll do that in a followup PR. |
|
@rkennke Not to confuse your life, but SubstrateVM has an annotation The I don't know if that changes the names you want to give to |
|
@Peter-B-Kessler oook, good to know, thanks! It sounds like I can safely ignore it for now (and not sure if the previous names have been any more useful either) :-) I'm about to do some SubstrateVM/GC work soon anyway (mostly unrelated to this here), and then I guess I will get a better understanding of the situation there. |
|
The thing to remember about the current SubstrateVM garbage collector is the (lack of) motivation for it. The idea of SubstrateVM was fast startup for small, short-running, services. In the best of all possible worlds, the application runs to completion without needing any collection. But we had to have some garbage collector, so a serial, stop-the-world, copying collector was "good enough". For now. If your application has gigabyte heaps, you don't need fast startup, and you are probably better off using HotSpot with your favorite (:-) collector. The other constraint was running in environments where large blocks of contiguous memory are not available, which is why the current SubstrateVM heap comes in "chunks". That also means one does not have to specify a maximum heap size, and one can change the heap shape at runtime. Also, pinning objects is ... easier. If you have questions about the current SubstrateVM collector and heap: ask away. |
|
My application doesn't have GBs of heaps. I'm looking at 100-200MB. I guess it's too big/too long-running to not fit the original assumption, but not big enough to warrant full hotspot+GCs. Let's take that discussion to the mailing lists though... ;-) This PR looks good to integrate (at least, CI-wise). Do the latest changes resolve your concerns? |
|
@Peter-B-Kessler BTW, if you expect that an application dies before even hitting a single GC, you might want an even simpler GC: a single-space, sliding GC that triggers on memory exhaustion. This way you'd make best use of available memory, and not pay the runtime overhead of barriers. ;-) |
|
I suspect Peter (or, more importantly, Graal users) probably wants an insurance policy as well as low GC overhead. |
|
The adoption of Epsilon for those sorts of uses is an indication that this is a more feasible proposal than it sounds like. And indeed, under closed world assumption, when you know how much you're going to allocate, and lifetime is short and limited anyway, this might indeed be your best bet. |
|
Fortunately/Unfortunately, the GraalVM runtime compiler itself is written in Java, and allocates a lot of memory, and leaves behind a lot of garbage. So we chose a two-generation scavenger as a compromise. The epsilon garbage collector might be useful for when we can ahead-of-time compile the whole application. Eliminating barriers would be one advantage. If we could eliminate safepoint checks that would win, too. Lots of opportunities to win the "most improved VM" award. :-) |
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 correct new barrier type to use in this class (both changes) is ARRAY: In Substrate VM's single threaded mode, the thread local variables are stored in a normal Java array that resides in the image heap.
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 should probably be an implementation detail of LoadVMThreadLocalNode instead of being a constructor parameter.
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 don't think so. VMThreadMTFeature.java passes NONE there. I'll change it to ARRAY for the VMThreadSTFeature.
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.
Changed to ARRAY in latest push.
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 difference between the MT and ST feature is correct: in multi-threaded (MT) mode, the thread local variables are in the thread descriptor is in C memory, i.e., no barriers needed. In single-threaded (ST) mode, the thread local variables are in the Java heap in a regular array, i.e., array write barriers are needed.
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.
So the barrier kind is really a property of VMThreadLocalInfo?
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.
No, the barrier kind is a property of how the thread local storage is implemented. Which is all encapsulated in this class, so defining the barrier kind in this class is correct.
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.
Sounds good.
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.
It's not ideal to have a barrier type that is only used by one specific VM, the HotSpot VM, in the VM-independent part of Graal. Maybe it is a bad idea in the first place to have barrier types as an enum here, and not just define an empty marker interface here and have the actual value definitions in VM-specific code.
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 a clear set in the core would better than multiple different definitions but I agree this naming is very HotSpot specific. Maybe this would be better called WEAK_FIELD to generalize it?
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.
We could do a split: some definitions (definitely UNKNOWN, but maybe also FIELD and ARRAY) in the platform independent part, and others like REFERENT in HotSpot specific code.
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.
Why is REFERENT HotSpot specific since it's a field in a (non-HotSpot specific) JDK class?
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 guess the field is defined in the Reference class because it simplified the HotSpot implementation (unfortunately the JDK and the VM are not as decoupled as they should be). But the field has the interesting comment /* Treated specially by GC */ ;-)
So your argument is that the bad JDK/VM separation means that Graal also does not need to separate it out into VM independent code. Which is a valid argument.
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.
If SVM adds a G1 style collector it will need the exact same special handling. The read from referent needs special handling because it's reading from a weak field. Even if the field were hidden in some way the actual read would still need this work.
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.
Currently, only Shenandoah and G1, probably ZGC (not sure) need to know about it, they are all Hotspot-only. Current SVM GCs don't currently need to know about it, but it surely belongs into the GC interface anyway (even if ignored by specific implementations). I'm fine with renaming it to WEAK_FIELD, this should be generic enough?
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 so.
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.
Latest push fixes 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.
I think you need to rearrange these tests. type.isArray() must be tested before type.isAssignableFrom(objectArrayType) to find the ARRAY case.
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.
Latest push should fix it.
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 needs a type != null guard.
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.
Should be fixed.
|
The travis gate failed because of a minor indenting problem. There's also a problem our internal gate found that didn't show up here. There are a bunch of failures when running with -Dgraal.VerifyPhases=true that look like this: You can just do something like |
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.
Wrong indent.
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.
Should be fixed.
|
Hello Roman Kennke, thanks for contributing a PR to our project! We use the Oracle Contributor Agreement to make the copyright of contributions clear. We don't have a record of you having signed this yet, based on your email address rkennke -(at)- linux -(dot)- fritz -(dot)- box. You can sign it at that link. If you think you've already signed it, please comment below and we'll check. |
|
Hi @rkennke can you please change the commits in this PR to use your RedHat email address since that it what is registered in the OCA database consulted by @graalvmbot . |
Sorry, I don't know how to do that. git rebase doesn't seem to work on merge commits, which is the one with wrong email. |
|
I don't know how to fix the author in merge commits either so I think squashing all the commits in the PR is probably the right way to go. However, please don't open a new PR - just force push your squashed commit to this PR (i.e., |
Are you sure? force-pushing to a branch with PR is discouraged by github: Also, I am not sure how to do that either. Interactively 'rebase' the branch, thereby deleting all the changesets, and then commit the squashed changeset? Seems easier to create a new branch+PR, link back to this here, and start with clean slate? |
|
I've force pushed often to GitHub PRs with no negative consequences. As far as I know, the best reason to avoid force pushing is when you are actively collaborating with others on a PR (as in they are also pushing commits to the PR - not just reviewing it). |
|
As long as you don't force push master, everything is fine ;-). The following should work for squashing (make a local backup of the changesets in case something gets messed up): |
|
Worked like a charm! Thanks! |
9c588cd to
bbb272a
Compare
|
Ok, I think I messed it up. Rebased and re-committed the whole thing as single changeset. I hope that works now. |
|
Hmm, it looks like I killed the travis checker somehow. How should I proceed? Sorry for messing things up so badly... |
|
That is fine. For this type of change, we will anyway have to run much more tests than just the Travis checker. |
|
Ok, cool. Travis seems kaputt anyway, my other PR (#1117) travis job seems stuck since a while already... Let me know if you find anything that requires fixing. Thanks! |
|
I grabbed your latest bits and they pass our internal gates so it all looks good. We're waiting to push it until the GraalVM freeze is over at the end of the month. |
|
Perfect, thanks! |
|
It looks like this has already been integrated: Closing the PR. |
|
Sorry, it usually detects the merge of you commit and automatically closes it. Not sure why it didn't detect it in this case. |
As discussed here:
https://mail.openjdk.java.net/pipermail/graal-dev/2019-February/005634.html
I would like to generalize the GC barrier information that we carry around in nodes. Instead of the rather GC specific PRECISE vs IMPRECISE information, I'd prefer to record whether or not the access is to array element or a field, and whether or not the access is to primitive field or object field. We also need to know if it's the special access to a Reference.referent field.
I tried to determine the primitive vs. object field information in the backend from the JavaKind of the node (or in case of writes, its value), but it turns out this not always consistent with the information carried in BarrierType. I suspect that object writes can sometimes be generated that don't require a barrier?
Notice that the implementation covers the need for current barriers. This means it's equivalent to what was there before. It's not yet generating the correct information for loads, yet (except for the referent field access), because no GC currently needs it. I will get to this later, when adding support for Shenandoah and/or ZGC, which will require this sort of information. I'd rather not do this blindly. ;-)