avoid coercing 'this' to a supertype; cleaner handling of stackvalues for 'this' and 'super' (KT-2395)

This commit is contained in:
Dmitry Jemerov
2012-07-11 16:59:01 +02:00
parent 739a1f8245
commit de3f5d0e2d
7 changed files with 45 additions and 33 deletions
@@ -127,7 +127,7 @@ public class ClosureAnnotator {
}
@NotNull
public ClassDescriptor classDescriptorForScrpitDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
public ClassDescriptor classDescriptorForScriptDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
ClassDescriptorImpl classDescriptor = classesForFunctions.get(scriptDescriptor);
if (classDescriptor == null) {
throw new IllegalStateException("Class for script is not registered: " + scriptDescriptor);
@@ -146,7 +146,7 @@ public class ClosureAnnotator {
@NotNull
public JvmClassName classNameForScriptDescriptor(@NotNull ScriptDescriptor scriptDescriptor) {
return classNameForClassDescriptor(classDescriptorForScrpitDescriptor(scriptDescriptor));
return classNameForClassDescriptor(classDescriptorForScriptDescriptor(scriptDescriptor));
}
private void mapFilesToNamespaces(Collection<JetFile> files) {
@@ -35,11 +35,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ScriptReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibraryNames;
@@ -136,7 +132,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
assert provided instanceof ClassDescriptor;
if (!CodegenUtil.isInterface(provided) && CodegenUtil.isInterface(required)) {
v.checkcast(asmType(required.getDefaultType()));
inner.put(TYPE_OBJECT, v);
final Type type = asmType(required.getDefaultType());
v.checkcast(type);
return StackValue.onStack(type);
}
return inner;
@@ -199,7 +198,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue visitSuperExpression(JetSuperExpression expression, StackValue data) {
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
if (descriptor instanceof ClassDescriptor) {
return generateThisOrOuter((ClassDescriptor) descriptor);
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor);
}
else {
JetType type = context.getThisDescriptor().getDefaultType();
@@ -1161,9 +1160,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (descriptor instanceof ValueParameterDescriptor && descriptor.getContainingDeclaration() instanceof ScriptDescriptor) {
ScriptDescriptor scriptDescriptor = (ScriptDescriptor) descriptor.getContainingDeclaration();
JvmClassName scriptClassName = state.getInjector().getClosureAnnotator().classNameForScriptDescriptor(scriptDescriptor);
final ClosureAnnotator closureAnnotator = state.getInjector().getClosureAnnotator();
JvmClassName scriptClassName = closureAnnotator.classNameForScriptDescriptor(scriptDescriptor);
ValueParameterDescriptor valueParameterDescriptor = (ValueParameterDescriptor) descriptor;
generateThisOrOuter(state.getInjector().getClosureAnnotator().classDescriptorForScrpitDescriptor(scriptDescriptor));
final ClassDescriptor scriptClass = closureAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor);
final StackValue script = StackValue.thisOrOuter(this, scriptClass);
script.put(script.type, v);
Type fieldType = typeMapper.mapType(valueParameterDescriptor.getType(), MapTypeMode.VALUE);
return StackValue.field(fieldType, scriptClassName, valueParameterDescriptor.getName().getIdentifier(), false);
}
@@ -1513,27 +1515,23 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} else {
v.getstatic(classObjType.getInternalName(), "$classobj", exprType.getDescriptor());
}
StackValue.onStack(exprType).put(type, v);
}
else {
generateThisOrOuter(classReceiverDeclarationDescriptor).put(exprType, v);
StackValue.thisOrOuter(this, classReceiverDeclarationDescriptor).put(type, v);
}
StackValue.onStack(exprType).put(type, v);
}
else if (descriptor instanceof ScriptReceiver) {
generateScript((ScriptReceiver) descriptor);
}
else if (descriptor instanceof ExtensionReceiver) {
Type exprType = asmType(descriptor.getType());
ExtensionReceiver extensionReceiver = (ExtensionReceiver) descriptor;
generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(exprType, v);
StackValue.onStack(exprType).put(type, v);
generateReceiver(extensionReceiver.getDeclarationDescriptor()).put(type, v);
}
else if (descriptor instanceof ExpressionReceiver) {
ExpressionReceiver expressionReceiver = (ExpressionReceiver) descriptor;
JetExpression expr = expressionReceiver.getExpression();
Type exprType = asmType(expressionReceiver.getType());
gen(expr, exprType);
StackValue.onStack(exprType).put(type, v);
gen(expr, type);
}
else if (descriptor instanceof AutoCastReceiver) {
AutoCastReceiver autoCastReceiver = (AutoCastReceiver) descriptor;
@@ -1602,25 +1600,23 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
cur = cur.getParentContext();
}
throw new UnsupportedOperationException(); }
public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass) {
CodegenContext cur = context;
throw new UnsupportedOperationException();
}
public StackValue generateThisOrOuter(@NotNull final ClassDescriptor calleeContainingClass) {
PsiElement psiElement = BindingContextUtils.classDescriptorToDeclaration(bindingContext, calleeContainingClass);
boolean isObject = psiElement instanceof JetClassOrObject && CodegenUtil.isNonLiteralObject((JetClassOrObject) psiElement);
cur = context;
StackValue result = StackValue.local(0, TYPE_OBJECT);
CodegenContext cur = context;
Type type = asmType(calleeContainingClass.getDefaultType());
StackValue result = StackValue.local(0, type);
while (cur != null) {
if (cur instanceof CodegenContexts.MethodContext && !(cur instanceof CodegenContexts.ConstructorContext))
cur = cur.getParentContext();
if (DescriptorUtils.isSubclass(cur.getThisDescriptor(), calleeContainingClass)) {
Type type = asmType(calleeContainingClass.getDefaultType());
if (!isObject || (cur.getThisDescriptor() == calleeContainingClass)) {
result.put(TYPE_OBJECT, v);
return castToRequiredTypeOfInterfaceIfNeeded(StackValue.onStack(type), cur.getThisDescriptor(), calleeContainingClass);
return castToRequiredTypeOfInterfaceIfNeeded(result, cur.getThisDescriptor(), calleeContainingClass);
}
else {
v.getstatic(type.getInternalName(), "$instance", type.getDescriptor());
@@ -2697,7 +2693,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue visitThisExpression(JetThisExpression expression, StackValue receiver) {
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
if (descriptor instanceof ClassDescriptor) {
return generateThisOrOuter((ClassDescriptor) descriptor);
return StackValue.thisOrOuter(this, (ClassDescriptor) descriptor);
}
else {
if (descriptor instanceof FunctionDescriptor || descriptor instanceof PropertyDescriptor) {
@@ -953,7 +953,7 @@ public class JetTypeMapper {
for (ScriptDescriptor importedScript : importedScripts) {
signatureWriter.writeParameterType(JvmMethodParameterKind.VALUE);
mapType(closureAnnotator.classDescriptorForScrpitDescriptor(importedScript).getDefaultType(), signatureWriter, MapTypeMode.VALUE);
mapType(closureAnnotator.classDescriptorForScriptDescriptor(importedScript).getDefaultType(), signatureWriter, MapTypeMode.VALUE);
signatureWriter.writeParameterTypeEnd();
}
@@ -35,7 +35,6 @@ import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import javax.inject.Inject;
import java.util.Collections;
import java.util.List;
/**
@@ -99,7 +98,7 @@ public class ScriptCodegen {
ScriptDescriptor scriptDescriptor = (ScriptDescriptor) state.getBindingContext().get(BindingContext.SCRIPT, scriptDeclaration);
ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScrpitDescriptor(scriptDescriptor);
ClassDescriptor classDescriptorForScript = closureAnnotator.classDescriptorForScriptDescriptor(scriptDescriptor);
CodegenContexts.ScriptContext context = (CodegenContexts.ScriptContext) CodegenContexts.STATIC.intoScript(scriptDescriptor, classDescriptorForScript);
@@ -1087,7 +1087,8 @@ public abstract class StackValue {
@Override
public void put(Type type, InstructionAdapter v) {
codegen.generateThisOrOuter(descriptor);
final StackValue stackValue = codegen.generateThisOrOuter(descriptor);
stackValue.put(stackValue.type, v); // no coercion here
}
}
@@ -0,0 +1,11 @@
import java.util.AbstractList
class MyList(): AbstractList<String>() {
public fun getModificationCount(): Int = modCount
public override fun get(index: Int): String? = ""
public override fun size(): Int = 0
}
fun box(): String {
return if (MyList().getModificationCount() == 0) "OK" else "fail"
}
@@ -471,4 +471,9 @@ public class ClassGenTest extends CodegenTestCase {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
blackBoxMultiFile("regressions/kt2060_1.kt", "regressions/kt2060.kt");
}
public void testKt2395() {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
blackBoxMultiFile("regressions/kt2395.kt");
}
}