@@ -878,69 +878,30 @@ abstract class ManagedStrategy(
878
878
codeLocation : Int ,
879
879
params : Array <Any ?>
880
880
) {
881
- val guarantee = methodGuaranteeType(owner, className, methodName)
882
- when (guarantee) {
883
- ManagedGuaranteeType .IGNORE -> {
884
- if (collectTrace) {
885
- runInIgnoredSection {
886
- val params = if (isSuspendFunction(className, methodName, params)) {
887
- params.dropLast(1 ).toTypedArray()
888
- } else {
889
- params
890
- }
891
- beforeMethodCall(owner, currentThread, codeLocation, className, methodName, params)
892
- }
893
- }
894
- // It's important that this method can't be called inside runInIgnoredSection, as the ignored section
895
- // flag would be set to false when leaving runInIgnoredSection,
896
- // so enterIgnoredSection would have no effect
897
- enterIgnoredSection()
881
+ val guarantee = runInIgnoredSection {
882
+ val atomicMethodDescriptor = getAtomicMethodDescriptor(owner, methodName)
883
+ val guarantee = when {
884
+ (atomicMethodDescriptor != null ) -> ManagedGuaranteeType .TREAT_AS_ATOMIC
885
+ else -> methodGuaranteeType(owner, className, methodName)
898
886
}
899
-
900
- ManagedGuaranteeType .TREAT_AS_ATOMIC -> {
901
- runInIgnoredSection {
902
- if (collectTrace) {
903
- beforeMethodCall(owner, currentThread, codeLocation, className, methodName, params)
904
- }
905
- newSwitchPointOnAtomicMethodCall(codeLocation)
906
- }
907
- // It's important that this method can't be called inside runInIgnoredSection, as the ignored section
908
- // flag would be set to false when leaving runInIgnoredSection,
909
- // so enterIgnoredSection would have no effect
910
- enterIgnoredSection()
887
+ if (owner == null && atomicMethodDescriptor == null && guarantee == null ) { // static method
888
+ LincheckJavaAgent .ensureClassHierarchyIsTransformed(className.canonicalClassName)
911
889
}
912
-
913
- null -> {
914
- if (owner == null ) { // static method
915
- runInIgnoredSection {
916
- LincheckJavaAgent .ensureClassHierarchyIsTransformed(className.canonicalClassName)
917
- }
918
- }
919
- if (collectTrace) {
920
- runInIgnoredSection {
921
- val params = if (isSuspendFunction(className, methodName, params)) {
922
- params.dropLast(1 ).toTypedArray()
923
- } else {
924
- params
925
- }
926
- beforeMethodCall(owner, currentThread, codeLocation, className, methodName, params)
927
- }
928
- }
890
+ if (collectTrace) {
891
+ addBeforeMethodCallTracePoint(owner, codeLocation, className, methodName, params, atomicMethodDescriptor)
892
+ }
893
+ if (guarantee == ManagedGuaranteeType .TREAT_AS_ATOMIC ) {
894
+ newSwitchPointOnAtomicMethodCall(codeLocation)
929
895
}
896
+ guarantee
930
897
}
931
- }
932
-
933
- override fun beforeAtomicMethodCall (
934
- owner : Any? ,
935
- className : String ,
936
- methodName : String ,
937
- codeLocation : Int ,
938
- params : Array <Any ?>
939
- ) = runInIgnoredSection {
940
- if (collectTrace) {
941
- beforeMethodCall(owner, currentThread, codeLocation, className, methodName, params)
898
+ if (guarantee == ManagedGuaranteeType .IGNORE ||
899
+ guarantee == ManagedGuaranteeType .TREAT_AS_ATOMIC ) {
900
+ // It's important that this method can't be called inside runInIgnoredSection, as the ignored section
901
+ // flag would be set to false when leaving runInIgnoredSection,
902
+ // so enterIgnoredSection would have no effect
903
+ enterIgnoredSection()
942
904
}
943
- newSwitchPointOnAtomicMethodCall(codeLocation)
944
905
}
945
906
946
907
override fun onMethodCallReturn (result : Any? ) {
@@ -1056,20 +1017,15 @@ abstract class ManagedStrategy(
1056
1017
suspendedFunctionsStack[iThread].clear()
1057
1018
}
1058
1019
1059
- /* *
1060
- * This method is invoked by a test thread
1061
- * before each method invocation.
1062
- * @param codeLocation the byte-code location identifier of this invocation
1063
- * @param iThread number of invoking thread
1064
- */
1065
- private fun beforeMethodCall (
1020
+ private fun addBeforeMethodCallTracePoint (
1066
1021
owner : Any? ,
1067
- iThread : Int ,
1068
1022
codeLocation : Int ,
1069
1023
className : String ,
1070
1024
methodName : String ,
1071
- params : Array <Any ?>,
1025
+ methodParams : Array <Any ?>,
1026
+ atomicMethodDescriptor : AtomicMethodDescriptor ? ,
1072
1027
) {
1028
+ val iThread = currentThread
1073
1029
val callStackTrace = callStackTrace[iThread]
1074
1030
val suspendedMethodStack = suspendedFunctionsStack[iThread]
1075
1031
val methodId = if (suspendedMethodStack.isNotEmpty()) {
@@ -1081,8 +1037,13 @@ abstract class ManagedStrategy(
1081
1037
} else {
1082
1038
methodCallNumber++
1083
1039
}
1040
+ val params = if (isSuspendFunction(className, methodName, methodParams)) {
1041
+ methodParams.dropLast(1 ).toTypedArray()
1042
+ } else {
1043
+ methodParams
1044
+ }
1084
1045
// Code location of the new method call is currently the last one
1085
- val tracePoint = createBeforeMethodCallTracePoint(owner, iThread, className, methodName, params, codeLocation)
1046
+ val tracePoint = createBeforeMethodCallTracePoint(owner, iThread, className, methodName, params, codeLocation, atomicMethodDescriptor )
1086
1047
methodCallTracePointStack[iThread] + = tracePoint
1087
1048
callStackTrace.add(CallStackTraceElement (tracePoint, methodId))
1088
1049
if (owner == null ) {
@@ -1098,7 +1059,8 @@ abstract class ManagedStrategy(
1098
1059
className : String ,
1099
1060
methodName : String ,
1100
1061
params : Array <Any ?>,
1101
- codeLocation : Int
1062
+ codeLocation : Int ,
1063
+ atomicMethodDescriptor : AtomicMethodDescriptor ? ,
1102
1064
): MethodCallTracePoint {
1103
1065
val callStackTrace = callStackTrace[iThread]
1104
1066
val tracePoint = MethodCallTracePoint (
@@ -1108,27 +1070,29 @@ abstract class ManagedStrategy(
1108
1070
methodName = methodName,
1109
1071
stackTraceElement = CodeLocations .stackTrace(codeLocation)
1110
1072
)
1111
- if (owner is VarHandle ) {
1112
- return initializeVarHandleMethodCallTracePoint(tracePoint, owner, params)
1073
+ // handle non-atomic methods
1074
+ if (atomicMethodDescriptor == null ) {
1075
+ val ownerName = if (owner != null ) findOwnerName(owner) else simpleClassName(className)
1076
+ if (ownerName != null ) {
1077
+ tracePoint.initializeOwnerName(ownerName)
1078
+ }
1079
+ tracePoint.initializeParameters(params.map { adornedStringRepresentation(it) })
1080
+ return tracePoint
1113
1081
}
1114
- if (owner is AtomicIntegerFieldUpdater <* > || owner is AtomicLongFieldUpdater <* > || owner is AtomicReferenceFieldUpdater <* , * >) {
1115
- return initializeAtomicUpdaterMethodCallTracePoint(tracePoint, owner, params)
1082
+ // handle atomic methods
1083
+ if (isVarHandle(owner)) {
1084
+ return initializeVarHandleMethodCallTracePoint(tracePoint, owner as VarHandle , params)
1116
1085
}
1117
- if (isAtomicReference(owner)) {
1086
+ if (isAtomicFieldUpdater(owner)) {
1087
+ return initializeAtomicUpdaterMethodCallTracePoint(tracePoint, owner!! , params)
1088
+ }
1089
+ if (isAtomic(owner) || isAtomicArray(owner)) {
1118
1090
return initializeAtomicReferenceMethodCallTracePoint(tracePoint, owner!! , params)
1119
1091
}
1120
1092
if (isUnsafe(owner)) {
1121
1093
return initializeUnsafeMethodCallTracePoint(tracePoint, owner!! , params)
1122
1094
}
1123
-
1124
- tracePoint.initializeParameters(params.map { adornedStringRepresentation(it) })
1125
-
1126
- val ownerName = if (owner != null ) findOwnerName(owner) else simpleClassName(className)
1127
- if (ownerName != null ) {
1128
- tracePoint.initializeOwnerName(ownerName)
1129
- }
1130
-
1131
- return tracePoint
1095
+ error(" Unknown atomic method $className ::$methodName " )
1132
1096
}
1133
1097
1134
1098
private fun simpleClassName (className : String ) = className.takeLastWhile { it != ' /' }
@@ -1178,10 +1142,6 @@ abstract class ManagedStrategy(
1178
1142
tracePoint.initializeOwnerName((receiverName?.let { " $it ." } ? : " " ) + " ${atomicReferenceInfo.fieldName} [${atomicReferenceInfo.index} ]" )
1179
1143
tracePoint.initializeParameters(params.drop(1 ).map { adornedStringRepresentation(it) })
1180
1144
}
1181
- AtomicReferenceMethodType .TreatAsDefaultMethod -> {
1182
- tracePoint.initializeOwnerName(adornedStringRepresentation(receiver))
1183
- tracePoint.initializeParameters(params.map { adornedStringRepresentation(it) })
1184
- }
1185
1145
is AtomicReferenceInstanceMethod -> {
1186
1146
val receiverName = findOwnerName(atomicReferenceInfo.owner)
1187
1147
tracePoint.initializeOwnerName(receiverName?.let { " $it .${atomicReferenceInfo.fieldName} " } ? : atomicReferenceInfo.fieldName)
@@ -1195,6 +1155,10 @@ abstract class ManagedStrategy(
1195
1155
tracePoint.initializeOwnerName(" ${atomicReferenceInfo.ownerClass.simpleName} .${atomicReferenceInfo.fieldName} [${atomicReferenceInfo.index} ]" )
1196
1156
tracePoint.initializeParameters(params.drop(1 ).map { adornedStringRepresentation(it) })
1197
1157
}
1158
+ AtomicReferenceMethodType .TreatAsDefaultMethod -> {
1159
+ tracePoint.initializeOwnerName(adornedStringRepresentation(receiver))
1160
+ tracePoint.initializeParameters(params.map { adornedStringRepresentation(it) })
1161
+ }
1198
1162
}
1199
1163
return tracePoint
1200
1164
}
@@ -1237,20 +1201,6 @@ abstract class ManagedStrategy(
1237
1201
return tracePoint
1238
1202
}
1239
1203
1240
- private fun isAtomicReference (receiver : Any? ) = receiver is AtomicReference <* > ||
1241
- receiver is AtomicLong ||
1242
- receiver is AtomicInteger ||
1243
- receiver is AtomicBoolean ||
1244
- receiver is AtomicIntegerArray ||
1245
- receiver is AtomicReferenceArray <* > ||
1246
- receiver is AtomicLongArray
1247
-
1248
- private fun isUnsafe (receiver : Any? ): Boolean {
1249
- if (receiver == null ) return false
1250
- val className = receiver::class .java.name
1251
- return className == " sun.misc.Unsafe" || className == " jdk.internal.misc.Unsafe"
1252
- }
1253
-
1254
1204
/* *
1255
1205
* Returns beautiful string representation of the [owner].
1256
1206
* If the [owner] is `this` of the current method, then returns `null`.
0 commit comments