On 16/09/2015 14:01, Caldarale, Charles R wrote: >> From: Mark Thomas [mailto:ma...@apache.org] >> Subject: Re: RV-Predict bugs > >> To re-cap. The assertion is that >> === >> String foo; >> doSomething() { >> if (foo == null) { >> foo = calculateNewValue(); >> } >> return foo; >> } >> === >> can be transformed (by the complier?) to >> === >> String foo; >> String bar; >> doSomething() { >> bar = foo; >> if (foo == null) { >> foo = calculateNewValue(); >> bar = foo; >> } >> return bar; >> } >> === > >> Ignoring re-ordering this transformation creates an obvious concurrency >> issue (foo is changed from null to non-null after its value is copied to >> bar and before foo is tested for null). > > Correct. That changed the original logic of the method, creating a timing > window that wasn't there before. In compiler language (see below), it > rematerialized a load for a shared memory location. > >> The questions I have are: > >> 1. Is such a transformation legal? I assume the answer is yes but I've >> been struggling to find the language in the JLS that permits this. Is it >> 17.4 "An implementation is free to produce any code it likes, as long as >> all resulting executions of a program produce a result that can be >> predicted by the memory model."? > >> 2. Why would something make a transformation like this? This brings us >> back to the question of theoretical issues vs. practical issues which >> helps us judge the severity of any given issue. > > 1. No (at least not in the real world). > > 2. Compiler bug. An analogous example is the one-time gcc error that > transformed > if (a == 0) a = 1; > into > temp = a; > if (temp == 0) temp = 1; > a = temp; > This caused immense havoc, besides being a performance killer. > > For reference, read the LLVM spec for concurrency handling: > http://llvm.org/docs/Atomics.html > In particular, this section on instruction ordering: > http://llvm.org/docs/Atomics.html#atomic-orderings > Note the difference in implementation between handling shared variables in > C/C++ (NotAtomic) and shared variables in Java (Unordered). > > (For those not familiar with LLVM, it's the compilation tool chain used for > OS X, iOS, Android, PS4, and many other platforms.) > > The key bit of information pertinent to Java is this: > > "In terms of the optimizer, this prohibits any transformation that transforms > a single load into multiple loads, transforms a store into multiple stores, > narrows a store, or stores a value which would not be stored otherwise. Some > examples of unsafe optimizations are narrowing an assignment into a bitfield, > *rematerializing a load*, and turning loads and stores into a memcpy call. > Reordering unordered operations is safe, though, and optimizers should take > advantage of that because unordered operations are common in languages that > need them." > > The above may go beyond the theoretical limitations of the memory model, but > is representative of what compilers must do in order to generate workable > programs in the real world. This isn't academia, it's business. > > I think I'm done here.
Thanks Chuck. Your input is much appreciated. Thanks too to everyone else who has contributed to this thread. I know I've learned a lot from it and I hope others have as well. I think this puts the transformation issue in the same category as re-ordering. In theory compilers / hardware can do this and still be compliant with the JLS/JMM but in practice none do. Mark --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org