From 847f889a0a49f57e59f8d2ffea45d3dfaa7aa133 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Thu, 11 May 2017 15:45:52 +0300 Subject: [PATCH] Allow merging tracked values in ReferenceTrackingInterpreter subclasses This is required for things like detupling. --- .../captured/ReferenceTrackingInterpreter.kt | 35 ++++++++++++++----- .../captured/TrackedReferenceValue.kt | 17 +++++++-- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/captured/ReferenceTrackingInterpreter.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/captured/ReferenceTrackingInterpreter.kt index c41ee4cf1c8..a0e0a1807c1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/captured/ReferenceTrackingInterpreter.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/captured/ReferenceTrackingInterpreter.kt @@ -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 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 diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/captured/TrackedReferenceValue.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/captured/TrackedReferenceValue.kt index 51a975053c1..0ff75117036 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/captured/TrackedReferenceValue.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/captured/TrackedReferenceValue.kt @@ -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 } @@ -42,6 +42,20 @@ class ProperTrackedReferenceValue(type: Type, val descriptor: ReferenceValueDesc "[$descriptor]" } + +class MergedTrackedReferenceValue(type: Type, override val descriptors: Set) : 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) : TrackedReferenceValue(type) { override fun equals(other: Any?): Boolean = other === this || @@ -49,7 +63,6 @@ class TaintedTrackedReferenceValue(type: Type, override val descriptors: Set