Add runtime string concat options. Some renaming

This commit is contained in:
Mikhael Bogdanov
2020-09-29 08:47:06 +02:00
parent 04012951c1
commit c329c22630
20 changed files with 97 additions and 24 deletions
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.codegen;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
@@ -52,7 +51,6 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isBoolean;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveClass;
@@ -495,12 +493,12 @@ public class DescriptorAsmUtil {
return index;
}
public static void genInvokeAppendMethod(@NotNull StringAppendGenerator generator, @NotNull Type type, @Nullable KotlinType kotlinType) {
public static void genInvokeAppendMethod(@NotNull StringConcatGenerator generator, @NotNull Type type, @Nullable KotlinType kotlinType) {
genInvokeAppendMethod(generator, type, kotlinType, null);
}
public static void genInvokeAppendMethod(
@NotNull StringAppendGenerator generator,
@NotNull StringConcatGenerator generator,
@NotNull Type type,
@Nullable KotlinType kotlinType,
@Nullable KotlinTypeMapper typeMapper
@@ -925,7 +925,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
else {
return StackValue.operation(type, v -> {
StringAppendGenerator generator = StringAppendGenerator.Companion.create(state, v);
StringConcatGenerator generator = StringConcatGenerator.Companion.create(state, v);
generator.genStringBuilderConstructorIfNeded();
invokeAppendForEntries(generator, entries);
generator.genToString();
@@ -934,7 +934,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
private void invokeAppendForEntries(StringAppendGenerator generator, List<StringTemplateEntry> entries) {
private void invokeAppendForEntries(StringConcatGenerator generator, List<StringTemplateEntry> entries) {
for (StringTemplateEntry entry : entries) {
if (entry instanceof StringTemplateEntry.Expression) {
invokeAppend(generator, ((StringTemplateEntry.Expression) entry).expression);
@@ -4300,7 +4300,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
}
public void invokeAppend(StringAppendGenerator generator, KtExpression expr) {
public void invokeAppend(StringConcatGenerator generator, KtExpression expr) {
expr = KtPsiUtil.safeDeparenthesize(expr);
ConstantValue<?> compileTimeConstant = getPrimitiveOrStringCompileTimeConstant(expr);
@@ -102,7 +102,7 @@ public class FunctionsFromAnyGeneratorImpl extends FunctionsFromAnyGenerator {
mv.visitCode();
StringAppendGenerator generator = StringAppendGenerator.Companion.create(generationState, iv);
StringConcatGenerator generator = StringConcatGenerator.Companion.create(generationState, iv);
generator.genStringBuilderConstructorIfNeded();
boolean first = true;
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.codegen
import com.google.common.collect.Sets
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.JvmRuntimeStringConcat
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
import org.jetbrains.org.objectweb.asm.Handle
@@ -16,14 +16,14 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.lang.StringBuilder
class StringAppendGenerator(val useInvokeDynamic: Boolean, val mv: InstructionAdapter) {
class StringConcatGenerator(val mode: JvmRuntimeStringConcat, val mv: InstructionAdapter) {
private val template = StringBuilder("")
private val paramTypes = arrayListOf<Type>()
@JvmOverloads
fun genStringBuilderConstructorIfNeded(swap: Boolean = false) {
if (useInvokeDynamic) return
if (mode.isDynamic) return
mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder")
mv.dup()
mv.invokespecial("java/lang/StringBuilder", "<init>", "()V", false)
@@ -33,7 +33,7 @@ class StringAppendGenerator(val useInvokeDynamic: Boolean, val mv: InstructionAd
}
fun addCharConstant(value: Char) {
if (!useInvokeDynamic) {
if (!mode.isDynamic) {
mv.iconst(value.toInt())
invokeAppend(Type.CHAR_TYPE)
} else {
@@ -42,7 +42,7 @@ class StringAppendGenerator(val useInvokeDynamic: Boolean, val mv: InstructionAd
}
fun addStringConstant(value: String) {
if (!useInvokeDynamic) {
if (!mode.isDynamic) {
mv.aconst(value)
invokeAppend(JAVA_STRING_TYPE)
} else {
@@ -51,7 +51,7 @@ class StringAppendGenerator(val useInvokeDynamic: Boolean, val mv: InstructionAd
}
fun invokeAppend(type: Type) {
if (!useInvokeDynamic) {
if (!mode.isDynamic) {
mv.invokevirtual(
"java/lang/StringBuilder",
"append",
@@ -71,7 +71,7 @@ class StringAppendGenerator(val useInvokeDynamic: Boolean, val mv: InstructionAd
}
fun genToString() {
if (!useInvokeDynamic) {
if (!mode.isDynamic) {
mv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)
} else {
//if state was flushed in `invokeAppend` do nothing
@@ -114,7 +114,7 @@ class StringAppendGenerator(val useInvokeDynamic: Boolean, val mv: InstructionAd
}
fun create(state: GenerationState, mv: InstructionAdapter) =
StringAppendGenerator(/*TODO: add flag*/state.target.bytecodeVersion >= JvmTarget.JVM_9.bytecodeVersion, mv)
StringConcatGenerator(state.runtimeStringConcat, mv)
}
}
@@ -39,7 +39,7 @@ class Concat : IntrinsicMethod() {
arguments: List<KtExpression>,
receiver: StackValue
): Type {
val generator = StringAppendGenerator.create(codegen.state, v)
val generator = StringConcatGenerator.create(codegen.state, v)
if (element is KtBinaryExpression && element.operationReference.getReferencedNameElementType() == KtTokens.PLUS) {
// LHS + RHS
generator.genStringBuilderConstructorIfNeded()
@@ -59,7 +59,7 @@ class Concat : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable =
object : IntrinsicCallable(method) {
lateinit var generator: StringAppendGenerator
lateinit var generator: StringConcatGenerator
override fun invokeMethodWithArguments(
resolvedCall: ResolvedCall<*>,
receiver: StackValue,
@@ -83,8 +83,8 @@ class Concat : IntrinsicMethod() {
}
override fun afterReceiverGeneration(v: InstructionAdapter, frameMap: FrameMap, state: GenerationState) {
generator = StringAppendGenerator.create(state, v)
if (!generator.useInvokeDynamic) {
generator = StringConcatGenerator.create(state, v)
if (!generator.mode.isDynamic) {
v.generateNewInstanceDupAndPlaceBeforeStackTop(frameMap, JAVA_STRING_TYPE, "java/lang/StringBuilder")
v.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
} else {
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.codegen.intrinsics
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -25,19 +24,19 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class StringPlus : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable =
object : IntrinsicCallable(method) {
private lateinit var generator: StringAppendGenerator
private lateinit var generator: StringConcatGenerator
override fun invokeMethodWithArguments(
resolvedCall: ResolvedCall<*>,
receiver: StackValue,
codegen: ExpressionCodegen
): StackValue {
generator = StringAppendGenerator.create(codegen.state, codegen.v)
generator = StringConcatGenerator.create(codegen.state, codegen.v)
return super.invokeMethodWithArguments(resolvedCall, receiver, codegen)
}
override fun genInvokeInstruction(v: InstructionAdapter) {
if (!generator.useInvokeDynamic) {
if (!generator.mode.isDynamic) {
v.invokestatic(
IntrinsicMethods.INTRINSICS_CLASS_NAME, "stringPlus",
"(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;", false
@@ -191,6 +191,10 @@ class GenerationState private constructor(
val languageVersionSettings = configuration.languageVersionSettings
val target = configuration.get(JVMConfigurationKeys.JVM_TARGET) ?: JvmTarget.DEFAULT
val runtimeStringConcat =
if (target.bytecodeVersion >= JvmTarget.JVM_9.bytecodeVersion)
configuration.get(JVMConfigurationKeys.RUNTIME_STRING_CONCAT) ?: JvmRuntimeStringConcat.DISABLE
else JvmRuntimeStringConcat.DISABLE
val moduleName: String = moduleName ?: JvmCodegenUtil.getModuleName(module)
val classBuilderMode: ClassBuilderMode = builderFactory.classBuilderMode
@@ -334,6 +334,16 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
var emitJvmTypeAnnotations: Boolean by FreezableVar(false)
@Argument(
value = "-Xruntime-string-concat",
valueDescription = "{disable|enable|indy}",
description = """Switch a way in which string concatenation is performed.
-Xruntime-string-concat=enable Performs string concatenation via `invokedynamic` 'makeConcatWithConstants'. Works only with `-jvm-target 9` or greater
-Xruntime-string-concat=indy Performs string concatenation via `invokedynamic` 'makeConcat'. Works only with `-jvm-target 9` or greater
-Xruntime-string-concat=disable Performs string concatenation via `StringBuilder`"""
)
var runtimeStringConcat: String? by NullableStringFreezableVar(JvmRuntimeStringConcat.DISABLE.name.toLowerCase())
@Argument(
value = "-Xklib",
valueDescription = "<path>",
@@ -49,6 +49,24 @@ fun CompilerConfiguration.setupJvmSpecificArguments(arguments: K2JVMCompilerArgu
}
}
if (arguments.runtimeStringConcat != null) {
val runtimeStringConcat = JvmRuntimeStringConcat.fromString(arguments.runtimeStringConcat!!)
if (runtimeStringConcat != null) {
put(JVMConfigurationKeys.RUNTIME_STRING_CONCAT, runtimeStringConcat)
if (jvmTarget.bytecodeVersion < JvmTarget.JVM_9.bytecodeVersion && runtimeStringConcat != JvmRuntimeStringConcat.DISABLE) {
messageCollector.report(
WARNING,
"`-Xruntime-string-concat=${arguments.runtimeStringConcat}` does nothing with JVM target `${jvmTarget.description}`."
)
}
} else {
messageCollector.report(
ERROR, "Unknown `runtime-string-concat` mode: ${arguments.jvmTarget}\n" +
"Supported versions: ${JvmRuntimeStringConcat.values().joinToString { it.name.toLowerCase() }}"
)
}
}
addAll(JVMConfigurationKeys.ADDITIONAL_JAVA_MODULES, arguments.additionalJavaModules?.asList())
}
@@ -111,6 +111,9 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> EMIT_JVM_TYPE_ANNOTATIONS =
CompilerConfigurationKey.create("Emit JVM type annotations in bytecode");
public static final CompilerConfigurationKey<JvmRuntimeStringConcat> RUNTIME_STRING_CONCAT =
CompilerConfigurationKey.create("Specifies string concatenation scheme");
public static final CompilerConfigurationKey<List<String>> KLIB_PATHS =
CompilerConfigurationKey.create("Paths to .klib libraries");
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.config
enum class JvmRuntimeStringConcat {
DISABLE,
ENABLE, // makeConcatWithConstants
INDY; // makeConcat
val isDynamic
get() = this != DISABLE
companion object {
@JvmStatic
fun fromString(string: String) = values().find { it.name == string.toUpperCase() }
}
}
+5
View File
@@ -81,6 +81,11 @@ where advanced options include:
profilerPath is a path to libasyncProfiler.so
Example: -Xprofile=<PATH_TO_ASYNC_PROFILER>/async-profiler/build/libasyncProfiler.so:event=cpu,interval=1ms,threads,start,framebuf=50000000:<SNAPSHOT_DIR_PATH>
-Xrepeat=<number> Debug option: Repeats modules compilation <number> times
-Xruntime-string-concat={disable|enable|indy}
Switch a way in which string concatenation is performed.
-Xruntime-string-concat=enable Performs string concatenation via `invokedynamic` 'makeConcatWithConstants'. Works only with `-jvm-target 9` or greater
-Xruntime-string-concat=indy Performs string concatenation via `invokedynamic` 'makeConcat'. Works only with `-jvm-target 9` or greater
-Xruntime-string-concat=disable Performs string concatenation via `StringBuilder`
-Xsanitize-parentheses Transform '(' and ')' in method names to some other character sequence.
This mode can BREAK BINARY COMPATIBILITY and is only supposed to be used to workaround
problems with parentheses in identifiers on certain platforms
@@ -1,3 +1,4 @@
// KOTLIN_CONFIGURATION_FLAGS: RUNTIME_STRING_CONCAT=enable
// JVM_TARGET: 9
class A
@@ -1,3 +1,4 @@
// KOTLIN_CONFIGURATION_FLAGS: RUNTIME_STRING_CONCAT=enable
// JVM_TARGET: 9
fun box() {
@@ -1,3 +1,4 @@
// KOTLIN_CONFIGURATION_FLAGS: RUNTIME_STRING_CONCAT=enable
// JVM_TARGET: 9
fun box() {
val z = "0"
@@ -1,3 +1,4 @@
// KOTLIN_CONFIGURATION_FLAGS: RUNTIME_STRING_CONCAT=enable
// JVM_TARGET: 9
class A
@@ -1,3 +1,4 @@
// KOTLIN_CONFIGURATION_FLAGS: RUNTIME_STRING_CONCAT=enable
// JVM_TARGET: 9
fun box(a: String, b: String?) {
val sb = StringBuilder();
@@ -1,3 +1,4 @@
// KOTLIN_CONFIGURATION_FLAGS: RUNTIME_STRING_CONCAT=enable
// JVM_TARGET: 9
fun box(): String {
val z = "0"
@@ -1,3 +1,4 @@
// KOTLIN_CONFIGURATION_FLAGS: RUNTIME_STRING_CONCAT=enable
// JVM_TARGET: 9
fun box(): String {
val z = "0"
@@ -157,6 +157,7 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
"CONSTRUCTOR_CALL_NORMALIZATION_MODE=([a-zA-Z_\\-0-9]*)"
)
private val ASSERTIONS_MODE_FLAG_PATTERN = Pattern.compile("ASSERTIONS_MODE=([a-zA-Z_0-9-]*)")
private val RUNTIME_STRING_CONCAT = Pattern.compile("RUNTIME_STRING_CONCAT=([a-zA-Z_0-9-]*)")
private fun tryApplyBooleanFlag(
configuration: CompilerConfiguration,
@@ -294,6 +295,14 @@ abstract class KotlinBaseTest<F : KotlinBaseTest.TestFile> : KtUsefulTestCase()
?: error("Wrong ASSERTIONS_MODE value: $flagValueString")
configuration.put(JVMConfigurationKeys.ASSERTIONS_MODE, mode)
}
m = RUNTIME_STRING_CONCAT.matcher(flag)
if (m.matches()) {
val flagValueString = m.group(1)
val mode = JvmRuntimeStringConcat.fromString(flagValueString)
?: error("Wrong RUNTIME_STRING_CONCAT value: $flagValueString")
configuration.put(JVMConfigurationKeys.RUNTIME_STRING_CONCAT, mode)
}
}
}