StorageManager for compile-time initializer

This commit is contained in:
Natalia Ukhorskaya
2014-02-12 19:59:35 +04:00
parent 17259a052e
commit df3ed5059c
27 changed files with 75 additions and 89 deletions
@@ -1731,12 +1731,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetExpression initializer = property.getDelegateExpressionOrInitializer();
if (initializer == null) return false;
CompileTimeConstant<?> compileTimeValue = ExpressionCodegen.getCompileTimeConstant(initializer, typeMapper.getBindingContext());
if (compileTimeValue == null) return true;
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) typeMapper.getBindingContext().get(BindingContext.VARIABLE, property);
assert propertyDescriptor != null;
CompileTimeConstant<?> compileTimeValue = propertyDescriptor.getCompileTimeInitializer();
if (compileTimeValue == null) return true;
//TODO: OPTIMIZATION: don't initialize static final fields
Object value = compileTimeValue.getValue();
@@ -235,10 +235,9 @@ public class PropertyCodegen extends GenerationStateAware {
Object value = null;
if (ImplementationBodyCodegen.shouldWriteFieldInitializer(propertyDescriptor, typeMapper)) {
JetExpression initializer = p instanceof JetProperty ? ((JetProperty) p).getInitializer() : null;
CompileTimeConstant<?> initializer = propertyDescriptor.getCompileTimeInitializer();
if (initializer != null) {
CompileTimeConstant<?> compileTimeValue = ExpressionCodegen.getCompileTimeConstant(initializer, bindingContext);
value = compileTimeValue != null ? compileTimeValue.getValue() : null;
value = initializer.getValue();
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.jet.descriptors.serialization;
import kotlin.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.descriptors.*;
@@ -132,8 +133,8 @@ public class DescriptorDeserializer {
}
@NotNull
private PropertyDescriptor loadProperty(@NotNull Callable proto) {
int flags = proto.getFlags();
private PropertyDescriptor loadProperty(@NotNull final Callable proto) {
final int flags = proto.getFlags();
PropertyDescriptorImpl property = new PropertyDescriptorImpl(
containingDeclaration,
@@ -194,8 +195,15 @@ public class DescriptorDeserializer {
}
property.setCompileTimeInitializer(
getPropertyConstant(containingDeclaration, proto, flags, AnnotatedCallableKind.PROPERTY,
deserializers.getConstantDeserializer(), nameResolver)
storageManager.createNullableLazyValue(new Function0<CompileTimeConstant<?>>() {
@Nullable
@Override
public CompileTimeConstant<?> invoke() {
return getPropertyConstant(
containingDeclaration, proto, flags, AnnotatedCallableKind.PROPERTY,
deserializers.getConstantDeserializer(), nameResolver);
}
})
);
property.initialize(getter, setter);
@@ -28,7 +28,6 @@ import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.lang.resolve.BindingContext.COMPILE_TIME_INITIALIZER
import org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.jet.lang.types.TypeUtils
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument
@@ -299,7 +298,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
if (resolvedCall != null) {
val callableDescriptor = resolvedCall.getResultingDescriptor()
if (callableDescriptor is VariableDescriptor) {
val compileTimeConstant = callableDescriptor.getCompileTimeInitializer() ?: trace.getBindingContext().get(COMPILE_TIME_INITIALIZER, callableDescriptor)
val compileTimeConstant = callableDescriptor.getCompileTimeInitializer()
if (compileTimeConstant == null) return null
val value: Any? =
@@ -433,27 +432,6 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
}
}
public fun recordCompileTimeValueForInitializerIfNeeded(
variableDescriptor: VariableDescriptor,
initializer: JetExpression,
variableType: JetType,
trace: BindingTrace
) {
if (!variableDescriptor.isVar()) {
if (variableDescriptor.getCompileTimeInitializer() == null && trace.get(BindingContext.COMPILE_TIME_INITIALIZER, variableDescriptor) == null) {
val constant = ConstantExpressionEvaluator.evaluate(initializer, trace, variableType)
if (constant != null) {
if (constant is IntegerValueTypeConstant) {
trace.record(BindingContext.COMPILE_TIME_INITIALIZER, variableDescriptor, constant.createCompileTimeConstantWithType(variableType))
}
else {
trace.record(BindingContext.COMPILE_TIME_INITIALIZER, variableDescriptor, constant)
}
}
}
}
}
public fun IntegerValueTypeConstant.createCompileTimeConstantWithType(expectedType: JetType): CompileTimeConstant<*>?
= createCompileTimeConstant(this.getValue(expectedType), EvaluatorContext(this.canBeUsedInAnnotations(), true))
@@ -77,7 +77,6 @@ public interface BindingContext {
Slices.<JetAnnotationEntry, AnnotationDescriptorImpl>sliceBuilder().setOpposite(ANNOTATION_DESCRIPTOR_TO_PSI_ELEMENT).build();
WritableSlice<JetExpression, CompileTimeConstant<?>> COMPILE_TIME_VALUE = Slices.createSimpleSlice();
WritableSlice<VariableDescriptor, CompileTimeConstant<?>> COMPILE_TIME_INITIALIZER = Slices.createSimpleSlice();
WritableSlice<JetTypeReference, JetType> TYPE = Slices.createSimpleSlice();
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>(DO_NOTHING);
@@ -566,8 +566,6 @@ public class BodyResolver {
scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, c.getOuterDataFlowInfo(), trace);
EvaluatePackage.recordCompileTimeValueForInitializerIfNeeded(propertyDescriptor, initializer, expectedTypeForInitializer, trace);
}
@NotNull
@@ -973,21 +973,32 @@ public class DescriptorResolver {
}
}
else {
return typeResolver.resolveType(scope, propertyTypeRef, trace, true);
JetType type = typeResolver.resolveType(scope, propertyTypeRef, trace, true);
JetExpression initializer = variable.getInitializer();
if (initializer != null) {
setConstantForVariable(variableDescriptor, initializer, type, trace);
}
return type;
}
}
private static void setConstantForVariable(
private void setConstantForVariable(
@NotNull VariableDescriptorImpl variableDescriptor,
@NotNull JetExpression initializer,
@NotNull JetType initializerType,
@NotNull BindingTrace trace
@NotNull final JetExpression initializer,
@NotNull final JetType initializerType,
@NotNull final BindingTrace trace
) {
CompileTimeConstant<?> constant = ConstantExpressionEvaluator.object$.evaluate(initializer, trace, initializerType);
if (constant instanceof IntegerValueTypeConstant){
constant = EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) constant, initializerType);
}
variableDescriptor.setCompileTimeInitializer(constant);
variableDescriptor.setCompileTimeInitializer(storageManager.createRecursionTolerantNullableLazyValue(new Function0<CompileTimeConstant<?>>() {
@Nullable
@Override
public CompileTimeConstant<?> invoke() {
CompileTimeConstant<?> constant = ConstantExpressionEvaluator.object$.evaluate(initializer, trace, initializerType);
if ((constant instanceof IntegerValueTypeConstant)) {
return EvaluatePackage.createCompileTimeConstantWithType((IntegerValueTypeConstant) constant, initializerType);
}
return constant;
}
}, null));
}
@NotNull
@@ -1390,4 +1401,4 @@ public class DescriptorResolver {
}
}
}
}
}
@@ -130,8 +130,6 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
JetType outType = propertyDescriptor.getType();
JetTypeInfo typeInfo = facade.getTypeInfo(initializer, context.replaceExpectedType(outType));
dataFlowInfo = typeInfo.getDataFlowInfo();
EvaluatePackage.recordCompileTimeValueForInitializerIfNeeded(propertyDescriptor, initializer, outType, context.trace);
}
{
@@ -6,5 +6,5 @@ val prop1: Int = 0x7777777777
// val prop2: 513105426295.toLong()
val prop2: Long = 0x7777777777
// val prop3: IntegerValueType(513105426295)
// val prop3: 513105426295.toLong()
val prop3 = 0x7777777777
@@ -1,6 +1,6 @@
package test
// val p1: IntegerValueType(-1)
// val p1: -1.toInt()
val p1 = -1
// val p2: -1.toLong()
@@ -12,4 +12,4 @@ package testOther
import test.normal
val some: Int = 1
val fromImported: Int = normal
val fromImported: Int = normal
@@ -1,4 +1,4 @@
package test
internal val fromImported: kotlin.Int
internal val normal: kotlin.Int
internal val fromImported: kotlin.Int = 1
internal val normal: kotlin.Int = 1
@@ -5,7 +5,7 @@ class ConstructorTypeParamClassObjectTypeConflict<test> {
trait test
}
val some: test? = null
val some: test? = throw Exception()
}
class ConstructorTypeParamClassObjectConflict<test> {
@@ -2,7 +2,7 @@ package test
public object Obj {
/*primary*/ private constructor Obj()
public final val v: kotlin.String
public final val v: kotlin.String = "val"
public final fun <get-v>(): kotlin.String
public final fun f(): kotlin.String
@@ -5,7 +5,7 @@ public final class Outer {
public object Obj {
/*primary*/ private constructor Obj()
public final val v: kotlin.String
public final val v: kotlin.String = "val"
public final fun <get-v>(): kotlin.String
public final fun f(): kotlin.String
@@ -8,7 +8,7 @@ public final class Outer {
public object Obj {
/*primary*/ private constructor Obj()
public final val v: kotlin.String
public final val v: kotlin.String = "val"
public final fun <get-v>(): kotlin.String
public final fun f(): kotlin.String
@@ -9,7 +9,7 @@ public object Outer {
public object Obj {
/*primary*/ private constructor Obj()
public final val v: kotlin.String
public final val v: kotlin.String = "val"
public final fun <get-v>(): kotlin.String
public final fun f(): kotlin.String
@@ -5,7 +5,7 @@ internal val x: kotlin.Int = 5.toInt()
public object Obj {
/*primary*/ private constructor Obj()
public final val v: kotlin.String
public final val v: kotlin.String = "val"
public final fun <get-v>(): kotlin.String
public final fun f(): kotlin.String
@@ -5,12 +5,12 @@ internal final class Test {
internal class object <class-object-for-Test> {
/*primary*/ private constructor <class-object-for-Test>()
public final val prop1: kotlin.Int
public final val prop1: kotlin.Int = 10.toInt()
public final fun <get-prop1>(): kotlin.Int
public final var prop2: kotlin.Int
public final fun <get-prop2>(): kotlin.Int
protected final fun <set-prop2>(/*0*/ <set-?>: kotlin.Int): kotlin.Unit
public final val prop3: kotlin.Int
public final val prop3: kotlin.Int = 12.toInt()
public final fun <get-prop3>(): kotlin.Int
internal final var prop4: kotlin.Int
internal final fun <get-prop4>(): kotlin.Int
@@ -4,12 +4,12 @@ internal trait Test {
internal class object <class-object-for-Test> {
/*primary*/ private constructor <class-object-for-Test>()
public final val prop1: kotlin.Int
public final val prop1: kotlin.Int = 10.toInt()
public final fun <get-prop1>(): kotlin.Int
public final var prop2: kotlin.Int
public final fun <get-prop2>(): kotlin.Int
protected final fun <set-prop2>(/*0*/ <set-?>: kotlin.Int): kotlin.Unit
public final val prop3: kotlin.Int
public final val prop3: kotlin.Int = 12.toInt()
public final fun <get-prop3>(): kotlin.Int
internal final var prop4: kotlin.Int
internal final fun <get-prop4>(): kotlin.Int
@@ -8,8 +8,8 @@ internal final class ClassVal {
internal final fun <get-property2>(): kotlin.Int
private final val property3: java.lang.Object
private final fun <get-property3>(): java.lang.Object
protected final val property4: kotlin.String
protected final val property4: kotlin.String = ""
protected final fun <get-property4>(): kotlin.String
public final val property5: kotlin.Int
public final val property5: kotlin.Int = 1.toInt()
public final fun <get-property5>(): kotlin.Int
}
@@ -8,8 +8,8 @@ internal final class ClassVal {
internal final fun <get-property2>(): kotlin.Int
private final val property3: java.lang.Object
private final fun <get-property3>(): java.lang.Object
protected final val property4: kotlin.String
protected final val property4: kotlin.String = ""
protected final fun <get-property4>(): kotlin.String
public final val property5: kotlin.Int
public final val property5: kotlin.Int = 1.toInt()
public final fun <get-property5>(): kotlin.Int
}
@@ -14,7 +14,7 @@ internal final class B : test.A {
public open override /*1*/ var p: kotlin.Int
public open override /*1*/ fun <get-p>(): kotlin.Int
public open override /*1*/ fun <set-p>(/*0*/ <set-?>: kotlin.Int): kotlin.Unit
internal open override /*1*/ val v: kotlin.Int
internal open override /*1*/ val v: kotlin.Int = 0.toInt()
internal open override /*1*/ fun <get-v>(): kotlin.Int
internal open override /*1*/ fun f(): kotlin.Int
}
@@ -41,7 +41,7 @@ abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorReso
fun doConstantTest(path: String) {
doTest(path) {
property, context ->
val compileTimeConstant = context.get(BindingContext.COMPILE_TIME_VALUE, property.getInitializer())
val compileTimeConstant = property.getCompileTimeInitializer()
if (compileTimeConstant is StringValue) {
"\\\"${compileTimeConstant.getValue()}\\\""
} else {
@@ -54,7 +54,7 @@ abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorReso
fun doIsPureTest(path: String) {
doTest(path) {
property, context ->
val compileTimeConstant = context.get(BindingContext.COMPILE_TIME_VALUE, property.getInitializer())
val compileTimeConstant = property.getCompileTimeInitializer()
if (compileTimeConstant is IntegerValueConstant) {
compileTimeConstant.isPure().toString()
} else {
@@ -63,7 +63,7 @@ abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorReso
}
}
private fun doTest(path: String, getValueToTest: (JetProperty, BindingContext) -> String) {
private fun doTest(path: String, getValueToTest: (VariableDescriptor, BindingContext) -> String) {
val myFile = File(path)
val fileText = FileUtil.loadFile(myFile, true)
val packageView = getPackage(fileText)
@@ -80,9 +80,7 @@ abstract class AbstractEvaluateExpressionTest : AbstractAnnotationDescriptorReso
val property = AbstractAnnotationDescriptorResolveTest.getPropertyDescriptor(packageView, propertyName, false)
?: AbstractAnnotationDescriptorResolveTest.getLocalVarDescriptor(context!!, propertyName)
val jetProperty = BindingContextUtils.descriptorToDeclaration(context!!, property) as JetProperty
val testedObject = getValueToTest(jetProperty, context!!)
val testedObject = getValueToTest(property, context!!)
expectedActual.add(expectedPropertyPrefix + expected!! to expectedPropertyPrefix + testedObject)
}
@@ -56,16 +56,6 @@ public class RecursiveDescriptorComparator {
public static final Configuration RECURSIVE = new Configuration(false, false, true,
Predicates.<FqName>alwaysTrue(),
FORBID_ERROR_TYPES, DEFAULT_RENDERER);
public static final Configuration WITHOUT_COMPILE_TIME_CONSTANTS = new Configuration(false, false, true,
Predicates.<FqName>alwaysTrue(),
FORBID_ERROR_TYPES,
new DescriptorRendererBuilder()
.setWithDefinedIn(false)
.setExcludedAnnotationClasses(Arrays.asList(new FqName(ExpectedLoadErrorsUtil.ANNOTATION_CLASS_NAME)))
.setOverrideRenderingPolicy(DescriptorRenderer.OverrideRenderingPolicy.RENDER_OPEN_OVERRIDE)
.setVerbose(true)
.setIncludePropertyConstant(false)
.build());
public static final Configuration RECURSIVE_ALL = new Configuration(true, true, true,
Predicates.<FqName>alwaysTrue(),
@@ -267,7 +267,10 @@ public abstract class LazyJavaMemberScope(
propertyDescriptor.setType(effectiveSignature.getReturnType(), Collections.emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(getContainingDeclaration()), null : JetType?)
if (!propertyDescriptor.isVar()) {
propertyDescriptor.setCompileTimeInitializer(JavaPropertyInitializerEvaluator.getInstance().getInitializerConstant(field, propertyDescriptor))
propertyDescriptor.setCompileTimeInitializer(
c.storageManager.createNullableLazyValue {
JavaPropertyInitializerEvaluator.getInstance().getInitializerConstant(field, propertyDescriptor)
})
}
c.javaResolverCache.recordField(field, propertyDescriptor);
@@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.storage.NullableLazyValue;
import java.util.Collections;
import java.util.List;
@@ -30,7 +31,7 @@ import java.util.Set;
public abstract class VariableDescriptorImpl extends DeclarationDescriptorNonRootImpl implements VariableDescriptor {
private JetType outType;
private CompileTimeConstant<?> compileTimeInitializer;
private NullableLazyValue<CompileTimeConstant<?>> compileTimeInitializer;
public VariableDescriptorImpl(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -65,10 +66,13 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorNonRoo
@Nullable
@Override
public CompileTimeConstant<?> getCompileTimeInitializer() {
return compileTimeInitializer;
if (compileTimeInitializer != null) {
return compileTimeInitializer.invoke();
}
return null;
}
public void setCompileTimeInitializer(@Nullable CompileTimeConstant<?> compileTimeInitializer) {
public void setCompileTimeInitializer(@NotNull NullableLazyValue<CompileTimeConstant<?>> compileTimeInitializer) {
if (!isVar()) {
this.compileTimeInitializer = compileTimeInitializer;
}