KT-2589 fix: putting some order on bytecode flags

This commit is contained in:
Alex Tkachman
2012-08-09 13:35:44 +03:00
parent f5e9786ffc
commit 6af235fe2b
10 changed files with 105 additions and 63 deletions
+30
View File
@@ -0,0 +1,30 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All Jvm Backend Tests" type="JUnit" factoryName="JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea">
<pattern>
<option name="PATTERN" value="org.jetbrains.jet.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<module name="compiler-tests" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" value="" />
<option name="PACKAGE_NAME" value="org.jetbrains.jet.codegen" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea -XX:+HeapDumpOnOutOfMemoryError -Xmx512m -XX:MaxPermSize=320m" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="wholeProject" />
</option>
<envs />
<patterns />
<RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Run" />
<method />
</configuration>
</component>
@@ -16,7 +16,6 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.asm4.FieldVisitor;
import org.jetbrains.asm4.MethodVisitor; import org.jetbrains.asm4.MethodVisitor;
import org.jetbrains.asm4.Opcodes; import org.jetbrains.asm4.Opcodes;
import org.jetbrains.asm4.Type; import org.jetbrains.asm4.Type;
@@ -25,14 +24,12 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import static org.jetbrains.asm4.Opcodes.ACC_ABSTRACT; import static org.jetbrains.asm4.Opcodes.ACC_ABSTRACT;
import static org.jetbrains.asm4.Opcodes.ACC_PRIVATE;
import static org.jetbrains.asm4.Opcodes.ACC_PUBLIC; import static org.jetbrains.asm4.Opcodes.ACC_PUBLIC;
/** /**
@@ -100,26 +97,10 @@ public abstract class ClassBodyCodegen {
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
if (!isAnnotation) { if (!isAnnotation) {
int accessModifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); propertyCodegen.generateBackingField(p, propertyDescriptor);
if((accessModifiers & ACC_PRIVATE) == 0) { propertyCodegen.generateDefaultGetter(propertyDescriptor, JetTypeMapper.getAccessModifiers(propertyDescriptor,0), p);
propertyCodegen.generateDefaultGetter(propertyDescriptor, accessModifiers, p); if (propertyDescriptor.isVar()) {
if (propertyDescriptor.isVar()) { propertyCodegen.generateDefaultSetter(propertyDescriptor, JetTypeMapper.getAccessModifiers(propertyDescriptor,0), p);
propertyCodegen.generateDefaultSetter(propertyDescriptor, accessModifiers, origin);
}
}
//noinspection ConstantConditions
if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
int modifiers = accessModifiers;
if (!propertyDescriptor.isVar()) {
modifiers |= Opcodes.ACC_FINAL;
}
if (JetStandardLibrary.isVolatile(propertyDescriptor)) {
modifiers |= Opcodes.ACC_VOLATILE;
}
Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
FieldVisitor fieldVisitor = v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, null);
AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor);
} }
} }
else { else {
@@ -1027,18 +1027,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
} }
for (JetParameter p : toClass.getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = bindingContext.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, ACC_PUBLIC, p);
}
}
}
}
} }
@Nullable @Nullable
@@ -1002,7 +1002,7 @@ public class JetTypeMapper {
return defaultFlags; return defaultFlags;
} }
if (p.getContainingDeclaration() instanceof NamespaceDescriptor) { if (p.getContainingDeclaration() instanceof NamespaceDescriptor) {
return ACC_PROTECTED; return 0;
} }
return ACC_PRIVATE; return ACC_PRIVATE;
} }
@@ -41,6 +41,7 @@ import java.util.BitSet;
/** /**
* @author max * @author max
* @author alex.tkachman
*/ */
public class PropertyCodegen { public class PropertyCodegen {
private final GenerationState state; private final GenerationState state;
@@ -75,14 +76,14 @@ public class PropertyCodegen {
} }
} }
private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) { public void generateBackingField(PsiElement p, PropertyDescriptor propertyDescriptor) {
if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
if (CodegenUtil.isInterface(containingDeclaration)) if (CodegenUtil.isInterface(containingDeclaration))
return; return;
Object value = null; Object value = null;
final JetExpression initializer = p.getInitializer(); final JetExpression initializer = p instanceof JetProperty ? ((JetProperty)p).getInitializer() : null;
if (initializer != null) { if (initializer != null) {
if (initializer instanceof JetConstantExpression) { if (initializer instanceof JetConstantExpression) {
CompileTimeConstant<?> compileTimeValue = state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer); CompileTimeConstant<?> compileTimeValue = state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer);
@@ -91,11 +92,10 @@ public class PropertyCodegen {
} }
int modifiers; int modifiers;
if (kind == OwnerKind.NAMESPACE) { if (kind == OwnerKind.NAMESPACE) {
int access = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); modifiers = Opcodes.ACC_STATIC;
modifiers = access | Opcodes.ACC_STATIC;
} }
else { else {
modifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); modifiers = Opcodes.ACC_PRIVATE;
} }
if (!propertyDescriptor.isVar()) { if (!propertyDescriptor.isVar()) {
modifiers |= Opcodes.ACC_FINAL; modifiers |= Opcodes.ACC_FINAL;
@@ -104,7 +104,7 @@ public class PropertyCodegen {
modifiers |= Opcodes.ACC_VOLATILE; modifiers |= Opcodes.ACC_VOLATILE;
} }
Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE); Type type = state.getInjector().getJetTypeMapper().mapType(propertyDescriptor.getType(), MapTypeMode.VALUE);
FieldVisitor fieldVisitor = v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, value); FieldVisitor fieldVisitor = v.newField(p, modifiers, propertyDescriptor.getName().getName(), type.getDescriptor(), null, value);
AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor); AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper()).genAnnotations(propertyDescriptor);
} }
} }
@@ -150,7 +150,8 @@ public class PropertyCodegen {
private void generateDefaultGetter(JetProperty p) { private void generateDefaultGetter(JetProperty p) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p); final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p);
int flags = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0) | (propertyDescriptor.getModality() == Modality.ABSTRACT ? Opcodes.ACC_ABSTRACT : 0); assert propertyDescriptor != null;
int flags = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0) | (propertyDescriptor.getModality() == Modality.ABSTRACT ? Opcodes.ACC_ABSTRACT : (propertyDescriptor.getModality() == Modality.FINAL ? Opcodes.ACC_FINAL : 0));
generateDefaultGetter(propertyDescriptor, flags, p); generateDefaultGetter(propertyDescriptor, flags, p);
} }
@@ -21,7 +21,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.DescriptorResolver;
import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.lang.resolve.ScriptNameUtil;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -34,11 +33,9 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; 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.ScriptReceiver;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeSubstitutor; import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -106,17 +103,8 @@ public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl {
if(jetDeclaration instanceof JetProperty) { if(jetDeclaration instanceof JetProperty) {
VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, jetDeclaration); VariableDescriptor descriptor = bindingContext.get(BindingContext.VARIABLE, jetDeclaration);
assert descriptor != null; assert descriptor != null;
propertyDescriptor = new PropertyDescriptor(classDescriptor, initializeWithDefaultGetterSetter((PropertyDescriptor) descriptor);
Collections.<AnnotationDescriptor>emptyList(), classScope.addPropertyDescriptor(descriptor);
Modality.FINAL,
propertyDescriptor.getVisibility(),
false,
false,
descriptor.getName(),
CallableMemberDescriptor.Kind.DECLARATION);
propertyDescriptor.setType(returnType, Collections.<TypeParameterDescriptor>emptyList(), classReceiver, ReceiverDescriptor.NO_RECEIVER);
propertyDescriptor.initialize(null, null);
classScope.addPropertyDescriptor(propertyDescriptor);
} }
else if(jetDeclaration instanceof JetNamedFunction) { else if(jetDeclaration instanceof JetNamedFunction) {
SimpleFunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, jetDeclaration); SimpleFunctionDescriptor descriptor = bindingContext.get(BindingContext.FUNCTION, jetDeclaration);
@@ -128,6 +116,21 @@ public class ScriptDescriptor extends DeclarationDescriptorNonRootImpl {
} }
} }
public static void initializeWithDefaultGetterSetter(PropertyDescriptor propertyDescriptor) {
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
if(getter == null) {
getter = propertyDescriptor.getVisibility() != Visibilities.PRIVATE ? DescriptorResolver.createDefaultGetter(propertyDescriptor) : null;
if(getter != null)
getter.initialize(propertyDescriptor.getType());
}
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
if(setter == null) {
setter = propertyDescriptor.isVar() ? DescriptorResolver.createDefaultSetter(propertyDescriptor) : null;
}
propertyDescriptor.initialize(getter, setter);
}
public int getPriority() { public int getPriority() {
return priority; return priority;
} }
@@ -372,7 +372,7 @@ public class DescriptorResolver {
return constructorDescriptor; return constructorDescriptor;
} }
final class UpperBoundCheckerTask { static final class UpperBoundCheckerTask {
JetTypeReference upperBound; JetTypeReference upperBound;
JetType upperBoundType; JetType upperBoundType;
boolean isClassObjectConstraint; boolean isClassObjectConstraint;
@@ -834,7 +834,7 @@ public class DescriptorResolver {
return setterDescriptor; return setterDescriptor;
} }
private PropertySetterDescriptor createDefaultSetter(PropertyDescriptor propertyDescriptor) { public static PropertySetterDescriptor createDefaultSetter(PropertyDescriptor propertyDescriptor) {
PropertySetterDescriptor setterDescriptor; PropertySetterDescriptor setterDescriptor;
setterDescriptor = new PropertySetterDescriptor( setterDescriptor = new PropertySetterDescriptor(
propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), propertyDescriptor.getModality(), propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), propertyDescriptor.getModality(),
@@ -0,0 +1 @@
open class Foo(var foo: String?, open protected val bar: String?)
@@ -16,6 +16,7 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import org.jetbrains.asm4.Opcodes;
import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.ConfigurationKind;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@@ -81,7 +82,7 @@ public class PropertyGenTest extends CodegenTestCase {
final Field field = fields[0]; final Field field = fields[0];
field.setAccessible(true); field.setAccessible(true);
assertEquals("x", field.getName()); assertEquals("x", field.getName());
assertEquals(Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL, field.getModifiers()); assertEquals(Modifier.STATIC | Modifier.FINAL, field.getModifiers());
assertEquals(239, field.get(null)); assertEquals(239, field.get(null));
} }
@@ -279,4 +280,32 @@ public class PropertyGenTest extends CodegenTestCase {
blackBoxFile("regressions/kt2509.kt"); blackBoxFile("regressions/kt2509.kt");
} }
public void testKt2589() throws Exception {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
loadFile("regressions/kt2589.kt");
final Class aClass = loadImplementationClass(generateClassesInFile(), "Foo");
assertTrue((aClass.getModifiers() & Opcodes.ACC_FINAL) == 0);
try {
Field foo = aClass.getDeclaredField("foo");
assertTrue((foo.getModifiers() & Opcodes.ACC_PRIVATE) != 0);
assertTrue((foo.getModifiers() & Opcodes.ACC_FINAL) == 0);
Field bar = aClass.getDeclaredField("bar");
assertTrue((bar.getModifiers() & Opcodes.ACC_PRIVATE) != 0);
assertTrue((bar.getModifiers() & Opcodes.ACC_FINAL) != 0);
Method getFoo = aClass.getDeclaredMethod("getFoo");
assertTrue((getFoo.getModifiers() & Opcodes.ACC_PUBLIC) != 0);
assertTrue((getFoo.getModifiers() & Opcodes.ACC_FINAL) != 0);
Method getBar = aClass.getDeclaredMethod("getBar");
assertTrue((getBar.getModifiers() & Opcodes.ACC_PROTECTED) != 0);
assertTrue((getBar.getModifiers() & Opcodes.ACC_FINAL) == 0);
}
catch (Throwable e) {
System.out.println(generateToText());
throw new RuntimeException(e);
}
}
} }
@@ -17,6 +17,7 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.ServiceManager;
import org.jetbrains.asm4.Opcodes;
import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.ConfigurationKind;
import org.jetbrains.jet.lang.parsing.JetParserDefinition; import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.parsing.JetScriptDefinition; import org.jetbrains.jet.lang.parsing.JetScriptDefinition;
@@ -106,7 +107,8 @@ public class ScriptGenTest extends CodegenTestCase {
final Class aClass = loadClass("Fib", generateClassesInFile()); final Class aClass = loadClass("Fib", generateClassesInFile());
try { try {
Constructor constructor = aClass.getConstructor(int.class); Constructor constructor = aClass.getConstructor(int.class);
Field result = aClass.getField("result"); Field result = aClass.getDeclaredField("result");
result.setAccessible(true);
Object script = constructor.newInstance(5); Object script = constructor.newInstance(5);
assertEquals(8,result.get(script)); assertEquals(8,result.get(script));
} }
@@ -121,7 +123,8 @@ public class ScriptGenTest extends CodegenTestCase {
final Class aClass = loadClass("test.Fibwp", generateClassesInFile()); final Class aClass = loadClass("test.Fibwp", generateClassesInFile());
try { try {
Constructor constructor = aClass.getConstructor(int.class); Constructor constructor = aClass.getConstructor(int.class);
Field result = aClass.getField("result"); Field result = aClass.getDeclaredField("result");
result.setAccessible(true);
Object script = constructor.newInstance(5); Object script = constructor.newInstance(5);
assertEquals(8,result.get(script)); assertEquals(8,result.get(script));
} }
@@ -136,11 +139,17 @@ public class ScriptGenTest extends CodegenTestCase {
final Class aClass = loadClass("Fibwprunner", generateClassesInFile()); final Class aClass = loadClass("Fibwprunner", generateClassesInFile());
try { try {
Constructor constructor = aClass.getConstructor(); Constructor constructor = aClass.getConstructor();
Field result = aClass.getField("result"); Field result = aClass.getDeclaredField("result");
result.setAccessible(true);
Method resultMethod = aClass.getDeclaredMethod("getResult");
assertTrue((resultMethod.getModifiers() & Opcodes.ACC_FINAL) != 0);
assertTrue((resultMethod.getModifiers() & Opcodes.ACC_PUBLIC) != 0);
Field rv = aClass.getField("rv"); Field rv = aClass.getField("rv");
assertTrue((result.getModifiers() & Opcodes.ACC_PRIVATE) != 0);
Object script = constructor.newInstance(); Object script = constructor.newInstance();
assertEquals(12,rv.get(script)); assertEquals(12,rv.get(script));
assertEquals(8,result.get(script)); assertEquals(8,result.get(script));
assertEquals(8,resultMethod.invoke(script));
} }
catch (Exception e) { catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);