Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bootstrap/src/sun/nio/ch/lincheck/EventTracker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ interface EventTracker {

fun afterReflectiveSetter(receiver: Any?, value: Any?)

fun beforeMethodCall(owner: Any?, className: String, methodName: String, codeLocation: Int, params: Array<Any?>)
fun beforeMethodCall(owner: Any?, className: String, methodName: String, codeLocation: Int, methodId: Int, params: Array<Any?>)
fun onMethodCallReturn(result: Any?)
fun onMethodCallException(t: Throwable)

Expand Down
4 changes: 2 additions & 2 deletions bootstrap/src/sun/nio/ch/lincheck/Injections.java
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,8 @@ public static void afterReflectiveSetter(Object receiver, Object value) {
*
* @param owner is `null` for public static methods.
*/
public static void beforeMethodCall(Object owner, String className, String methodName, int codeLocation, Object[] params) {
getEventTracker().beforeMethodCall(owner, className, methodName, codeLocation, params);
public static void beforeMethodCall(Object owner, String className, String methodName, int codeLocation, int methodId, Object[] params) {
getEventTracker().beforeMethodCall(owner, className, methodName, codeLocation, methodId, params);
}

/**
Expand Down
13 changes: 13 additions & 0 deletions src/jvm/main/org/jetbrains/kotlinx/lincheck/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ private fun Class<out Any>.getMethod(name: String, parameterTypes: Array<Class<o
method.name == name && method.parameterTypes.map { it.name } == parameterTypes.map { it.name }
} ?: throw NoSuchMethodException("${getName()}.$name(${parameterTypes.joinToString(",")})")

/**
* @return hashcode of the unboxed value if [value] represents a boxed primitive, otherwise returns [System.identityHashCode]
* of the [value].
*/
internal fun primitiveOrIdentityHashCode(value: Any?): Int {
return if (value.isPrimitiveWrapper) value.hashCode() else System.identityHashCode(value)
}

private val Any?.isPrimitiveWrapper get() = when (this) {
is Boolean, is Int, is Short, is Long, is Double, is Float, is Char, is Byte -> true
else -> false
}

/**
* Creates [Result] of corresponding type from any given value.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,18 @@ internal class InterleavingSequenceTrackableSet {
fun mergeBranch(newChain: List<InterleavingHistoryNode>, startIndex: Int, executionsCountedEarlier: Int) {
if (startIndex > newChain.lastIndex) return
val firstNewNode = newChain[startIndex]
val firstNewNodeExecutions = (firstNewNode.executions + firstNewNode.spinCyclePeriod) - executionsCountedEarlier
var firstNewNodeExecutions = (firstNewNode.executions + firstNewNode.spinCyclePeriod) - executionsCountedEarlier
check(firstNewNode.threadId == threadId)

// Some execution points may be added to the history after the spin-cycle is detected early
// even if we switched the execution using LoopDetector hint. In this case, the new branch may have
// more executions than the InterleavingSequenceSetNode which told switching the thread at this point.
// But these executions will be omitted in the next time, so we merge new branch taking execution count
// from the corresponding existing node.
if (cycleOccurred && firstNewNodeExecutions > executions) {
firstNewNodeExecutions = executions
}

when {
executions == firstNewNodeExecutions -> mergeFurtherOrAddNewBranch(newChain, startIndex + 1, 0)

Expand Down Expand Up @@ -295,8 +304,26 @@ internal class InterleavingSequenceTrackableSet {
transition.mergeBranch(newChain, startIndex, executionsCountedEarlier)
}
}

// Utility function to debug spin-locks related internals.
fun getTree(prefix: String = "", isTail: Boolean = true): String = buildString {
val tailSymbol = if (isTail) "\\-- " else "|-- "
appendLine("$prefix$tailSymbol$threadId : $executions : $cyclePeriod : ${if (cycleOccurred) "!" else "."}")
val children = transitions?.values?.toList() ?: emptyList()
for (i in children.indices) {
children[i].getTree(prefix + if (isTail) " " else "| ", i == children.size - 1)
}
}
}

// Utility function to debug spin-locks related internals.
internal fun treeToString(): String = buildString {
rootTransitions.forEach { (threadId, node) ->
appendLine("$threadId:")
appendLine(node.getTree())
appendLine()
}
}

/**
* Transforms a new chain
Expand Down Expand Up @@ -329,7 +356,7 @@ internal class InterleavingSequenceTrackableSet {
threadId = next.threadId,
executions = next.executions + next.spinCyclePeriod,
cyclePeriod = next.spinCyclePeriod,
cycleLocationsHash = first.executionHash,
cycleLocationsHash = next.executionHash,
cycleOccurred = i == chain.lastIndex
)
current.addTransition(next.threadId, nextNode)
Expand Down
Loading