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

Reply via email to