From fcbc95bbb48098c8a2576abee69f6217bc968586 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 2 Oct 2012 22:09:02 +0400 Subject: [PATCH] Generate not-null assertions after getting a field --- .../backend/src/org/jetbrains/jet/codegen/AsmUtil.java | 8 ++++++++ .../src/org/jetbrains/jet/codegen/StackValue.java | 1 + compiler/testData/codegen/notNullAssertions/A.java | 7 +++++++ .../codegen/notNullAssertions/AssertionChecker.kt | 6 ++++++ runtime/src/jet/runtime/Intrinsics.java | 10 +++++++++- 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java index 434604b0436..dbcc8385065 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AsmUtil.java @@ -420,6 +420,14 @@ public class AsmUtil { genMethodThrow(mv, STUB_EXCEPTION, STUB_EXCEPTION_MESSAGE); } + public static void genNotNullAssertionForField( + @NotNull InstructionAdapter v, + @NotNull GenerationState state, + @NotNull PropertyDescriptor descriptor + ) { + genNotNullAssertion(v, state, descriptor, "checkFieldIsNotNull"); + } + public static void genNotNullAssertionForMethod( @NotNull InstructionAdapter v, @NotNull GenerationState state, diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java index 96866387fcc..bf715df48e8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/StackValue.java @@ -982,6 +982,7 @@ public abstract class StackValue { if (getter == null) { v.visitFieldInsn(isStatic ? GETSTATIC : GETFIELD, methodOwner.getInternalName(), descriptor.getName().getName(), this.type.getDescriptor()); + genNotNullAssertionForField(v, state, descriptor); } else { v.visitMethodInsn(invokeOpcode, methodOwner.getInternalName(), getter.getName(), getter.getDescriptor()); diff --git a/compiler/testData/codegen/notNullAssertions/A.java b/compiler/testData/codegen/notNullAssertions/A.java index 4d21176cfac..8e9bd8ae717 100644 --- a/compiler/testData/codegen/notNullAssertions/A.java +++ b/compiler/testData/codegen/notNullAssertions/A.java @@ -1,6 +1,13 @@ import jet.runtime.typeinfo.KotlinSignature; +import org.jetbrains.annotations.NotNull; public class A { + @NotNull + public final String NULL = null; + + @NotNull + public static final String STATIC_NULL = null; + @KotlinSignature("fun foo() : String") public String foo() { return null; diff --git a/compiler/testData/codegen/notNullAssertions/AssertionChecker.kt b/compiler/testData/codegen/notNullAssertions/AssertionChecker.kt index 2cb57cc50f3..0df80e8bc42 100644 --- a/compiler/testData/codegen/notNullAssertions/AssertionChecker.kt +++ b/compiler/testData/codegen/notNullAssertions/AssertionChecker.kt @@ -49,4 +49,10 @@ fun checkAssertions(val illegalStateExpected: Boolean) { // prefix expression check("inc") { var a = A(); ++a } + + // field + check("NULL") { val a = A().NULL } + + // static field + check("STATIC_NULL") { val a = A.STATIC_NULL } } diff --git a/runtime/src/jet/runtime/Intrinsics.java b/runtime/src/jet/runtime/Intrinsics.java index 8db661d85ef..9478d053d0e 100644 --- a/runtime/src/jet/runtime/Intrinsics.java +++ b/runtime/src/jet/runtime/Intrinsics.java @@ -43,6 +43,14 @@ public class Intrinsics { } } + public static void checkFieldIsNotNull(Object value, String className, String fieldName) { + if (value == null) { + IllegalStateException exception = + new IllegalStateException("Field specified as non-null contains null: " + className + "." + fieldName); + throw sanitizeStackTrace(exception); + } + } + public static Class getJavaClass(T self) { return (Class) self.getClass(); } @@ -66,7 +74,7 @@ public class Intrinsics { } private static final Set METHOD_NAMES_TO_SKIP = new HashSet(Arrays.asList( - "throwNpe", "checkReturnedValueIsNotNull" + "throwNpe", "checkReturnedValueIsNotNull", "checkFieldIsNotNull" )); private static T sanitizeStackTrace(T throwable) {