Turn SwitchCodegenUtil into a class
This commit is contained in:
@@ -50,7 +50,7 @@ import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
|
||||
import org.jetbrains.kotlin.config.ApiVersion;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
@@ -131,6 +131,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
private final MemberCodegen<?> parentCodegen;
|
||||
private final TailRecursionCodegen tailRecursionCodegen;
|
||||
public final CallGenerator defaultCallGenerator = new CallGenerator.DefaultCallGenerator(this);
|
||||
private final SwitchCodegenProvider switchCodegenProvider;
|
||||
|
||||
private final Stack<BlockStackElement> blockStackElements = new Stack<>();
|
||||
|
||||
@@ -162,6 +163,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
this.parentCodegen = parentCodegen;
|
||||
this.tailRecursionCodegen = new TailRecursionCodegen(context, this, this.v, state);
|
||||
this.switchCodegenProvider = new SwitchCodegenProvider(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -4122,12 +4124,12 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
Type resultType = isStatement ? Type.VOID_TYPE : expressionType(expression);
|
||||
|
||||
return StackValue.operation(resultType, v -> {
|
||||
SwitchCodegen switchCodegen = SwitchCodegenUtil.buildAppropriateSwitchCodegenIfPossible(
|
||||
expression, isStatement, CodegenUtil.isExhaustive(bindingContext, expression, isStatement), this
|
||||
SwitchCodegen switchCodegen = switchCodegenProvider.buildAppropriateSwitchCodegenIfPossible(
|
||||
expression, isStatement, CodegenUtil.isExhaustive(bindingContext, expression, isStatement)
|
||||
);
|
||||
if (switchCodegen != null) {
|
||||
switchCodegen.generate();
|
||||
return Unit.INSTANCE;
|
||||
return null;
|
||||
}
|
||||
|
||||
int subjectLocal = expr != null ? myFrameMap.enterTemp(subjectType) : -1;
|
||||
|
||||
+5
-7
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.codegen.*;
|
||||
import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
|
||||
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
|
||||
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
|
||||
import org.jetbrains.kotlin.coroutines.CoroutineUtilKt;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
@@ -83,7 +83,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
private final JvmRuntimeTypes runtimeTypes;
|
||||
private final JvmFileClassesProvider fileClassesProvider;
|
||||
private final TypeMappingConfiguration<Type> typeMappingConfiguration;
|
||||
private final boolean shouldInlineConstVals;
|
||||
private final SwitchCodegenProvider switchCodegenProvider;
|
||||
|
||||
public CodegenAnnotatingVisitor(@NotNull GenerationState state) {
|
||||
this.bindingTrace = state.getBindingTrace();
|
||||
@@ -92,7 +92,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
this.runtimeTypes = state.getJvmRuntimeTypes();
|
||||
this.fileClassesProvider = state.getFileClassesProvider();
|
||||
this.typeMappingConfiguration = state.getTypeMapper().getTypeMappingConfiguration();
|
||||
this.shouldInlineConstVals = state.getShouldInlineConstVals();
|
||||
this.switchCodegenProvider = new SwitchCodegenProvider(state);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -682,7 +682,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
WhenByEnumsMapping mapping = new WhenByEnumsMapping(classDescriptor, currentClassName, fieldNumber);
|
||||
|
||||
for (ConstantValue<?> constant : SwitchCodegenUtil.getAllConstants(expression, bindingContext, shouldInlineConstVals)) {
|
||||
for (ConstantValue<?> constant : switchCodegenProvider.getAllConstants(expression)) {
|
||||
if (constant instanceof NullValue) continue;
|
||||
|
||||
assert constant instanceof EnumValue : "expression in when should be EnumValue";
|
||||
@@ -696,10 +696,8 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
||||
|
||||
private boolean isWhenWithEnums(@NotNull KtWhenExpression expression) {
|
||||
return WhenChecker.isWhenByEnum(expression, bindingContext) &&
|
||||
SwitchCodegenUtil.checkAllItemsAreConstantsSatisfying(
|
||||
switchCodegenProvider.checkAllItemsAreConstantsSatisfying(
|
||||
expression,
|
||||
bindingContext,
|
||||
shouldInlineConstVals,
|
||||
constant -> constant instanceof EnumValue || constant instanceof NullValue
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ abstract public class SwitchCodegen {
|
||||
protected Label endLabel = new Label();
|
||||
protected Label defaultLabel;
|
||||
|
||||
protected final SwitchCodegenProvider switchCodegenProvider;
|
||||
|
||||
public SwitchCodegen(
|
||||
@NotNull KtWhenExpression expression, boolean isStatement,
|
||||
boolean isExhaustive, @NotNull ExpressionCodegen codegen,
|
||||
@@ -59,6 +61,7 @@ abstract public class SwitchCodegen {
|
||||
this.isExhaustive = isExhaustive;
|
||||
this.codegen = codegen;
|
||||
this.bindingContext = codegen.getBindingContext();
|
||||
this.switchCodegenProvider = new SwitchCodegenProvider(codegen);
|
||||
|
||||
this.subjectType = subjectType != null ? subjectType : codegen.expressionType(expression.getSubjectExpression());
|
||||
resultType = isStatement ? Type.VOID_TYPE : codegen.expressionType(expression);
|
||||
@@ -100,7 +103,7 @@ abstract public class SwitchCodegen {
|
||||
for (KtWhenEntry entry : expression.getEntries()) {
|
||||
Label entryLabel = new Label();
|
||||
|
||||
for (ConstantValue<?> constant : SwitchCodegenUtil.getConstantsFromEntry(entry, bindingContext, codegen.getState().getShouldInlineConstVals())) {
|
||||
for (ConstantValue<?> constant : switchCodegenProvider.getConstantsFromEntry(entry)) {
|
||||
if (constant instanceof NullValue) continue;
|
||||
processConstant(constant, entryLabel);
|
||||
}
|
||||
@@ -158,7 +161,7 @@ abstract public class SwitchCodegen {
|
||||
private int findNullEntryIndex(@NotNull KtWhenExpression expression) {
|
||||
int entryIndex = 0;
|
||||
for (KtWhenEntry entry : expression.getEntries()) {
|
||||
for (ConstantValue<?> constant : SwitchCodegenUtil.getConstantsFromEntry(entry, bindingContext, codegen.getState().getShouldInlineConstVals())) {
|
||||
for (ConstantValue<?> constant : switchCodegenProvider.getConstantsFromEntry(entry)) {
|
||||
if (constant instanceof NullValue) {
|
||||
return entryIndex;
|
||||
}
|
||||
|
||||
+28
-55
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.`when`
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
@@ -29,14 +30,16 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
object SwitchCodegenUtil {
|
||||
@JvmStatic
|
||||
fun checkAllItemsAreConstantsSatisfying(
|
||||
expression: KtWhenExpression,
|
||||
bindingContext: BindingContext,
|
||||
shouldInlineConstVals: Boolean,
|
||||
predicate: Function1<ConstantValue<*>, Boolean>
|
||||
): Boolean =
|
||||
class SwitchCodegenProvider
|
||||
private constructor (
|
||||
private val bindingContext: BindingContext,
|
||||
private val shouldInlineConstVals: Boolean,
|
||||
private val codegen: ExpressionCodegen?
|
||||
) {
|
||||
constructor(state: GenerationState) : this(state.bindingContext, state.shouldInlineConstVals, null)
|
||||
constructor(codegen: ExpressionCodegen) : this(codegen.bindingContext, codegen.state.shouldInlineConstVals, codegen)
|
||||
|
||||
fun checkAllItemsAreConstantsSatisfying(expression: KtWhenExpression, predicate: Function1<ConstantValue<*>, Boolean>): Boolean =
|
||||
expression.entries.all { entry ->
|
||||
entry.conditions.all { condition ->
|
||||
if (condition !is KtWhenConditionWithExpression) return false
|
||||
@@ -46,33 +49,19 @@ object SwitchCodegenUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getAllConstants(
|
||||
expression: KtWhenExpression,
|
||||
bindingContext: BindingContext,
|
||||
shouldInlineConstVals: Boolean
|
||||
): Iterable<ConstantValue<*>?> =
|
||||
fun getAllConstants(expression: KtWhenExpression): Iterable<ConstantValue<*>?> =
|
||||
ArrayList<ConstantValue<*>?>().apply {
|
||||
for (entry in expression.entries) {
|
||||
addConstantsFromConditions(entry, bindingContext, shouldInlineConstVals)
|
||||
addConstantsFromConditions(entry)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getConstantsFromEntry(
|
||||
entry: KtWhenEntry,
|
||||
bindingContext: BindingContext,
|
||||
shouldInlineConstVals: Boolean
|
||||
): Iterable<ConstantValue<*>?> =
|
||||
fun getConstantsFromEntry(entry: KtWhenEntry): Iterable<ConstantValue<*>?> =
|
||||
ArrayList<ConstantValue<*>?>().apply {
|
||||
addConstantsFromConditions(entry, bindingContext, shouldInlineConstVals)
|
||||
addConstantsFromConditions(entry)
|
||||
}
|
||||
|
||||
private fun ArrayList<ConstantValue<*>?>.addConstantsFromConditions(
|
||||
entry: KtWhenEntry,
|
||||
bindingContext: BindingContext,
|
||||
shouldInlineConstVals: Boolean
|
||||
) {
|
||||
private fun ArrayList<ConstantValue<*>?>.addConstantsFromConditions(entry: KtWhenEntry) {
|
||||
for (condition in entry.conditions) {
|
||||
if (condition !is KtWhenConditionWithExpression) continue
|
||||
val patternExpression = condition.expression ?: throw AssertionError("expression in when should not be null")
|
||||
@@ -80,16 +69,14 @@ object SwitchCodegenUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun buildAppropriateSwitchCodegenIfPossible(
|
||||
expression: KtWhenExpression,
|
||||
isStatement: Boolean,
|
||||
isExhaustive: Boolean,
|
||||
codegen: ExpressionCodegen
|
||||
isExhaustive: Boolean
|
||||
): SwitchCodegen? {
|
||||
val bindingContext = codegen.bindingContext
|
||||
val shouldInlineConstVals = codegen.state.shouldInlineConstVals
|
||||
if (!isThereConstantEntriesButNulls(expression, bindingContext, shouldInlineConstVals)) {
|
||||
val codegen = codegen ?: throw AssertionError("Can't create SwitchCodegen in this context")
|
||||
|
||||
if (!isThereConstantEntriesButNulls(expression)) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -100,37 +87,23 @@ object SwitchCodegenUtil {
|
||||
return when {
|
||||
mapping != null ->
|
||||
EnumSwitchCodegen(expression, isStatement, isExhaustive, codegen, mapping)
|
||||
isIntegralConstantsSwitch(expression, subjectType, bindingContext, shouldInlineConstVals) ->
|
||||
isIntegralConstantsSwitch(expression, subjectType) ->
|
||||
IntegralConstantsSwitchCodegen(expression, isStatement, isExhaustive, codegen)
|
||||
isStringConstantsSwitch(expression, subjectType, bindingContext, shouldInlineConstVals) ->
|
||||
isStringConstantsSwitch(expression, subjectType) ->
|
||||
StringSwitchCodegen(expression, isStatement, isExhaustive, codegen)
|
||||
else -> null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun isThereConstantEntriesButNulls(
|
||||
expression: KtWhenExpression,
|
||||
bindingContext: BindingContext,
|
||||
shouldInlineConstVals: Boolean
|
||||
): Boolean =
|
||||
getAllConstants(expression, bindingContext, shouldInlineConstVals).any { it != null && it !is NullValue }
|
||||
private fun isThereConstantEntriesButNulls(expression: KtWhenExpression): Boolean =
|
||||
getAllConstants(expression).any { it != null && it !is NullValue }
|
||||
|
||||
private fun isIntegralConstantsSwitch(
|
||||
expression: KtWhenExpression,
|
||||
subjectType: Type,
|
||||
bindingContext: BindingContext,
|
||||
shouldInlineConstVals: Boolean
|
||||
): Boolean =
|
||||
private fun isIntegralConstantsSwitch(expression: KtWhenExpression, subjectType: Type): Boolean =
|
||||
AsmUtil.isIntPrimitive(subjectType) &&
|
||||
checkAllItemsAreConstantsSatisfying(expression, bindingContext, shouldInlineConstVals) { it is IntegerValueConstant<*> }
|
||||
checkAllItemsAreConstantsSatisfying(expression) { it is IntegerValueConstant<*> }
|
||||
|
||||
private fun isStringConstantsSwitch(
|
||||
expression: KtWhenExpression,
|
||||
subjectType: Type,
|
||||
bindingContext: BindingContext,
|
||||
shouldInlineConstVals: Boolean
|
||||
): Boolean =
|
||||
private fun isStringConstantsSwitch(expression: KtWhenExpression, subjectType: Type): Boolean =
|
||||
subjectType.className == String::class.java.name &&
|
||||
checkAllItemsAreConstantsSatisfying(expression, bindingContext, shouldInlineConstVals) { it is StringValue || it is NullValue }
|
||||
checkAllItemsAreConstantsSatisfying(expression) { it is StringValue || it is NullValue }
|
||||
}
|
||||
Reference in New Issue
Block a user