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) {
|
||||
expression = JetPsiUtil.deparenthesize(expression);
|
||||
Type type = expressionType(expression);
|
||||
|
||||
if (expression instanceof JetSafeQualifiedExpression && !isPrimitive(type)) {
|
||||
StackValue value = generateSafeQualifiedExpression((JetSafeQualifiedExpression) expression, ifnull);
|
||||
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) {
|
||||
JetExpression receiver = JetPsiUtil.deparenthesize(expression.getReceiverExpression());
|
||||
JetExpression receiver = expression.getReceiverExpression();
|
||||
JetExpression selector = expression.getSelectorExpression();
|
||||
Type receiverType = expressionType(receiver);
|
||||
|
||||
assert receiver != null : "receiver should be not null: " + expression.getText();
|
||||
generateExpressionWithNullFallback(receiver, ifnull);
|
||||
|
||||
if (isPrimitive(receiverType)) {
|
||||
@@ -2631,13 +2632,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
@Override
|
||||
public StackValue visitSafeQualifiedExpression(@NotNull JetSafeQualifiedExpression expression, StackValue unused) {
|
||||
Label ifnull = new Label();
|
||||
Label end = new Label();
|
||||
Type type = boxType(expressionType(expression));
|
||||
|
||||
StackValue value = generateSafeQualifiedExpression(expression, ifnull);
|
||||
value.put(type, v);
|
||||
|
||||
if (!isPrimitive(expressionType(expression.getReceiverExpression()))) {
|
||||
Label end = new Label();
|
||||
|
||||
v.goTo(end);
|
||||
v.mark(ifnull);
|
||||
v.pop();
|
||||
@@ -2845,13 +2847,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
}
|
||||
|
||||
private StackValue generateElvis(JetBinaryExpression expression) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
JetExpression left = expression.getLeft();
|
||||
|
||||
Type exprType = expressionType(expression);
|
||||
Type leftType = expressionType(left);
|
||||
|
||||
Label ifNull = new Label();
|
||||
Label end = new Label();
|
||||
|
||||
|
||||
assert left != null : "left expression in elvis should be not null: " + expression.getText();
|
||||
generateExpressionWithNullFallback(left, ifNull);
|
||||
@@ -2864,6 +2866,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
v.ifnull(ifNull);
|
||||
StackValue.onStack(leftType).put(exprType, v);
|
||||
|
||||
Label end = new Label();
|
||||
v.goTo(end);
|
||||
|
||||
v.mark(ifNull);
|
||||
|
||||
+7
-6
@@ -16,6 +16,7 @@
|
||||
|
||||
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.tree.AbstractInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
|
||||
@@ -28,12 +29,12 @@ import java.util.Set;
|
||||
public class BoxedBasicValue extends BasicValue {
|
||||
private final Set<AbstractInsnNode> associatedInsns = new HashSet<AbstractInsnNode>();
|
||||
private final AbstractInsnNode boxingInsn;
|
||||
private final Type boxedType;
|
||||
private final Type primitiveType;
|
||||
private boolean wasUnboxed = false;
|
||||
|
||||
public BoxedBasicValue(Type type, Type boxedType, AbstractInsnNode insnNode) {
|
||||
super(type);
|
||||
this.boxedType = boxedType;
|
||||
public BoxedBasicValue(Type primitiveType, AbstractInsnNode insnNode) {
|
||||
super(AsmUtil.boxType(primitiveType));
|
||||
this.primitiveType = primitiveType;
|
||||
associatedInsns.add(insnNode);
|
||||
boxingInsn = insnNode;
|
||||
}
|
||||
@@ -58,8 +59,8 @@ public class BoxedBasicValue extends BasicValue {
|
||||
associatedInsns.add(insnNode);
|
||||
}
|
||||
|
||||
public Type getBoxedType() {
|
||||
return boxedType;
|
||||
public Type getPrimitiveType() {
|
||||
return primitiveType;
|
||||
}
|
||||
|
||||
public boolean wasUnboxed() {
|
||||
|
||||
+63
-31
@@ -16,10 +16,14 @@
|
||||
|
||||
package org.jetbrains.jet.codegen.optimization.boxing;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.AsmUtil;
|
||||
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.Type;
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.InsnList;
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode;
|
||||
@@ -31,6 +35,18 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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 InsnList insnList;
|
||||
|
||||
@@ -38,24 +54,15 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
||||
this.insnList = insnList;
|
||||
}
|
||||
|
||||
private static boolean isClassBox(@NotNull String 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 isWrapperClassName(@NotNull String owner) {
|
||||
return wrappersClassNames.contains(owner);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -66,7 +73,7 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
||||
|
||||
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) {
|
||||
@@ -76,7 +83,7 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
||||
|
||||
MethodInsnNode methodInsnNode = (MethodInsnNode) insn;
|
||||
|
||||
return isClassBox(methodInsnNode.owner) && methodInsnNode.name.equals("valueOf");
|
||||
return isWrapperClassName(methodInsnNode.owner) && methodInsnNode.name.equals("valueOf");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,32 +94,30 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
||||
if (isBoxing(insn)) {
|
||||
int index = insnList.indexOf(insn);
|
||||
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);
|
||||
boxingPlaces.put(index, boxedBasicValue);
|
||||
}
|
||||
|
||||
return boxingPlaces.get(index);
|
||||
}
|
||||
|
||||
if (isUnboxing(insn) &&
|
||||
} else if (isUnboxing(insn) &&
|
||||
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.addInsn(insn);
|
||||
boxedBasicValue.setWasUnboxed(true);
|
||||
} else {
|
||||
for (BasicValue arg : values) {
|
||||
if (arg instanceof BoxedBasicValue) {
|
||||
onMethodCallWithBoxedValue((BoxedBasicValue) arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
protected void onNewBoxedValue(BoxedBasicValue value) {
|
||||
|
||||
}
|
||||
|
||||
protected boolean isAllowedUnaryOperationWithBoxed(int opcode) {
|
||||
return opcode == Opcodes.CHECKCAST || opcode == Opcodes.IFNULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@@ -128,10 +133,37 @@ public class BoxingInterpreter extends OptimizationBasicInterpreter {
|
||||
@Override
|
||||
@NotNull
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
protected void onNewBoxedValue(BoxedBasicValue value) {
|
||||
candidatesBoxedValues.add(value);
|
||||
public BasicValue binaryOperation(
|
||||
@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
|
||||
@@ -50,7 +59,7 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
|
||||
public BasicValue copyOperation(@NotNull AbstractInsnNode insn, @NotNull BasicValue value) throws AnalyzerException {
|
||||
// currently we don't allow any copy operations with boxed values
|
||||
if (value instanceof BoxedBasicValue) {
|
||||
candidatesBoxedValues.remove(value);
|
||||
markAsDirty((BoxedBasicValue) value);
|
||||
return new BasicValue(value.getType());
|
||||
}
|
||||
|
||||
@@ -58,23 +67,22 @@ class RedundantBoxingInterpreter extends BoxingInterpreter {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) {
|
||||
if (v instanceof BoxedBasicValue && w instanceof BoxedBasicValue && v == w) {
|
||||
return v;
|
||||
}
|
||||
protected void onNewBoxedValue(BoxedBasicValue value) {
|
||||
candidatesBoxedValues.add(value);
|
||||
}
|
||||
|
||||
if (v instanceof BoxedBasicValue) {
|
||||
candidatesBoxedValues.remove(v);
|
||||
v = new BasicValue(v.getType());
|
||||
}
|
||||
private void markAsDirty(BoxedBasicValue value) {
|
||||
candidatesBoxedValues.remove(value);
|
||||
}
|
||||
|
||||
if (w instanceof BoxedBasicValue) {
|
||||
candidatesBoxedValues.remove(w);
|
||||
w = new BasicValue(w.getType());
|
||||
}
|
||||
@Override
|
||||
protected void onMethodCallWithBoxedValue(BoxedBasicValue value) {
|
||||
markAsDirty(value);
|
||||
}
|
||||
|
||||
return super.merge(v, w);
|
||||
@Override
|
||||
protected void onMergeFail(BoxedBasicValue v) {
|
||||
markAsDirty(v);
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
public abstract class MethodTransformer {
|
||||
private final MethodTransformer methodTransformer;
|
||||
private final MethodTransformer delegate;
|
||||
|
||||
protected MethodTransformer(MethodTransformer methodTransformer) {
|
||||
this.methodTransformer = methodTransformer;
|
||||
protected MethodTransformer(MethodTransformer delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (methodTransformer != null) {
|
||||
methodTransformer.transform(owner, methodNode);
|
||||
if (delegate != null) {
|
||||
delegate.transform(owner, methodNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user