optimization of toString for primitive types and "$expr"
- intrinsic toString for promitive types added to stdlib - utility method added to CodegenUtil - optimization logic added to generation of interpolating string
This commit is contained in:
@@ -382,4 +382,15 @@ public class CodegenUtil {
|
||||
new Type[] {exprType.getSort() == Type.OBJECT ? (exprType.equals(JAVA_STRING_TYPE) ? JAVA_STRING_TYPE : OBJECT_TYPE) : exprType});
|
||||
v.invokevirtual("java/lang/StringBuilder", "append", appendDescriptor.getDescriptor());
|
||||
}
|
||||
|
||||
public static StackValue genToString(InstructionAdapter v, StackValue receiver) {
|
||||
final int sort = receiver.type.getSort();
|
||||
|
||||
final Type type = sort == Type.OBJECT || sort == Type.ARRAY
|
||||
? AsmTypeConstants.OBJECT_TYPE
|
||||
: sort == Type.BYTE || sort == Type.SHORT ? Type.INT_TYPE : receiver.type;
|
||||
receiver.put(type, v);
|
||||
v.invokestatic("java/lang/String", "valueOf", "(" + type.getDescriptor() + ")Ljava/lang/String;");
|
||||
return StackValue.onStack(JAVA_STRING_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -968,7 +968,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
@Override
|
||||
public StackValue visitStringTemplateExpression(JetStringTemplateExpression expression, StackValue receiver) {
|
||||
StringBuilder constantValue = new StringBuilder("");
|
||||
for (JetStringTemplateEntry entry : expression.getEntries()) {
|
||||
final JetStringTemplateEntry[] entries = expression.getEntries();
|
||||
|
||||
if (entries.length == 1 && entries[0] instanceof JetStringTemplateEntryWithExpression) {
|
||||
return genToString(v, gen(entries[0].getExpression()));
|
||||
}
|
||||
|
||||
for (JetStringTemplateEntry entry : entries) {
|
||||
if (entry instanceof JetLiteralStringTemplateEntry) {
|
||||
constantValue.append(entry.getText());
|
||||
}
|
||||
@@ -986,7 +992,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
}
|
||||
else {
|
||||
generateStringBuilderConstructor(v);
|
||||
for (JetStringTemplateEntry entry : expression.getEntries()) {
|
||||
for (JetStringTemplateEntry entry : entries) {
|
||||
if (entry instanceof JetStringTemplateEntryWithExpression) {
|
||||
invokeAppend(entry.getExpression());
|
||||
}
|
||||
|
||||
@@ -62,8 +62,11 @@ public class IntrinsicMethods {
|
||||
public static final String KOTLIN_JAVA_CLASS_FUNCTION = "kotlin.javaClass.function";
|
||||
public static final String KOTLIN_ARRAYS_ARRAY = "kotlin.arrays.array";
|
||||
private static final String KOTLIN_JAVA_CLASS_PROPERTY = "kotlin.javaClass.property";
|
||||
private static final String KOTLIN_TO_STRING = "kotlin.toString";
|
||||
private static final String KOTLIN_HASH_CODE = "kotlin.hashCode";
|
||||
private static final EnumValues ENUM_VALUES = new EnumValues();
|
||||
private static final EnumValueOf ENUM_VALUE_OF = new EnumValueOf();
|
||||
public static final ToString TO_STRING = new ToString();
|
||||
|
||||
private final Map<String, IntrinsicMethod> namedMethods = new HashMap<String, IntrinsicMethod>();
|
||||
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
|
||||
@@ -75,6 +78,8 @@ public class IntrinsicMethods {
|
||||
namedMethods.put(KOTLIN_JAVA_CLASS_FUNCTION, new JavaClassFunction());
|
||||
namedMethods.put(KOTLIN_JAVA_CLASS_PROPERTY, new JavaClassProperty());
|
||||
namedMethods.put(KOTLIN_ARRAYS_ARRAY, new JavaClassArray());
|
||||
namedMethods.put(KOTLIN_HASH_CODE, HASH_CODE);
|
||||
namedMethods.put(KOTLIN_TO_STRING, TO_STRING);
|
||||
|
||||
ImmutableList<Name> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
|
||||
for (Name method : primitiveCastMethods) {
|
||||
@@ -117,7 +122,7 @@ public class IntrinsicMethods {
|
||||
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("name"), 0, new EnumName());
|
||||
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("ordinal"), 0, new EnumOrdinal());
|
||||
|
||||
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("toString"), 0, new ToString());
|
||||
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("toString"), 0, TO_STRING);
|
||||
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("equals"), 1, EQUALS);
|
||||
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("identityEquals"), 1, IDENTITY_EQUALS);
|
||||
intrinsicsMap.registerIntrinsic(JetStandardClasses.STANDARD_CLASSES_FQNAME, Name.identifier("plus"), 1, STRING_PLUS);
|
||||
|
||||
@@ -20,11 +20,11 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.asm4.Type;
|
||||
import org.jetbrains.asm4.commons.InstructionAdapter;
|
||||
import org.jetbrains.jet.codegen.CodegenUtil;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.resolve.java.AsmTypeConstants;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -42,14 +42,6 @@ public class ToString implements IntrinsicMethod {
|
||||
StackValue receiver,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
if (receiver.type.getSort() == Type.OBJECT || receiver.type.getSort() == Type.ARRAY) {
|
||||
receiver.put(AsmTypeConstants.OBJECT_TYPE, v);
|
||||
v.invokestatic("java/lang/String", "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;");
|
||||
}
|
||||
else {
|
||||
receiver.put(receiver.type, v);
|
||||
v.invokestatic("java/lang/String", "valueOf", "(" + receiver.type.getDescriptor() + ")Ljava/lang/String;");
|
||||
}
|
||||
return StackValue.onStack(AsmTypeConstants.JAVA_STRING_TYPE);
|
||||
return CodegenUtil.genToString(v, receiver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,24 @@ fun box(): String {
|
||||
if (239.toByte().toString() != (239.toByte() as Byte?).toString()) return "byte failed"
|
||||
if (239.toShort().toString() != (239.toShort() as Short?).toString()) return "short failed"
|
||||
if (239.toInt().toString() != (239.toInt() as Int?).toString()) return "int failed"
|
||||
if (239.toFloat().toString() != (239.toFloat() as Float?).toString()) return "float failed"
|
||||
if (239.toLong().toString() != (239.toLong() as Long?).toString()) return "long failed"
|
||||
if (239.toDouble().toString() != (239.toDouble() as Double?).toString()) return "double failed"
|
||||
if (true.toString() != (true as Boolean?).toString()) return "boolean failed"
|
||||
if ('a'.toChar().toString() != ('a'.toChar() as Char?).toString()) return "char failed"
|
||||
|
||||
|
||||
if ("${239.toByte()}" != (239.toByte() as Byte?).toString()) return "byte template failed"
|
||||
if ("${239.toShort()}" != (239.toShort() as Short?).toString()) return "short template failed"
|
||||
if ("${239.toInt()}" != (239.toInt() as Int?).toString()) return "int template failed"
|
||||
if ("${239.toFloat()}" != (239.toFloat() as Float?).toString()) return "float template failed"
|
||||
if ("${239.toLong()}" != (239.toLong() as Long?).toString()) return "long template failed"
|
||||
if ("${239.toDouble()}" != (239.toDouble() as Double?).toString()) return "double template failed"
|
||||
if ("${true}" != (true as Boolean?).toString()) return "boolean template failed"
|
||||
if ("${'a'.toChar()}" != ('a'.toChar() as Char?).toString()) return "char template failed"
|
||||
|
||||
for(b in 0..255) {
|
||||
if("${b.toByte()}" != (b.toByte() as Byte?).toString()) return "byte conversion failed"
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
||||
|
||||
public void testByteLess() throws Exception {
|
||||
binOpTest("fun foo(a: Byte, b: Byte): Boolean = a < b",
|
||||
Byte.valueOf((byte) 126), Byte.valueOf((byte) 127), true);
|
||||
Byte.valueOf((byte) 126), Byte.valueOf((byte) 127), true);
|
||||
}
|
||||
|
||||
public void testBooleanConstant() throws Exception {
|
||||
@@ -448,8 +448,4 @@ public class PrimitiveTypesTest extends CodegenTestCase {
|
||||
public void testEmptyRanges() throws Exception {
|
||||
blackBoxFile("emptyRanges.kt");
|
||||
}
|
||||
|
||||
public void testToString() throws Exception {
|
||||
blackBoxFile("intrinsics/tostring.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,3 +9,58 @@ public val <out T> T.javaClass : Class<T>
|
||||
[Intrinsic("kotlin.javaClass.property")] get() = (this as java.lang.Object).getClass() as Class<T>
|
||||
|
||||
[Intrinsic("kotlin.javaClass.function")] fun <out T> javaClass() : Class<T> = null as Class<T>
|
||||
|
||||
|
||||
/**
|
||||
* A helper method for calling hashCode() on Kotlin objects
|
||||
* TODO remove when Any supports equals() and hashCode()
|
||||
*/
|
||||
[Intrinsic("kotlin.hashCode")] public inline fun Any.hashCode(): Int = (this as java.lang.Object).hashCode()
|
||||
|
||||
/**
|
||||
* A helper method for calling toString() on Kotlin primitives
|
||||
* TODO remove when Any supports toString()
|
||||
*/
|
||||
[Intrinsic("kotlin.toString")] public fun Boolean.toString(): String = (null as String)
|
||||
|
||||
/**
|
||||
* A helper method for calling toString() on Kotlin primitives
|
||||
* TODO remove when Any supports toString()
|
||||
*/
|
||||
[Intrinsic("kotlin.toString")] public fun Byte.toString(): String = (null as String)
|
||||
|
||||
/**
|
||||
* A helper method for calling toString() on Kotlin primitives
|
||||
* TODO remove when Any supports toString()
|
||||
*/
|
||||
[Intrinsic("kotlin.toString")] public fun Short.toString(): String = (null as String)
|
||||
|
||||
/**
|
||||
* A helper method for calling toString() on Kotlin primitives
|
||||
* TODO remove when Any supports toString()
|
||||
*/
|
||||
[Intrinsic("kotlin.toString")] public fun Char.toString(): String = (null as String)
|
||||
|
||||
/**
|
||||
* A helper method for calling toString() on Kotlin primitives
|
||||
* TODO remove when Any supports toString()
|
||||
*/
|
||||
[Intrinsic("kotlin.toString")] public fun Int.toString(): String = (null as String)
|
||||
|
||||
/**
|
||||
* A helper method for calling toString() on Kotlin primitives
|
||||
* TODO remove when Any supports toString()
|
||||
*/
|
||||
[Intrinsic("kotlin.toString")] public fun Float.toString(): String = (null as String)
|
||||
|
||||
/**
|
||||
* A helper method for calling toString() on Kotlin primitives
|
||||
* TODO remove when Any supports toString()
|
||||
*/
|
||||
[Intrinsic("kotlin.toString")] public fun Long.toString(): String = (null as String)
|
||||
|
||||
/**
|
||||
* A helper method for calling toString() on Kotlin primitives
|
||||
* TODO remove when Any supports toString()
|
||||
*/
|
||||
[Intrinsic("kotlin.toString")] public fun Double.toString(): String = (null as String)
|
||||
|
||||
@@ -47,9 +47,3 @@ public inline fun <T> callable(action: ()-> T): Callable<T> {
|
||||
public override fun call() = action()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper method for calling hashCode() on Kotlin objects
|
||||
* TODO remove when Any supports equals() and hashCode()
|
||||
*/
|
||||
public inline fun Any.hashCode(): Int = (this as java.lang.Object).hashCode()
|
||||
|
||||
Reference in New Issue
Block a user