[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Synchronisation and Optimisation



Would it correct the problem if we made CSE kill all information about
fields (and arrays and globals) when it encounters a monitorexit
statement? That is, 
NaiveSideEffectTester: unitCanWriteTo( Unit u, Value v )
would return true if u was a monitorexit, and v was visible to other
threads?

Ondrej

On Fri, Apr 12, 2002 at 01:27:02PM +0100, Stephen Cheng wrote:
> > With regards to flushing values of an object, I believe this is the
> > responsiblity of the VM's implementation of the monitorenter & monitorexit
> > bytecodes. The actual implementation (assuming it is correct)
> > should have no
> > relevance to effects at the Jimple level.
> 
> After a bit of experimentation and some further thinking, I agree with
> Rhodes that it is not the responsibility of jimplication process to "flush".
> It is in fact the compiler's (or optimiser's) responsibility to ensure that
> all field caches are "flushed" whenever there is a monitorenter/monitorexit.
> I.e. next time the field is accessed again the compiler must generate code
> to get the field, rather than using a cached (local variable) copy of the
> field.
> 
> I have been investigating the CSE implementation. CSE eliminates repeated
> access to fields. It seems to pay no heed to monitorenter/monitorexit. The
> following example seems to indicate CSE is generating incorrect code in the
> presence of monitorenter/monitorexit. I have marked the possibly incorrect
> changes made by CSE after label0.
> 
> Original java:
> public class Ex3Sync {
> 
>     int sharedInt = 10;
> 
> 	void testSync3() {
>         int x = sharedInt + 3;
> 
>         synchronized (this) {
>             sharedInt = sharedInt + sharedInt + 1;
> 
>             System.out.println( "sharedInt =" + sharedInt);
>             System.out.println( "x =" + x);
>         }
> 
> 	}
> }
> 
> This is the Jimple code for the Non-optimised class file:
> soot.Main -j Ex3: (abstract)
>     void testSync3()
>     {
>         Ex3Sync r0, r1;
>         int i0, $i1, $i2, $i3, $i4, $i5, $i6;
>         java.io.PrintStream $r2, $r7;
>         java.lang.String $r3, $r4, $r5, $r6, $r8, $r9, $r10, $r11;
>         java.lang.Throwable $r12;
> 
>         r0 := @this;
>         $i1 = r0.sharedInt;
>         i0 = $i1 + 3;
>         r1 = r0;
>         entermonitor r1;
> 
>      label0:
>         $i2 = r0.sharedInt;
>         $i3 = r0.sharedInt;
>         $i4 = $i2 + $i3;
>         $i5 = $i4 + 1;
>         r0.sharedInt = $i5;
>         $r2 = java.lang.System.out;
>         $r3 = "sharedInt =";
>         $i6 = r0.sharedInt;
>         $r4 = java.lang.String.valueOf($i6);
>         $r5 = java.lang.String.valueOf($r4);
>         $r6 = $r3.concat($r5);
>         $r2.println($r6);
>         $r7 = java.lang.System.out;
>         $r8 = "x =";
>         $r9 = java.lang.String.valueOf(i0);
>         $r10 = java.lang.String.valueOf($r9);
>         $r11 = $r8.concat($r10);
>         $r7.println($r11);
> 
>      label1:
>         exitmonitor r1;
>         goto label3;
> 
>      label2:
>         $r12 := @caughtexception;
>         exitmonitor r1;
>         throw $r12;
> 
>      label3:
>         return;
> 
>         catch java.lang.Throwable from label0 to label1 with label2;
>     }
> 
> 
> This is jimple code for the optimised class file:
> 
> soot.Main -O -j Ex3Sync (Abstract)
> 
>     void testSync3()
>     {
>         Ex3Sync r0;
>         int i0, i1, $i2, $i3, $i4;
>         java.io.PrintStream $r1, $r6;
>         java.lang.String $r2, $r3, $r4, $r5, $r7, $r8, $r9, $r10;
>         java.lang.Throwable $r11;
> 
>         r0 := @this;
>         i0 = r0.sharedInt;
>         i1 = i0 + 3;
>         entermonitor r0;
> 
>      label0:
> >> Note here
> >>        $i2 = i0 + i0;
> >>        $i3 = $i2 + 1;
>         r0.sharedInt = $i3;
>         $r1 = java.lang.System.out;
>         $r2 = "sharedInt =";
>         $i4 = r0.sharedInt;
>         $r3 = java.lang.String.valueOf($i4);
>         $r4 = java.lang.String.valueOf($r3);
>         $r5 = $r2.concat($r4);
>         $r1.println($r5);
>         $r6 = java.lang.System.out;
>         $r7 = "x =";
>         $r8 = java.lang.String.valueOf(i1);
>         $r9 = java.lang.String.valueOf($r8);
>         $r10 = $r7.concat($r9);
>         $r6.println($r10);
> 
>      label1:
>         exitmonitor r0;
>         goto label3;
> 
>      label2:
>         $r11 := @caughtexception;
>         exitmonitor r0;
>         throw $r11;
> 
>      label3:
>         return;
> 
>         catch java.lang.Throwable from label0 to label1 with label2;
>     }
> 
> Note:
> CSE has changed the code from:
> 
>         ...
>         entermonitor r1;
> 
>      label0:
>         $i2 = r0.sharedInt;
>         $i3 = r0.sharedInt;
>         $i4 = $i2 + $i3;
>         $i5 = $i4 + 1;
>         r0.sharedInt = $i5;
>         ...
> 
> to:
>         ...
>         entermonitor r0;
> 
>      label0:
> >> Note here
> >>        $i2 = i0 + i0;
> >>        $i3 = $i2 + 1;
>         r0.sharedInt = $i3;
>         ...
> 
> In the optimised version, sharedInt = sharedInt + sharedInt + 1 would never
> use the value updated by another thread, in violation of the VM
> specification.
> 
> Regards,
> Stephen
>