On 28/09/2016 11:24 PM, Peter Levart wrote:
On 09/28/2016 03:05 PM, David Holmes wrote:
On 28/09/2016 10:44 PM, Peter Levart wrote:
Hi,
According to discussion here:
http://cs.oswego.edu/pipermail/concurrency-interest/2016-September/015414.html
it seems compact strings introduced (at least theoretical) non-benign
data race into String.hasCode() method.
Here is a proposed patch:
http://cr.openjdk.java.net/~plevart/jdk9-dev/8166842_String.hashCode/webrev.01/
I'm far from convinced that the bug exists - theoretical or otherwise
- but the "fix" is harmless.
When we were working on JSR-133 one of the conceptual models is that
every write to a variable goes into the set of values that a read may
potentially return (so no out-of-thin-air for example). happens-before
establishes constraints on which value can legally be returned - the
most recent. An additional property was that once a value was
returned, a later read could not return an earlier value - in essence
once a read returns a given value, all earlier written values are
removed from the set of potential values that can be read.
That would be a nice property, yes.
Your bug requires that the code act as-if written:
int temp = hash;
if (temp == 0) {
hash = ...
}
return temp;
and I do not believe that is allowed.
David
Well, I can't find anything like that in JMM description. Could you
point me to it? Above example only reads once from hash. The code in
question is this:
if (hash == 0) { // 1st read
hash = ...
}
return hash; // 2nd read
And the bug requires the code to act like:
int temp2 = hash; // 2nd read
int temp1 = hash; // 1st read
if (temp1 == 0) {
return (hash = ...);
}
return temp2;
Given hash is not a volatile field there is nothing that requires the
compiler to emit code that reads it twice - of course javac will issue
getfields as per the source code.
So the compiler is of course allowed to read it twice, but you then want
it to reorder those reads such that the second use uses the value of the
first read, and the first use uses the value of the second read.
I recall discussions of such perverse compiler behaviour in the past. :(
Is this allowed?
Sadly yes. What we ended up with in JLS Ch17 permits this - it is a
variation of the aliasing example in 17.4.
There are places where the formalization of the JMM "threw the baby out
with the bath water" IMHO. Some of the less formal descriptions made far
more sense - like the notion of there being a set of values a read may
return, and how happens-before constrains that, and how once a value is
returned you cant then "read" an earlier value. <sigh>
Thanks,
David
Regards, Peter
For the bug:
https://bugs.openjdk.java.net/browse/JDK-8166842
JDK 8 did not have this problem, so no back-porting necessary.
Regards, Peter