Allow merging tracked values in ReferenceTrackingInterpreter subclasses
This is required for things like detupling.
This commit is contained in:
+26
-9
@@ -29,25 +29,42 @@ abstract class ReferenceTrackingInterpreter : OptimizationBasicInterpreter() {
|
||||
if (v.descriptor == w.descriptor)
|
||||
v
|
||||
else
|
||||
TaintedTrackedReferenceValue(
|
||||
getTaintedValueType(v.type, w.type),
|
||||
setOf(v.descriptor, w.descriptor)
|
||||
)
|
||||
createTaintedValue(v, w)
|
||||
|
||||
v is TrackedReferenceValue && w is TrackedReferenceValue ->
|
||||
createPossiblyMergedValue(v, w)
|
||||
|
||||
v is TrackedReferenceValue || w is TrackedReferenceValue ->
|
||||
TaintedTrackedReferenceValue(
|
||||
getTaintedValueType(v.type, w.type),
|
||||
v.referenceValueDescriptors + w.referenceValueDescriptors
|
||||
)
|
||||
createTaintedValue(v, w)
|
||||
|
||||
else ->
|
||||
super.merge(v, w)
|
||||
}
|
||||
|
||||
protected fun createTaintedValue(v: BasicValue, w: BasicValue) : TrackedReferenceValue =
|
||||
TaintedTrackedReferenceValue(
|
||||
getMergedValueType(v.type, w.type),
|
||||
mergeDescriptors(v, w).also {
|
||||
assert(it.isNotEmpty()) { "At least one of ($v, $w) should be a tracked reference" }
|
||||
}
|
||||
)
|
||||
|
||||
protected fun createMergedValue(v: TrackedReferenceValue, w: TrackedReferenceValue): TrackedReferenceValue =
|
||||
if (v is TaintedTrackedReferenceValue || w is TaintedTrackedReferenceValue)
|
||||
createTaintedValue(v, w)
|
||||
else
|
||||
MergedTrackedReferenceValue(getMergedValueType(v.type, w.type), mergeDescriptors(v, w))
|
||||
|
||||
protected open fun createPossiblyMergedValue(v: TrackedReferenceValue, w: TrackedReferenceValue): TrackedReferenceValue =
|
||||
createTaintedValue(v, w)
|
||||
|
||||
private fun mergeDescriptors(v: BasicValue, w: BasicValue) =
|
||||
v.referenceValueDescriptors + w.referenceValueDescriptors
|
||||
|
||||
private val BasicValue.referenceValueDescriptors: Set<ReferenceValueDescriptor>
|
||||
get() = if (this is TrackedReferenceValue) this.descriptors else emptySet()
|
||||
|
||||
private fun getTaintedValueType(type1: Type?, type2: Type?): Type =
|
||||
protected fun getMergedValueType(type1: Type?, type2: Type?): Type =
|
||||
when {
|
||||
type1 == null || type2 == null -> AsmTypes.OBJECT_TYPE
|
||||
type1 == type2 -> type1
|
||||
|
||||
+15
-2
@@ -23,7 +23,7 @@ interface ReferenceValueDescriptor {
|
||||
fun onUseAsTainted()
|
||||
}
|
||||
|
||||
abstract class TrackedReferenceValue(type: Type): StrictBasicValue(type) {
|
||||
sealed class TrackedReferenceValue(type: Type): StrictBasicValue(type) {
|
||||
abstract val descriptors: Set<ReferenceValueDescriptor>
|
||||
}
|
||||
|
||||
@@ -42,6 +42,20 @@ class ProperTrackedReferenceValue(type: Type, val descriptor: ReferenceValueDesc
|
||||
"[$descriptor]"
|
||||
}
|
||||
|
||||
|
||||
class MergedTrackedReferenceValue(type: Type, override val descriptors: Set<ReferenceValueDescriptor>) : TrackedReferenceValue(type) {
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other === this ||
|
||||
other is MergedTrackedReferenceValue && other.descriptors == this.descriptors
|
||||
|
||||
override fun hashCode(): Int =
|
||||
descriptors.hashCode()
|
||||
|
||||
override fun toString(): String =
|
||||
descriptors.toString()
|
||||
}
|
||||
|
||||
|
||||
class TaintedTrackedReferenceValue(type: Type, override val descriptors: Set<ReferenceValueDescriptor>) : TrackedReferenceValue(type) {
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other === this ||
|
||||
@@ -49,7 +63,6 @@ class TaintedTrackedReferenceValue(type: Type, override val descriptors: Set<Ref
|
||||
|
||||
override fun hashCode(): Int =
|
||||
descriptors.hashCode()
|
||||
|
||||
override fun toString(): String =
|
||||
"!$descriptors"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user