Minor, fixes after review
This commit is contained in:
committed by
Alexander Udalov
parent
3dea4bc07d
commit
485ac3f809
@@ -2601,7 +2601,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateExpressionWithNullFallback(@NotNull JetExpression expression, @NotNull Label ifnull) {
|
private void generateExpressionWithNullFallback(@NotNull JetExpression expression, @NotNull Label ifnull) {
|
||||||
|
expression = JetPsiUtil.deparenthesize(expression);
|
||||||
Type type = expressionType(expression);
|
Type type = expressionType(expression);
|
||||||
|
|
||||||
if (expression instanceof JetSafeQualifiedExpression && !isPrimitive(type)) {
|
if (expression instanceof JetSafeQualifiedExpression && !isPrimitive(type)) {
|
||||||
StackValue value = generateSafeQualifiedExpression((JetSafeQualifiedExpression) expression, ifnull);
|
StackValue value = generateSafeQualifiedExpression((JetSafeQualifiedExpression) expression, ifnull);
|
||||||
value.put(type, v);
|
value.put(type, v);
|
||||||
@@ -2612,11 +2614,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackValue generateSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, @NotNull Label ifnull) {
|
private StackValue generateSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, @NotNull Label ifnull) {
|
||||||
JetExpression receiver = JetPsiUtil.deparenthesize(expression.getReceiverExpression());
|
JetExpression receiver = expression.getReceiverExpression();
|
||||||
JetExpression selector = expression.getSelectorExpression();
|
JetExpression selector = expression.getSelectorExpression();
|
||||||
Type receiverType = expressionType(receiver);
|
Type receiverType = expressionType(receiver);
|
||||||
|
|
||||||
assert receiver != null : "receiver should be not null: " + expression.getText();
|
|
||||||
generateExpressionWithNullFallback(receiver, ifnull);
|
generateExpressionWithNullFallback(receiver, ifnull);
|
||||||
|
|
||||||
if (isPrimitive(receiverType)) {
|
if (isPrimitive(receiverType)) {
|
||||||
@@ -2631,13 +2632,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
@Override
|
@Override
|
||||||
public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) {
|
public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) {
|
||||||
Label ifnull = new Label();
|
Label ifnull = new Label();
|
||||||
Label end = new Label();
|
|
||||||
Type type = boxType(expressionType(expression));
|
Type type = boxType(expressionType(expression));
|
||||||
|
|
||||||
StackValue value = generateSafeQualifiedExpression(expression, ifnull);
|
StackValue value = generateSafeQualifiedExpression(expression, ifnull);
|
||||||
value.put(type, v);
|
value.put(type, v);
|
||||||
|
|
||||||
if (!isPrimitive(expressionType(expression.getReceiverExpression()))) {
|
if (!isPrimitive(expressionType(expression.getReceiverExpression()))) {
|
||||||
|
Label end = new Label();
|
||||||
|
|
||||||
v.goTo(end);
|
v.goTo(end);
|
||||||
v.mark(ifnull);
|
v.mark(ifnull);
|
||||||
v.pop();
|
v.pop();
|
||||||
@@ -2845,13 +2847,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StackValue generateElvis(JetBinaryExpression expression) {
|
private StackValue generateElvis(JetBinaryExpression expression) {
|
||||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
JetExpression left = expression.getLeft();
|
||||||
|
|
||||||
Type exprType = expressionType(expression);
|
Type exprType = expressionType(expression);
|
||||||
Type leftType = expressionType(left);
|
Type leftType = expressionType(left);
|
||||||
|
|
||||||
Label ifNull = new Label();
|
Label ifNull = new Label();
|
||||||
Label end = new Label();
|
|
||||||
|
|
||||||
assert left != null : "left expression in elvis should be not null: " + expression.getText();
|
assert left != null : "left expression in elvis should be not null: " + expression.getText();
|
||||||
generateExpressionWithNullFallback(left, ifNull);
|
generateExpressionWithNullFallback(left, ifNull);
|
||||||
@@ -2864,6 +2866,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
v.ifnull(ifNull);
|
v.ifnull(ifNull);
|
||||||
StackValue.onStack(leftType).put(exprType, v);
|
StackValue.onStack(leftType).put(exprType, v);
|
||||||
|
|
||||||
|
Label end = new Label();
|
||||||
v.goTo(end);
|
v.goTo(end);
|
||||||
|
|
||||||
v.mark(ifNull);
|
v.mark(ifNull);
|
||||||
|
|||||||
+7
-6
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen.optimization.boxing;
|
package org.jetbrains.jet.codegen.optimization.boxing;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.codegen.AsmUtil;
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
|
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
|
||||||
@@ -28,12 +29,12 @@ import java.util.Set;
|
|||||||
public class BoxedBasicValue extends BasicValue {
|
public class BoxedBasicValue extends BasicValue {
|
||||||
private final Set<AbstractInsnNode> associatedInsns = new HashSet<AbstractInsnNode>();
|
private final Set<AbstractInsnNode> associatedInsns = new HashSet<AbstractInsnNode>();
|
||||||
private final AbstractInsnNode boxingInsn;
|
private final AbstractInsnNode boxingInsn;
|
||||||
private final Type boxedType;
|
private final Type primitiveType;
|
||||||
private boolean wasUnboxed = false;
|
private boolean wasUnboxed = false;
|
||||||
|
|
||||||
public BoxedBasicValue(Type type, Type boxedType, AbstractInsnNode insnNode) {
|
public BoxedBasicValue(Type primitiveType, AbstractInsnNode insnNode) {
|
||||||
super(type);
|
super(AsmUtil.boxType(primitiveType));
|
||||||
this.boxedType = boxedType;
|
this.primitiveType = primitiveType;
|
||||||
associatedInsns.add(insnNode);
|
associatedInsns.add(insnNode);
|
||||||
boxingInsn = insnNode;
|
boxingInsn = insnNode;
|
||||||
}
|
}
|
||||||
@@ -58,8 +59,8 @@ public class BoxedBasicValue extends BasicValue {
|
|||||||
associatedInsns.add(insnNode);
|
associatedInsns.add(insnNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getBoxedType() {
|
public Type getPrimitiveType() {
|
||||||
return boxedType;
|
return primitiveType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean wasUnboxed() {
|
public boolean wasUnboxed() {
|
||||||
|
|||||||
+63
-31
@@ -16,10 +16,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.codegen.optimization.boxing;
|
package org.jetbrains.jet.codegen.optimization.boxing;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.codegen.AsmUtil;
|
||||||
import org.jetbrains.jet.codegen.optimization.common.OptimizationBasicInterpreter;
|
import org.jetbrains.jet.codegen.optimization.common.OptimizationBasicInterpreter;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type;
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
import org.jetbrains.org.objectweb.asm.tree.InsnList;
|
import org.jetbrains.org.objectweb.asm.tree.InsnList;
|
||||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode;
|
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode;
|
||||||
@@ -31,6 +35,18 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
||||||
|
private static final ImmutableSet<String> wrappersClassNames;
|
||||||
|
|
||||||
|
static {
|
||||||
|
ImmutableSet.Builder<String> wrappersClassesBuilder = ImmutableSet.builder();
|
||||||
|
|
||||||
|
for (JvmPrimitiveType primitiveType : JvmPrimitiveType.values()) {
|
||||||
|
wrappersClassesBuilder.add(AsmUtil.internalNameByFqNameWithoutInnerClasses(primitiveType.getWrapperFqName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
wrappersClassNames = wrappersClassesBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
private final Map<Integer, BoxedBasicValue> boxingPlaces = new HashMap<Integer, BoxedBasicValue>();
|
private final Map<Integer, BoxedBasicValue> boxingPlaces = new HashMap<Integer, BoxedBasicValue>();
|
||||||
private final InsnList insnList;
|
private final InsnList insnList;
|
||||||
|
|
||||||
@@ -38,24 +54,15 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
this.insnList = insnList;
|
this.insnList = insnList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isClassBox(@NotNull String owner) {
|
private static boolean isWrapperClassName(@NotNull String owner) {
|
||||||
|
return wrappersClassNames.contains(owner);
|
||||||
if (!owner.startsWith("java/lang/")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String className = owner.substring("java/lang/".length());
|
|
||||||
|
|
||||||
return (className.equals("Integer") ||
|
|
||||||
className.equals("Double") ||
|
|
||||||
className.equals("Long") ||
|
|
||||||
className.equals("Char") ||
|
|
||||||
className.equals("Byte") ||
|
|
||||||
className.equals("Boolean")) ||
|
|
||||||
className.endsWith("Number");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isUnboxingMethod(@NotNull String name) {
|
private static boolean isWrapperClassNameOrNumber(@NotNull String owner) {
|
||||||
|
return isWrapperClassName(owner) || owner.equals(Type.getInternalName(Number.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isUnboxingMethodName(@NotNull String name) {
|
||||||
return name.endsWith("Value");
|
return name.endsWith("Value");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +73,7 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
|
|
||||||
MethodInsnNode methodInsn = (MethodInsnNode) insn;
|
MethodInsnNode methodInsn = (MethodInsnNode) insn;
|
||||||
|
|
||||||
return isClassBox(methodInsn.owner) && isUnboxingMethod(methodInsn.name);
|
return isWrapperClassNameOrNumber(methodInsn.owner) && isUnboxingMethodName(methodInsn.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isBoxing(@NotNull AbstractInsnNode insn) {
|
private static boolean isBoxing(@NotNull AbstractInsnNode insn) {
|
||||||
@@ -76,7 +83,7 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
|
|
||||||
MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
|
MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
|
||||||
|
|
||||||
return isClassBox(methodInsnNode.owner) && methodInsnNode.name.equals("valueOf");
|
return isWrapperClassName(methodInsnNode.owner) && methodInsnNode.name.equals("valueOf");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,32 +94,30 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
if (isBoxing(insn)) {
|
if (isBoxing(insn)) {
|
||||||
int index = insnList.indexOf(insn);
|
int index = insnList.indexOf(insn);
|
||||||
if (!boxingPlaces.containsKey(index)) {
|
if (!boxingPlaces.containsKey(index)) {
|
||||||
BoxedBasicValue boxedBasicValue = new BoxedBasicValue(value.getType(), values.get(0).getType(), insn);
|
BoxedBasicValue boxedBasicValue = new BoxedBasicValue(values.get(0).getType(), insn);
|
||||||
onNewBoxedValue(boxedBasicValue);
|
onNewBoxedValue(boxedBasicValue);
|
||||||
boxingPlaces.put(index, boxedBasicValue);
|
boxingPlaces.put(index, boxedBasicValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return boxingPlaces.get(index);
|
return boxingPlaces.get(index);
|
||||||
}
|
} else if (isUnboxing(insn) &&
|
||||||
|
|
||||||
if (isUnboxing(insn) &&
|
|
||||||
values.get(0) instanceof BoxedBasicValue &&
|
values.get(0) instanceof BoxedBasicValue &&
|
||||||
value.getType().equals(((BoxedBasicValue) values.get(0)).getBoxedType())) {
|
value.getType().equals(((BoxedBasicValue) values.get(0)).getPrimitiveType())) {
|
||||||
|
|
||||||
BoxedBasicValue boxedBasicValue = (BoxedBasicValue) values.get(0);
|
BoxedBasicValue boxedBasicValue = (BoxedBasicValue) values.get(0);
|
||||||
boxedBasicValue.addInsn(insn);
|
boxedBasicValue.addInsn(insn);
|
||||||
boxedBasicValue.setWasUnboxed(true);
|
boxedBasicValue.setWasUnboxed(true);
|
||||||
|
} else {
|
||||||
|
for (BasicValue arg : values) {
|
||||||
|
if (arg instanceof BoxedBasicValue) {
|
||||||
|
onMethodCallWithBoxedValue((BoxedBasicValue) arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onNewBoxedValue(BoxedBasicValue value) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isAllowedUnaryOperationWithBoxed(int opcode) {
|
|
||||||
return opcode == Opcodes.CHECKCAST || opcode == Opcodes.IFNULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -128,10 +133,37 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
|||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) {
|
public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) {
|
||||||
if (v instanceof BoxedBasicValue && w instanceof BoxedBasicValue && v.equals(w)) {
|
if (v instanceof BoxedBasicValue && v.equals(w)) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v instanceof BoxedBasicValue) {
|
||||||
|
onMergeFail((BoxedBasicValue) v);
|
||||||
|
v = new BasicValue(v.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w instanceof BoxedBasicValue) {
|
||||||
|
onMergeFail((BoxedBasicValue) w);
|
||||||
|
w = new BasicValue(w.getType());
|
||||||
|
}
|
||||||
|
|
||||||
return super.merge(v, w);
|
return super.merge(v, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void onNewBoxedValue(BoxedBasicValue value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onMethodCallWithBoxedValue(BoxedBasicValue value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onMergeFail(BoxedBasicValue value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isAllowedUnaryOperationWithBoxed(int opcode) {
|
||||||
|
return opcode == Opcodes.CHECKCAST || opcode == Opcodes.IFNULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-17
@@ -36,8 +36,17 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onNewBoxedValue(BoxedBasicValue value) {
|
public BasicValue binaryOperation(
|
||||||
candidatesBoxedValues.add(value);
|
@NotNull AbstractInsnNode insn,
|
||||||
|
@NotNull BasicValue value1,
|
||||||
|
@NotNull BasicValue value2
|
||||||
|
) throws AnalyzerException {
|
||||||
|
|
||||||
|
if (insn.getOpcode() == Opcodes.PUTFIELD && value2 instanceof BoxedBasicValue) {
|
||||||
|
markAsDirty((BoxedBasicValue) value2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.binaryOperation(insn, value1, value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -50,7 +59,7 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
|
|||||||
public BasicValue copyOperation(@NotNull AbstractInsnNode insn, @NotNull BasicValue value) throws AnalyzerException {
|
public BasicValue copyOperation(@NotNull AbstractInsnNode insn, @NotNull BasicValue value) throws AnalyzerException {
|
||||||
// currently we don't allow any copy operations with boxed values
|
// currently we don't allow any copy operations with boxed values
|
||||||
if (value instanceof BoxedBasicValue) {
|
if (value instanceof BoxedBasicValue) {
|
||||||
candidatesBoxedValues.remove(value);
|
markAsDirty((BoxedBasicValue) value);
|
||||||
return new BasicValue(value.getType());
|
return new BasicValue(value.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,23 +67,22 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
protected void onNewBoxedValue(BoxedBasicValue value) {
|
||||||
public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) {
|
candidatesBoxedValues.add(value);
|
||||||
if (v instanceof BoxedBasicValue && w instanceof BoxedBasicValue && v == w) {
|
}
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v instanceof BoxedBasicValue) {
|
private void markAsDirty(BoxedBasicValue value) {
|
||||||
candidatesBoxedValues.remove(v);
|
candidatesBoxedValues.remove(value);
|
||||||
v = new BasicValue(v.getType());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (w instanceof BoxedBasicValue) {
|
@Override
|
||||||
candidatesBoxedValues.remove(w);
|
protected void onMethodCallWithBoxedValue(BoxedBasicValue value) {
|
||||||
w = new BasicValue(w.getType());
|
markAsDirty(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.merge(v, w);
|
@Override
|
||||||
|
protected void onMergeFail(BoxedBasicValue v) {
|
||||||
|
markAsDirty(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+5
-5
@@ -24,10 +24,10 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Frame;
|
|||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Value;
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Value;
|
||||||
|
|
||||||
public abstract class MethodTransformer {
|
public abstract class MethodTransformer {
|
||||||
private final MethodTransformer methodTransformer;
|
private final MethodTransformer delegate;
|
||||||
|
|
||||||
protected MethodTransformer(MethodTransformer methodTransformer) {
|
protected MethodTransformer(MethodTransformer delegate) {
|
||||||
this.methodTransformer = methodTransformer;
|
this.delegate = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static <V extends Value> Frame<V>[] runAnalyzer(
|
protected static <V extends Value> Frame<V>[] runAnalyzer(
|
||||||
@@ -44,8 +44,8 @@ public abstract class MethodTransformer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void transform(@NotNull String owner, @NotNull MethodNode methodNode) {
|
public void transform(@NotNull String owner, @NotNull MethodNode methodNode) {
|
||||||
if (methodTransformer != null) {
|
if (delegate != null) {
|
||||||
methodTransformer.transform(owner, methodNode);
|
delegate.transform(owner, methodNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user