Allow merging tracked values in ReferenceTrackingInterpreter subclasses

This is required for things like detupling.
This commit is contained in:
Dmitry Petrov
2017-05-11 15:45:52 +03:00
parent b445e0a049
commit 847f889a0a
2 changed files with 41 additions and 11 deletions
@@ -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
@@ -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"
}