JVM_IR KT-13213 split string constants into parts of acceptable length

This commit is contained in:
Dmitry Petrov
2020-12-25 13:07:54 +03:00
committed by TeamCityServer
parent 3f287d344e
commit 5d4b0b19d4
11 changed files with 3078 additions and 0 deletions
@@ -811,11 +811,39 @@ class ExpressionCodegen(
is Float -> mv.fconst(value)
is Double -> mv.dconst(value)
is Number -> mv.iconst(value.toInt())
is String -> generateStringConstant(value)
else -> if (expression.kind == IrConstKind.Null) return nullConstant else mv.aconst(value)
}
return expression.onStack
}
private fun generateStringConstant(value: String) {
val length = value.length
// Strings in constant pool contain at most 2^16-1 = 65535 bytes.
// Non-BMP characters in UTF8 require at most 4 bytes.
val maxPartLength = 65535 / 4
if (length <= maxPartLength) {
mv.aconst(value)
} else {
// Split strings into parts, each of which satisfies JVM class file constant pool constraints.
// Note that even if we split surrogate pairs between parts, they will be joined on concatenation.
mv.anew(Type.getObjectType("java/lang/StringBuilder"))
mv.dup()
mv.iconst(length)
mv.invokespecial("java/lang/StringBuilder", "<init>", "(I)V", false)
var i = 0
while (i < length) {
val j = minOf(i + maxPartLength, length)
mv.aconst(value.substring(i, j))
mv.invokevirtual("java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false)
i += maxPartLength
}
mv.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)
}
}
override fun visitExpressionBody(body: IrExpressionBody, data: BlockInfo) =
body.expression.accept(this, data)