RFR: 8291555: Replace stack-locking with fast-locking
Roman Kennke
rkennke at openjdk.org
Thu Oct 6 07:47:16 UTC 2022
On Tue, 16 Aug 2022 15:47:58 GMT, Robbin Ehn <rehn at openjdk.org> wrote:
> > @robehn or @dholmes-ora I believe one of you mentioned somewhere (can't find the comment, though) that we might need to support the bytecode sequence monitorenter A; monitorenter B; monitorexit A; monitorexit B; properly. I have now made a testcase that checks this, and it does indeed fail with this PR, while passing with upstream. Also, the JVM spec doesn't mention anywhere that it is required that monitorenter/exit are properly nested. I'll have to fix this in the interpreter (JIT compilers refuse to compile not-properly-nested monitorenter/exit anyway).
> > See https://github.com/rkennke/jdk/blob/fast-locking/test/hotspot/jtreg/runtime/locking/TestUnstructuredLocking.jasm
>
> jvms-2.11.10
>
> > Structured locking is the situation when, during a method invocation, every exit on a given monitor matches a preceding entry on that monitor. Since there is no assurance that all code submitted to the Java Virtual Machine will perform structured locking, implementations of the Java Virtual Machine are permitted but not required to enforce both of the following two rules guaranteeing structured locking. Let T be a thread and M be a monitor. Then:
> > The number of monitor entries performed by T on M during a method invocation must equal the number of monitor exits performed by T on M during the method invocation whether the method invocation completes normally or abruptly.
> > At no point during a method invocation may the number of monitor exits performed by T on M since the method invocation exceed the number of monitor entries performed by T on M since the method invocation.
> > Note that the monitor entry and exit automatically performed by the Java Virtual Machine when invoking a synchronized method are considered to occur during the calling method's invocation.
>
> I think the intent of above was to allow enforcing structured locking.
TBH, I don't see how this affects the scenario that I'm testing. The scenario:
monitorenter A;
monitorenter B;
monitorexit A;
monitorexit B;
violates any of the two conditions:
- the number of monitorenters and -exits during the execution always matches
- the number of monitorexits for each monitor does not exceed the number of monitorenters for the same monitor
Strictly speaking, I believe the conditions check for the (weaker) balanced property, but not for the (stronger) structured property.
> In relevant other projects, we support only structured locking in Java, but permit some unstructured locking when done via JNI. In that project JNI monitor enter/exit do not use the lockstack.
Yeah, JNI locking always inflate and uses full monitors. My proposal hasn't changed this.
> I don't think we today fully support unstructured locking either:
>
> ```
> void foo_lock() {
> monitorenter(this);
> // If VM abruptly returns here 'this' will be unlocked
> // Because VM assumes structured locking.
> // see e.g. remove_activation(...)
> }
> ```
>
> _I scratch this as it was a bit off topic._
Hmm yeah, this is required for properly handling exceptions. I have seen this making a bit of a mess in C1 code.
That said, unstructured locking today only ever works in the interpreter, the JIT compilers would refuse to compile unstructured locking code. So if somebody would come up with a language and compiler that emits unstructured (e.g. hand-over-hand) locks, it would run, but only very slowly.
I think I know how to make my proposal handle unstructured locking properly: In the interpreter monitorexit, I can check the top of the lock-stack, and if it doesn't match, call into the runtime, and there it's easy to implement the unstructured scenario.
-------------
PR: https://git.openjdk.org/jdk/pull/9680
More information about the serviceability-dev
mailing list