Support platform static in call receiver, keep side effect on skiped receiver generation

This commit is contained in:
Michael Bogdanov
2014-11-18 14:46:34 +03:00
parent 6b2272e422
commit 9bac3a8055
2 changed files with 57 additions and 24 deletions
@@ -28,6 +28,7 @@ import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression; import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.annotations.AnnotationsPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAbi;
@@ -63,9 +64,15 @@ public abstract class StackValue {
@NotNull @NotNull
public final Type type; public final Type type;
private final boolean hasSideEffects;
protected StackValue(@NotNull Type type) { protected StackValue(@NotNull Type type) {
this(type, true);
}
protected StackValue(@NotNull Type type, boolean hasSideEffects) {
this.type = type; this.type = type;
this.hasSideEffects = hasSideEffects;
} }
/** /**
@@ -113,6 +120,10 @@ public abstract class StackValue {
store(value, v, false); store(value, v, false);
} }
public boolean hasSideEffects() {
return hasSideEffects;
}
public void store(@NotNull StackValue value, @NotNull InstructionAdapter v, boolean skipReceiver) { public void store(@NotNull StackValue value, @NotNull InstructionAdapter v, boolean skipReceiver) {
if (!skipReceiver) { if (!skipReceiver) {
putReceiver(v, false); putReceiver(v, false);
@@ -429,7 +440,10 @@ public abstract class StackValue {
if (resolvedCall.getDispatchReceiver().exists() || resolvedCall.getExtensionReceiver().exists() || isLocalFunCall(callableMethod)) { if (resolvedCall.getDispatchReceiver().exists() || resolvedCall.getExtensionReceiver().exists() || isLocalFunCall(callableMethod)) {
boolean hasExtensionReceiver = resolvedCall.getExtensionReceiver().exists(); boolean hasExtensionReceiver = resolvedCall.getExtensionReceiver().exists();
StackValue extensionReceiver = genReceiver(receiver, codegen, resolvedCall, callableMethod, true); StackValue extensionReceiver = genReceiver(receiver, codegen, resolvedCall, callableMethod, true);
StackValue dispatchReceiver = genReceiver(hasExtensionReceiver ? none() : receiver, codegen, resolvedCall, callableMethod, false); StackValue dispatchReceiver = platformStaticCallIfPresent(
genReceiver(hasExtensionReceiver ? none() : receiver, codegen, resolvedCall, callableMethod, false),
resolvedCall.getResultingDescriptor()
);
return new CallReceiver(dispatchReceiver, extensionReceiver, return new CallReceiver(dispatchReceiver, extensionReceiver,
CallReceiver.calcType(resolvedCall, codegen.typeMapper, callableMethod)); CallReceiver.calcType(resolvedCall, codegen.typeMapper, callableMethod));
} }
@@ -453,6 +467,18 @@ public abstract class StackValue {
return none(); return none();
} }
private static StackValue platformStaticCallIfPresent(@NotNull StackValue resultReceiver, @NotNull CallableDescriptor descriptor) {
if (AnnotationsPackage.isPlatformStaticInObject(descriptor)) {
//dispatch receiver
if (resultReceiver.hasSideEffects()) {
resultReceiver = coercion(resultReceiver, Type.VOID_TYPE);
} else {
resultReceiver = none();
}
}
return resultReceiver;
}
@Contract("null -> false") @Contract("null -> false")
private static boolean isLocalFunCall(@Nullable CallableMethod callableMethod) { private static boolean isLocalFunCall(@Nullable CallableMethod callableMethod) {
return callableMethod != null && callableMethod.getGenerateCalleeType() != null; return callableMethod != null && callableMethod.getGenerateCalleeType() != null;
@@ -487,7 +513,7 @@ public abstract class StackValue {
public static final None INSTANCE = new None(); public static final None INSTANCE = new None();
private None() { private None() {
super(Type.VOID_TYPE); super(Type.VOID_TYPE, false);
} }
@Override @Override
@@ -500,7 +526,7 @@ public abstract class StackValue {
public final int index; public final int index;
private Local(int index, Type type) { private Local(int index, Type type) {
super(type); super(type, false);
this.index = index; this.index = index;
if (index < 0) { if (index < 0) {
@@ -561,7 +587,7 @@ public abstract class StackValue {
private final Object value; private final Object value;
public Constant(@Nullable Object value, Type type) { public Constant(@Nullable Object value, Type type) {
super(type); super(type, false);
this.value = value; this.value = value;
} }
@@ -1047,7 +1073,7 @@ public abstract class StackValue {
public final String name; public final String name;
public Field(Type type, Type owner, String name, boolean isStatic, StackValue receiver) { public Field(Type type, Type owner, String name, boolean isStatic, StackValue receiver) {
super(type, isStatic, isStatic, receiver); super(type, isStatic, isStatic, receiver, false);
this.owner = owner; this.owner = owner;
this.name = name; this.name = name;
} }
@@ -1157,17 +1183,12 @@ public abstract class StackValue {
public static class Shared extends StackValueWithSimpleReceiver { public static class Shared extends StackValueWithSimpleReceiver {
private final int index; private final int index;
private boolean isReleaseOnPut = false;
public Shared(int index, Type type) { public Shared(int index, Type type) {
super(type, false, false, local(index, OBJECT_TYPE)); super(type, false, false, local(index, OBJECT_TYPE), false);
this.index = index; this.index = index;
} }
public void releaseOnPut() {
isReleaseOnPut = true;
}
public int getIndex() { public int getIndex() {
return index; return index;
} }
@@ -1179,10 +1200,6 @@ public abstract class StackValue {
v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor()); v.visitFieldInsn(GETFIELD, sharedType.getInternalName(), "element", refType.getDescriptor());
coerceFrom(refType, v); coerceFrom(refType, v);
coerceTo(type, v); coerceTo(type, v);
if (isReleaseOnPut) {
v.aconst(null);
v.store(index, OBJECT_TYPE);
}
} }
@Override @Override
@@ -1234,7 +1251,7 @@ public abstract class StackValue {
final String name; final String name;
public FieldForSharedVar(Type type, Type owner, String name, StackValue.Field receiver) { public FieldForSharedVar(Type type, Type owner, String name, StackValue.Field receiver) {
super(type, false, false, receiver); super(type, false, false, receiver, false);
this.owner = owner; this.owner = owner;
this.name = name; this.name = name;
} }
@@ -1262,7 +1279,7 @@ public abstract class StackValue {
private final boolean coerceType; private final boolean coerceType;
public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper, boolean coerceType) { public ThisOuter(ExpressionCodegen codegen, ClassDescriptor descriptor, boolean isSuper, boolean coerceType) {
super(OBJECT_TYPE); super(OBJECT_TYPE, false);
this.codegen = codegen; this.codegen = codegen;
this.descriptor = descriptor; this.descriptor = descriptor;
this.isSuper = isSuper; this.isSuper = isSuper;
@@ -1366,7 +1383,7 @@ public abstract class StackValue {
@NotNull StackValue extensionReceiver, @NotNull StackValue extensionReceiver,
@NotNull Type type @NotNull Type type
) { ) {
super(type); super(type, dispatchReceiver.hasSideEffects() || extensionReceiver.hasSideEffects());
this.dispatchReceiver = dispatchReceiver; this.dispatchReceiver = dispatchReceiver;
this.extensionReceiver = extensionReceiver; this.extensionReceiver = extensionReceiver;
} }
@@ -1385,7 +1402,11 @@ public abstract class StackValue {
return callableMethod != null ? callableMethod.getReceiverClass() : typeMapper.mapType(extensionReceiver.getType()); return callableMethod != null ? callableMethod.getReceiverClass() : typeMapper.mapType(extensionReceiver.getType());
} }
else if (dispatchReceiver != null) { else if (dispatchReceiver != null) {
return callableMethod != null ? callableMethod.getThisType() : typeMapper.mapType(dispatchReceiver.getType()); if (AnnotationsPackage.isPlatformStaticInObject(descriptor)) {
return Type.VOID_TYPE;
} else {
return callableMethod != null ? callableMethod.getThisType() : typeMapper.mapType(dispatchReceiver.getType());
}
} }
else if (isLocalFunCall(callableMethod)) { else if (isLocalFunCall(callableMethod)) {
return callableMethod.getGenerateCalleeType(); return callableMethod.getGenerateCalleeType();
@@ -1423,14 +1444,24 @@ public abstract class StackValue {
@NotNull Type type, @NotNull Type type,
boolean isStaticPut, boolean isStaticPut,
boolean isStaticStore, boolean isStaticStore,
@NotNull StackValue receiver @NotNull StackValue receiver,
boolean hasSideEffects
) { ) {
super(type); super(type, hasSideEffects);
this.receiver = receiver; this.receiver = receiver;
this.isStaticPut = isStaticPut; this.isStaticPut = isStaticPut;
this.isStaticStore = isStaticStore; this.isStaticStore = isStaticStore;
} }
public StackValueWithSimpleReceiver(
@NotNull Type type,
boolean isStaticPut,
boolean isStaticStore,
@NotNull StackValue receiver
) {
this(type, isStaticPut, isStaticStore, receiver, true);
}
@Override @Override
public void putReceiver(@NotNull InstructionAdapter v, boolean isRead) { public void putReceiver(@NotNull InstructionAdapter v, boolean isRead) {
if (hasReceiver(isRead)) { if (hasReceiver(isRead)) {
@@ -1552,7 +1583,7 @@ public abstract class StackValue {
@NotNull StackValueWithSimpleReceiver originalValue, @NotNull StackValueWithSimpleReceiver originalValue,
@NotNull StackValue receiver @NotNull StackValue receiver
) { ) {
super(type, bothReceiverStatic(originalValue), bothReceiverStatic(originalValue), receiver); super(type, bothReceiverStatic(originalValue), bothReceiverStatic(originalValue), receiver, originalValue.hasSideEffects());
this.originalValue = originalValue; this.originalValue = originalValue;
} }
@@ -1656,3 +1687,4 @@ public abstract class StackValue {
} }
} }
} }
@@ -24,7 +24,7 @@ import org.jetbrains.jet.codegen.StackValue.StackValueWithSimpleReceiver
class CoercionValue( class CoercionValue(
val value: StackValue, val value: StackValue,
val castType: Type val castType: Type
) : StackValue(castType) { ) : StackValue(castType, value.hasSideEffects()) {
override fun putSelector(type: Type, v: InstructionAdapter) { override fun putSelector(type: Type, v: InstructionAdapter) {
value.putSelector(castType, v) value.putSelector(castType, v)
@@ -86,4 +86,5 @@ open class OperationStackValue(val resultType: Type, val lambda: (v: Instruction
} }
} }
class FunctionCallStackValue(resultType: Type, lambda: (v: InstructionAdapter)-> Unit) : OperationStackValue(resultType, lambda) class FunctionCallStackValue(resultType: Type, lambda: (v: InstructionAdapter)-> Unit) : OperationStackValue(resultType, lambda)