'when' should use intrinsics for '=='

#KT-19029 Fixed Target versions 1.1.5
 #KT-18818 Fixed Target versions 1.1.5
This commit is contained in:
Dmitry Petrov
2017-07-17 14:43:37 +03:00
parent 20cd748377
commit 2ed5a5e368
13 changed files with 281 additions and 51 deletions
@@ -152,14 +152,6 @@ public class AsmUtil {
return isIntPrimitive(type) || type == Type.LONG_TYPE;
}
public static boolean isNumberPrimitiveOrBoolean(Type type) {
return isNumberPrimitive(type) || type.getSort() == Type.BOOLEAN;
}
public static boolean isNumberPrimitive(Type type) {
return isIntPrimitive(type) || type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE;
}
public static boolean isPrimitive(Type type) {
return type.getSort() != Type.OBJECT && type.getSort() != Type.ARRAY;
}
@@ -2840,7 +2840,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
else if (opToken == KtTokens.EQEQ || opToken == KtTokens.EXCLEQ ||
opToken == KtTokens.EQEQEQ || opToken == KtTokens.EXCLEQEQEQ) {
return generateEquals(expression.getLeft(), expression.getRight(), opToken);
return generateEquals(expression.getLeft(), expression.getRight(), opToken, null);
}
else if (opToken == KtTokens.LT || opToken == KtTokens.LTEQ ||
opToken == KtTokens.GT || opToken == KtTokens.GTEQ) {
@@ -2885,44 +2885,76 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return StackValue.or(gen(expression.getLeft()), gen(expression.getRight()));
}
private StackValue generateEquals(@Nullable KtExpression left, @Nullable KtExpression right, @NotNull IElementType opToken) {
private StackValue genLazyUnlessProvided(@Nullable StackValue pregenerated, @NotNull KtExpression expr, @NotNull Type type) {
return pregenerated != null ? StackValue.coercion(pregenerated, type) : genLazy(expr, type);
}
private StackValue genUnlessProvided(@Nullable StackValue pregenerated, @NotNull KtExpression expr, @NotNull Type type) {
if (pregenerated != null) {
pregenerated.put(type, v);
}
else {
gen(expr, type);
}
return StackValue.onStack(type);
}
private StackValue generateEquals(
@Nullable KtExpression left,
@Nullable KtExpression right,
@NotNull IElementType opToken,
@Nullable StackValue pregeneratedLeft
) {
Type leftType = expressionType(left);
Type rightType = expressionType(right);
if (KtPsiUtil.isNullConstant(left)) {
return genCmpWithNull(right, opToken);
return genCmpWithNull(right, opToken, null);
}
if (KtPsiUtil.isNullConstant(right)) {
return genCmpWithNull(left, opToken);
return genCmpWithNull(left, opToken, pregeneratedLeft);
}
if (isIntZero(left, leftType) && isIntPrimitive(rightType)) {
return genCmpWithZero(right, opToken);
return genCmpWithZero(right, opToken, null);
}
if (isIntZero(right, rightType) && isIntPrimitive(leftType)) {
return genCmpWithZero(left, opToken);
return genCmpWithZero(left, opToken, pregeneratedLeft);
}
if (left instanceof KtSafeQualifiedExpression && isPrimitive(rightType)) {
if (pregeneratedLeft == null && left instanceof KtSafeQualifiedExpression && isPrimitive(rightType)) {
return genCmpSafeCallToPrimitive((KtSafeQualifiedExpression) left, right, rightType, opToken);
}
if (isPrimitive(leftType) && right instanceof KtSafeQualifiedExpression) {
return genCmpPrimitiveToSafeCall(left, leftType, (KtSafeQualifiedExpression) right, opToken);
return genCmpPrimitiveToSafeCall(left, leftType, (KtSafeQualifiedExpression) right, opToken, pregeneratedLeft);
}
if (BoxedToPrimitiveEquality.isApplicable(opToken, leftType, rightType)) {
return BoxedToPrimitiveEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType,
myFrameMap);
return BoxedToPrimitiveEquality.create(
opToken,
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
genLazy(right, rightType), rightType,
myFrameMap
);
}
if (PrimitiveToBoxedEquality.isApplicable(opToken, leftType, rightType)) {
return PrimitiveToBoxedEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType);
return PrimitiveToBoxedEquality.create(
opToken,
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
genLazy(right, rightType), rightType
);
}
if (PrimitiveToObjectEquality.isApplicable(opToken, leftType, rightType)) {
return PrimitiveToObjectEquality.create(opToken, genLazy(left, leftType), leftType, genLazy(right, rightType), rightType);
return PrimitiveToObjectEquality.create(
opToken,
genLazyUnlessProvided(pregeneratedLeft, left, leftType), leftType,
genLazy(right, rightType), rightType
);
}
@@ -2934,23 +2966,29 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (opToken == KtTokens.EQEQEQ || opToken == KtTokens.EXCLEQEQEQ) {
// TODO: always casting to the type of the left operand in case of primitives looks wrong
Type operandType = isPrimitive(leftType) ? leftType : OBJECT_TYPE;
return StackValue.cmp(opToken, operandType, genLazy(left, leftType), genLazy(right, rightType));
return StackValue.cmp(
opToken,
operandType,
genLazyUnlessProvided(pregeneratedLeft, left, leftType),
genLazy(right, rightType)
);
}
return genEqualsForExpressionsPreferIEEE754Arithmetic(left, right, opToken, leftType, rightType, null);
return genEqualsForExpressionsPreferIEEE754Arithmetic(left, right, opToken, leftType, rightType, pregeneratedLeft);
}
private StackValue genCmpPrimitiveToSafeCall(
@NotNull KtExpression left,
@NotNull Type leftType,
@NotNull KtSafeQualifiedExpression right,
@NotNull IElementType opToken
@NotNull IElementType opToken,
@Nullable StackValue pregeneratedLeft
) {
Label rightIsNull = new Label();
return new PrimitiveToSafeCallEquality(
opToken,
leftType,
genLazy(left, leftType),
genLazyUnlessProvided(pregeneratedLeft, left, leftType),
generateSafeQualifiedExpression(right, rightIsNull),
expressionType(right.getReceiverExpression()),
rightIsNull
@@ -3011,7 +3049,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return genEqualsForExpressionsOnStack(
opToken,
pregeneratedLeft != null ? StackValue.coercion(pregeneratedLeft, leftType) : genLazy(left, leftType),
genLazyUnlessProvided(pregeneratedLeft, left, leftType),
genLazy(right, rightType)
);
}
@@ -3027,12 +3065,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
) {
Type leftType = left754Type.isNullable ? AsmUtil.boxType(left754Type.type) : left754Type.type;
if (pregeneratedLeft != null) {
StackValue.coercion(pregeneratedLeft, leftType).put(leftType, v);
}
else {
gen(left, leftType);
}
genUnlessProvided(pregeneratedLeft, left, leftType);
Type rightType = right754Type.isNullable ? AsmUtil.boxType(right754Type.type) : right754Type.type;
gen(right, rightType);
@@ -3141,12 +3174,18 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
return isIntPrimitive(exprType) && exprValue != null && Integer.valueOf(0).equals(exprValue.getValue());
}
private StackValue genCmpWithZero(KtExpression exp, IElementType opToken) {
return StackValue.compareIntWithZero(gen(exp), (KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNE : IFEQ);
private StackValue genCmpWithZero(KtExpression exp, IElementType opToken, @Nullable StackValue pregeneratedExpr) {
return StackValue.compareIntWithZero(
pregeneratedExpr != null ? pregeneratedExpr : gen(exp),
(KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNE : IFEQ
);
}
private StackValue genCmpWithNull(KtExpression exp, IElementType opToken) {
return StackValue.compareWithNull(gen(exp), (KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNONNULL : IFNULL);
private StackValue genCmpWithNull(KtExpression exp, IElementType opToken, @Nullable StackValue pregeneratedExpr) {
return StackValue.compareWithNull(
pregeneratedExpr != null ? pregeneratedExpr : gen(exp),
(KtTokens.EQEQ == opToken || KtTokens.EQEQEQ == opToken) ? IFNONNULL : IFNULL
);
}
private StackValue generateElvis(@NotNull KtBinaryExpression expression) {
@@ -4010,22 +4049,7 @@ The "returned" value of try expression with no finally is either the last expres
private StackValue generateExpressionMatch(StackValue expressionToMatch, KtExpression subjectExpression, KtExpression patternExpression) {
if (expressionToMatch != null) {
Type subjectType = expressionToMatch.type;
markStartLineNumber(patternExpression);
KotlinType condJetType = bindingContext.getType(patternExpression);
Type condType;
if (isNumberPrimitiveOrBoolean(subjectType)) {
assert condJetType != null;
condType = asmType(condJetType);
if (!isNumberPrimitiveOrBoolean(condType)) {
subjectType = boxType(subjectType);
}
}
else {
condType = OBJECT_TYPE;
}
return genEqualsForExpressionsPreferIEEE754Arithmetic(subjectExpression, patternExpression, KtTokens.EQEQ, subjectType, condType, expressionToMatch);
return generateEquals(subjectExpression, patternExpression, KtTokens.EQEQ, expressionToMatch);
}
else {
return gen(patternExpression);