-
Notifications
You must be signed in to change notification settings - Fork 415
Fix choice of global vs block constraints in addKnownObjectConstraints #7621
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
This function created block constraints most of the time, but it would instead create a global constraint in the case of a constant string or a known object that's an instance of java/lang/Class. Now it takes a boolean parameter isGlobal, which it uses to decide whether the new constraint should be a global constraint. When called from constrainNewlyFoldedConst(), a global constraint can be created when the folding was based only on global constraints, which is similar to the way we already handle integral and null constants. This change will be important for const refs (coming later), since otherwise we could create a global constraint based on the symref of a const ref load that was just folded based on a block constraint, and the load might share its value number with others, e.g. if it was originally an auto load. When called from the VP handlers for aload and aloadi, it will now always create a block constraint. In these cases, it's tempting to try to create global constraints more often, since static and shadow loads will generally have been assigned fresh value numbers due to the possibility of concurrent writes from other threads. However, it isn't clear that it should always be safe to do so. For example, consider a shadow that we know to be immutable (not merely final). Loads of this shadow could share a value number whenever their base addresses do. I don't know whether any shadow is currently allowed to share its value number in this way, but a truly immutable shadow should be able to. So in this scenario there could be a single value number shared by multiple loads of the immutable shadow at different points. If transformIndirectLoadChain() could improve one of them based on path-sensitive knowledge of the base address, then the resulting improved load could be observed later on in the aloadi handler, and if it created a global constraint, it would inappropriately also constrain the other load. If that scenario were to play out with const refs (coming later), then transformIndirectLoadChain() would instead change the indirect load into a direct load, so the aload handler should be conservative as well.
|
@vijaysun-omr, could you please review? |
|
Could you please say a bit more (say a couple more sentences) about
i.e. in this situation of an immutable load that has the base address being identical, why is it inappropriate to constrain the other load ? |
|
Jenkins build all |
|
It's inappropriate to constrain the other load because the hypothetical transformation was based on path-sensitive information about the base address (a block constraint), and that information may not hold elsewhere, i.e. it may not hold at the other load, e.g.: The first load (in the constant case) should be folded without affecting the other one (Edited for brevity) |
|
I see, the value of the field may be different on different paths depending on the base value on that path. So, while it is fixed on all those paths, the fixed value may be different. |
This function created block constraints most of the time, but it would instead create a global constraint in the case of a constant string or a known object that's an instance of
java/lang/Class.Now it takes a boolean parameter
isGlobal, which it uses to decide whether the new constraint should be a global constraint.When called from
constrainNewlyFoldedConst(), a global constraint can be created when the folding was based only on global constraints, which is similar to the way we already handle integral and null constants. This change will be important for const refs (coming later), since otherwise we could create a global constraint based on the symref of a const ref load that was just folded based on a block constraint, and the load might share its value number with others, e.g. if it was originally an auto load.When called from the VP handlers for
aloadandaloadi, it will now always create a block constraint. In these cases, it's tempting to try to create global constraints more often, since static and shadow loads will generally have been assigned fresh value numbers due to the possibility of concurrent writes from other threads. However, it isn't clear that it should always be safe to do so.For example, consider a shadow that we know to be immutable (not merely final). Loads of this shadow could share a value number whenever their base addresses do. I don't know whether any shadow is currently allowed to share its value number in this way, but a truly immutable shadow should be able to. So in this scenario there could be a single value number shared by multiple loads of the immutable shadow at different points. If
transformIndirectLoadChain()could improve one of them based on path-sensitive knowledge of the base address, then the resulting improved load could be observed later on in thealoadihandler, and if it created a global constraint, it would inappropriately also constrain the other load.If that scenario were to play out with const refs (coming later), then
transformIndirectLoadChain()would instead change the indirect load into a direct load, so thealoadhandler should be conservative as well.