From d2d37088279c7fae11a992e075ac01b5f246e730 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Wed, 1 Sep 2021 12:57:07 +0200 Subject: [PATCH] Refactor a bit StringConcatGenerator class --- .../kotlin/codegen/StringConcatGenerator.kt | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StringConcatGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/StringConcatGenerator.kt index e584eef2eba..e0f04375af6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StringConcatGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StringConcatGenerator.kt @@ -21,9 +21,21 @@ import java.lang.StringBuilder class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapter) { - private val template = StringBuilder("") - private val specialSymbolsInTemplate = arrayListOf() - private val paramTypes = arrayListOf() + enum class ItemType { + PARAMETER, + CONSTANT, + INLINED_CONSTANT + } + + data class Item(val type: Type, var itemType: ItemType, val value: String) { + companion object { + fun inlinedConstant(value: String) = Item(JAVA_STRING_TYPE, ItemType.INLINED_CONSTANT, value) + fun constant(value: String) = Item(JAVA_STRING_TYPE, ItemType.CONSTANT, value) + fun parameter(type: Type) = Item(type, ItemType.PARAMETER, "\u0001") + } + } + + private val items = arrayListOf() private var paramSlots = 0 private var justFlushed = false @@ -46,22 +58,20 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte is StackValue.Constant -> { val value = stackValue.value if (value is String && (value.contains("\u0001") || value.contains("\u0002"))) { - template.append("\u0002") //reference to special symbols added on next line - specialSymbolsInTemplate.add(value) + items.add(Item.constant(value)) //strings with special symbols generated via bootstrap } else if (value is Char && (value == 1.toChar() || value == 2.toChar())) { - template.append("\u0002") //reference to special symbols added on next line - specialSymbolsInTemplate.add(value.toString()) + items.add(Item.constant(value.toString())) //strings with special symbols generated via bootstrap } else { - template.append(value) + items.add(Item.inlinedConstant(value.toString())) } return } TRUE -> { - template.append(true) + items.add(Item.inlinedConstant(true.toString())) return } FALSE -> { - template.append(false) + items.add(Item.inlinedConstant(false.toString())) return } } @@ -84,9 +94,8 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte ) } else { justFlushed = false - paramTypes.add(type) + items.add(Item.parameter(type)) paramSlots += type.size - template.append("\u0001") if (paramSlots >= 199) { // Concatenate current arguments into string // because of `StringConcatFactory` limitation add use it as new argument for further processing: @@ -112,11 +121,28 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte false ) + val templateBuilder = StringBuilder() + items.forEach { + when (it.itemType) { + ItemType.PARAMETER -> + templateBuilder.append("\u0001") + ItemType.CONSTANT -> + templateBuilder.append("\u0002") + ItemType.INLINED_CONSTANT -> + templateBuilder.append(it.value) + } + } + + val specialSymbolsInTemplate = items.filter { it.itemType == ItemType.CONSTANT }.map { it.value } + mv.invokedynamic( "makeConcatWithConstants", - Type.getMethodDescriptor(JAVA_STRING_TYPE, *paramTypes.toTypedArray()), + Type.getMethodDescriptor( + JAVA_STRING_TYPE, + *items.filter { it.itemType == ItemType.PARAMETER }.map { it.type }.toTypedArray() + ), bootstrap, - arrayOf(template.toString()) + specialSymbolsInTemplate + arrayOf(templateBuilder.toString()) + specialSymbolsInTemplate ) } else { val bootstrap = Handle( @@ -126,22 +152,24 @@ class StringConcatGenerator(val mode: JvmStringConcat, val mv: InstructionAdapte "(Ljava/lang/invoke/MethodHandles\$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;", false ) + assert(items.all { it.itemType == ItemType.PARAMETER }) { + "All arguments in `indy` concatenation should be processed as parameters, but: ${ + items.filterNot { it.itemType == ItemType.PARAMETER }.joinToString() + }" + } mv.invokedynamic( "makeConcat", - Type.getMethodDescriptor(JAVA_STRING_TYPE, *paramTypes.toTypedArray()), + Type.getMethodDescriptor(JAVA_STRING_TYPE, *items.map { it.type }.toTypedArray()), bootstrap, arrayOf() ) } //clear old template - template.clear() - specialSymbolsInTemplate.clear() - paramTypes.clear() + items.clear() //add just flushed string - paramTypes.add(JAVA_STRING_TYPE) - template.append("\u0001") + items.add(Item.parameter(JAVA_STRING_TYPE)) paramSlots = JAVA_STRING_TYPE.size } }