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)
|
if (v.descriptor == w.descriptor)
|
||||||
v
|
v
|
||||||
else
|
else
|
||||||
TaintedTrackedReferenceValue(
|
createTaintedValue(v, w)
|
||||||
getTaintedValueType(v.type, w.type),
|
|
||||||
setOf(v.descriptor, w.descriptor)
|
v is TrackedReferenceValue && w is TrackedReferenceValue ->
|
||||||
)
|
createPossiblyMergedValue(v, w)
|
||||||
|
|
||||||
v is TrackedReferenceValue || w is TrackedReferenceValue ->
|
v is TrackedReferenceValue || w is TrackedReferenceValue ->
|
||||||
TaintedTrackedReferenceValue(
|
createTaintedValue(v, w)
|
||||||
getTaintedValueType(v.type, w.type),
|
|
||||||
v.referenceValueDescriptors + w.referenceValueDescriptors
|
|
||||||
)
|
|
||||||
|
|
||||||
else ->
|
else ->
|
||||||
super.merge(v, w)
|
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>
|
private val BasicValue.referenceValueDescriptors: Set<ReferenceValueDescriptor>
|
||||||
get() = if (this is TrackedReferenceValue) this.descriptors else emptySet()
|
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 {
|
when {
|
||||||
type1 == null || type2 == null -> AsmTypes.OBJECT_TYPE
|
type1 == null || type2 == null -> AsmTypes.OBJECT_TYPE
|
||||||
type1 == type2 -> type1
|
type1 == type2 -> type1
|
||||||
|
|||||||
+15
-2
@@ -23,7 +23,7 @@ interface ReferenceValueDescriptor {
|
|||||||
fun onUseAsTainted()
|
fun onUseAsTainted()
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class TrackedReferenceValue(type: Type): StrictBasicValue(type) {
|
sealed class TrackedReferenceValue(type: Type): StrictBasicValue(type) {
|
||||||
abstract val descriptors: Set<ReferenceValueDescriptor>
|
abstract val descriptors: Set<ReferenceValueDescriptor>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +42,20 @@ class ProperTrackedReferenceValue(type: Type, val descriptor: ReferenceValueDesc
|
|||||||
"[$descriptor]"
|
"[$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) {
|
class TaintedTrackedReferenceValue(type: Type, override val descriptors: Set<ReferenceValueDescriptor>) : TrackedReferenceValue(type) {
|
||||||
override fun equals(other: Any?): Boolean =
|
override fun equals(other: Any?): Boolean =
|
||||||
other === this ||
|
other === this ||
|
||||||
@@ -49,7 +63,6 @@ class TaintedTrackedReferenceValue(type: Type, override val descriptors: Set<Ref
|
|||||||
|
|
||||||
override fun hashCode(): Int =
|
override fun hashCode(): Int =
|
||||||
descriptors.hashCode()
|
descriptors.hashCode()
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
"!$descriptors"
|
"!$descriptors"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user