Instrument constructor bodies#661
Conversation
2ea54e2 to
99efc8c
Compare
| | | suspendAndCauseFailure() [suspendable: Continuation#1]: 0 at SingleSuspensionPointTraceRepresentationTest.operation(MultipleSuspensionsTests.kt:49) | | ||
| | | counter ➜ AtomicInteger#1 at SingleSuspensionPointTraceRepresentationTest.suspendAndCauseFailure(MultipleSuspensionsTests.kt:54) | | ||
| | | counter.get(): 1 at SingleSuspensionPointTraceRepresentationTest.suspendAndCauseFailure(MultipleSuspensionsTests.kt:54) | | ||
| | | this$0.counter.get(): 1 at SingleSuspensionPointTraceRepresentationTest.suspendAndCauseFailure(MultipleSuspensionsTests.kt:54) | |
There was a problem hiding this comment.
Can we avoid this$0 here?
There was a problem hiding this comment.
I see no way. I consider the cosmetic changes not urgent as this PR is just an extracted step for native calls.
There was a problem hiding this comment.
It makes the trace slightly less intuitive. Could you please analyze how to fix it, please? It does not extremely complex.
There was a problem hiding this comment.
Evgeniy Zhelenskiy (@zhelenskiy) I've noticed you made a fix for this issue. Could you please check why it does not fix other this$0 occurrences in the trace?
There was a problem hiding this comment.
They already existed. Generally, it is an actual legitimate name for outer this parameter in the constructor of an inner class.
There was a problem hiding this comment.
This is not something you type in the code, so I would prefer omitting it in the trace.
There was a problem hiding this comment.
This is not something you type in the code
I saw such code many times in my life.
There was a problem hiding this comment.
You don't have this$0 in the code; why should you have it in the trace?
There was a problem hiding this comment.
How would you like to refer to the outer this?
There was a problem hiding this comment.
Is outer-this better? Or this@Type?
| | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | $this_runCatching.block(): threw IllegalStateException at BaseRunConcurrentRepresentationTest.testRunWithModelChecker$lambda$1$lambda$0(RunConcurrentRepresentationTests.kt:47) | | | | ||
| | block(): threw IllegalStateException at IncorrectConcurrentLinkedDequeRunConcurrentRepresentationTest.block(RunConcurrentRepresentationTests.kt:349) | | | | ||
| | Node#1.item.putObject(null) at ConcurrentLinkedDeque$Node.<init>(ConcurrentLinkedDeque.java:303) | | | |
There was a problem hiding this comment.
Can we show constructor calls as method calls? (it looks as we miss a constructor call here)
There was a problem hiding this comment.
Unfortunately, there is no simple way to do that.
There was a problem hiding this comment.
What are the possible ways?
There was a problem hiding this comment.
I'm not sure but it should be very complicated as the constructor call is separated into two parts.
There was a problem hiding this comment.
Evgeniy Zhelenskiy (@zhelenskiy), we already have such a logic for reads, wrapping them with "beforeRead" and "afterRead" methods. Would the same approach work here?
There was a problem hiding this comment.
no
There was a problem hiding this comment.
please elaborate
There was a problem hiding this comment.
I have previously tried doing this for some time and failed, so I think that:
- It is not that simple.
- It is another issue, and I don't see any reason to mix the PRs.
- It is much less urgent.
There was a problem hiding this comment.
I don't think adding constructor events to the trace with a dedicated constructor call is the right way to proceed. Besides, I do not see what exactly is not that simple in this discussion. Could you please provide specific obstacles, so we can discuss them and make the right choice?
Also adding Evgeniy Moiseenko (@eupp) to this thread.
There was a problem hiding this comment.
As far as I remember, the problems were with stack frames, uninitialized variables, etc.
My argument against doing it now is the following:
- the simple solution didn't work;
- there is a separate issue for that;
- the code is already working without it;
- it can be done separately;
- blocking this PR blocks native calls;
- it is minor by its impact;
- it is just a different feature, there is no need to mix up everything in one PR.
|
Should resolve #449 |
0f916a2 to
35f191a
Compare
|
Right now constructors are not fully instrumented, the The problem with verification error could be reproduced in the following way: /*
DataStructure::<init>:
this.a = 10
this.b = "hello world"
*/
scenario:
val ds: DataStructure? = null
T1 T2
ds = DataStructure() | ds?.method()
| ds?.a = 10
| ds?.b = "aaaa"When JVM loads transformed class for If this is not necessary to allow |
|
Dmitrii Art (@dmitrii-artuhov) thanks for the investigation. This situation in the scenario you provide looks like unsafe publication. But I wonder how JVM bytecode verifier is capable of detecting it (I thought it cannot). I suspect it has to do some kind of escape analysis to detect this. Could you please share the whole code snippet you have (using GPMC syntax preferably). |
|
Cannot exactly reproduce decribed case, but I have come up with other tests: class TestClass {
@Test
fun test() {
runConcurrentTest(1) {
val t = thread {} // inside has a `val thread = object : Thread { /* references to outer variable `block` */ }`
}
}
}class TestClass {
var field = 0
inner class Node {
init { field++ }
}
@Test
fun test() {
runConcurrentTest(1) {
val n = Node()
}
}
}both produce Probably I was wrong about unsafe publication example. Here is a different reason for the verification error. The unsafe publication examples I tried to get the same error, but could not. Probably thas is not the case. |
|
Dmitrii Art (@dmitrii-artuhov) Does it fail both before and after my change? |
They fail after commenting out this part of the code |
|
Then can we just not comment them out? It is unnecessary for the native calls support. |
|
If tracking field accesses in constructors is not required for native calls, then we are fine, I believe |
f6b4412 to
524f42e
Compare
524f42e to
7b0bda6
Compare
No description provided.