JetBrains / lincheck

Framework for testing concurrent data structures
Mozilla Public License 2.0
538 stars 31 forks source link

Detect atomic primitive method calls dynamically #336

Closed eupp closed 6 days ago

eupp commented 1 week ago

Currently, we have two injection methods to handle method calls: beforeMethodCall and beforeAtomicMethodCall. This solution has several problems:

  1. Code duplication.

  2. We do not handle classes inheriting from Atomic* classes propertly, because their methods are not detected as "atomic" statically by the MethodCallTransformer bytecode transformer that injects beforeMethodCall and beforeAtomicMethodCall invocations. This is because this transformer decides what method to insert statically based on the class name of the invoked method. It checks only for j.u.c.Atomic* method names, and do not handles subclasses of atomics.

This PR removes beforeAtomicMethodCall injection, letting the managed strategy to decide how to handle the method dynamically at runtime, based on the actual type of the method receiver.

I've also added a new test AtomicSubclassTest.kt checking that subclasses of Atomic* classes are properly supported.

Please note, that with this PR the memory access methods of Atomic*, Atomic*FieldUpdater, VarHandle and Unsafe APIs are treated as atomic. Therefore, this PR also closes #288.

The latter also implies that Atomic*Array::length() method is no longer considered to be atomic method. Because of this, it has disappeared from the trace output of some tests.