Support platform static in call receiver, keep side effect on skiped receiver generation
This commit is contained in:
@@ -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)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user