Put $assertionDisabled field into inline-site's class

The generated code is more inline with java, and we avoid the error of
accessing package-private field outside of the package.
However, this changes semantics a bit. Now, a user should set assertion
status of inline-site's package, instead of inline function's one.
 #KT-28317: Fixed
This commit is contained in:
Ilmir Usmanov
2019-02-01 20:11:06 +03:00
parent acb83f1af1
commit 1e4b7e1ef1
25 changed files with 818 additions and 33 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -21,12 +21,14 @@ import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
val assertionsDisabledFieldName = "\$assertionsDisabled"
const val ASSERTIONS_DISABLED_FIELD_NAME = "\$assertionsDisabled"
private const val ALWAYS_ENABLED_ASSERT_FUNCTION_NAME = "alwaysEnabledAssert"
private const val LAMBDA_INTERNAL_NAME = "kotlin/jvm/functions/Function0"
private const val ASSERTION_ERROR_INTERNAL_NAME = "java/lang/AssertionError"
@@ -43,6 +45,9 @@ private fun FunctionDescriptor.isBuiltinAlwaysEnabledAssertWithoutLambda() =
fun FunctionDescriptor.isBuiltinAlwaysEnabledAssert() =
this.isBuiltinAlwaysEnabledAssertWithLambda() || this.isBuiltinAlwaysEnabledAssertWithoutLambda()
fun FieldInsnNode.isCheckAssertionsStatus() =
opcode == Opcodes.GETSTATIC && name == ASSERTIONS_DISABLED_FIELD_NAME && desc == Type.BOOLEAN_TYPE.descriptor
fun createMethodNodeForAlwaysEnabledAssert(
functionDescriptor: FunctionDescriptor,
typeMapper: KotlinTypeMapper
@@ -131,17 +136,16 @@ private fun inlineAlwaysInlineAssert(resolvedCall: ResolvedCall<*>, codegen: Exp
)
}
fun generateAssertionsDisabledFieldInitialization(parentCodegen: MemberCodegen<*>) {
parentCodegen.v.newField(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_STATIC or Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC, assertionsDisabledFieldName,
fun generateAssertionsDisabledFieldInitialization(classBuilder: ClassBuilder, clInitBuilder: MethodVisitor) {
classBuilder.newField(
JvmDeclarationOrigin.NO_ORIGIN, Opcodes.ACC_STATIC or Opcodes.ACC_FINAL or Opcodes.ACC_SYNTHETIC, ASSERTIONS_DISABLED_FIELD_NAME,
"Z", null, null
)
val clInitCodegen = parentCodegen.createOrGetClInitCodegen()
MemberCodegen.markLineNumberForElement(parentCodegen.element.psiOrParent, clInitCodegen.v)
val thenLabel = Label()
val elseLabel = Label()
with(clInitCodegen.v) {
aconst(Type.getObjectType(parentCodegen.v.thisName))
with(InstructionAdapter(clInitBuilder)) {
mark(Label())
aconst(Type.getObjectType(classBuilder.thisName))
invokevirtual("java/lang/Class", "desiredAssertionStatus", "()Z", false)
ifne(thenLabel)
iconst(1)
@@ -151,7 +155,7 @@ fun generateAssertionsDisabledFieldInitialization(parentCodegen: MemberCodegen<*
iconst(0)
mark(elseLabel)
putstatic(parentCodegen.v.thisName, assertionsDisabledFieldName, "Z")
putstatic(classBuilder.thisName, ASSERTIONS_DISABLED_FIELD_NAME, "Z")
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -922,7 +922,7 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
public void generateAssertField() {
if (jvmAssertFieldGenerated) return;
AssertCodegenUtilKt.generateAssertionsDisabledFieldInitialization(this);
AssertCodegenUtilKt.generateAssertionsDisabledFieldInitialization(v, createOrGetClInitCodegen().v);
jvmAssertFieldGenerated = true;
}
@@ -1,18 +1,15 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.inline
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.coroutines.isCoroutineSuperClass
import org.jetbrains.kotlin.codegen.inline.coroutines.CoroutineTransformer
import org.jetbrains.kotlin.codegen.serialization.JvmCodegenStringTable
import org.jetbrains.kotlin.codegen.writeKotlinMetadata
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
@@ -179,6 +176,13 @@ class AnonymousObjectTransformer(
writeOuterInfo(visitor)
if (inliningContext.generateAssertField && fieldNames.none { it.key == ASSERTIONS_DISABLED_FIELD_NAME }) {
val clInitBuilder = classBuilder.newMethod(NO_ORIGIN, Opcodes.ACC_STATIC, "<clinit>", "()V", null, null)
generateAssertionsDisabledFieldInitialization(classBuilder, clInitBuilder)
clInitBuilder.visitInsn(Opcodes.RETURN)
clInitBuilder.visitEnd()
}
if (continuationClassName == transformationInfo.oldClassName) {
coroutineTransformer.registerClassBuilder(continuationClassName)
} else {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -299,9 +299,13 @@ abstract class InlineCodegen<out T : BaseExpressionCodegen>(
defaultSourceMapper.callSiteMarker = null
generateAssertFieldIfNeeded(info)
return result
}
protected abstract fun generateAssertFieldIfNeeded(info: RootInliningContext)
private fun isInlinedToInlineFunInKotlinRuntime(): Boolean {
val codegen = this.codegen as? ExpressionCodegen ?: return false
val caller = codegen.context.functionDescriptor
@@ -661,6 +665,12 @@ class PsiInlineCodegen(
sourceCompiler: SourceCompilerForInline
) : InlineCodegen<ExpressionCodegen>(codegen, state, function, typeParameterMappings, sourceCompiler), CallGenerator {
override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
if (info.generateAssertField) {
codegen.parentCodegen.generateAssertField()
}
}
override fun genCallInner(
callableMethod: Callable,
resolvedCall: ResolvedCall<*>?,
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -46,6 +46,8 @@ open class InliningContext(
val isInliningLambda = lambdaInfo != null
var generateAssertField = false
private val internalNameToAnonymousObjectTransformationInfo = hashMapOf<String, AnonymousObjectTransformationInfo>()
var isContinuation: Boolean = false
@@ -1,14 +1,11 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.inline
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.ClosureCodegen
import org.jetbrains.kotlin.codegen.IrExpressionLambda
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.coroutines.continuationAsmType
import org.jetbrains.kotlin.codegen.coroutines.getOrCreateJvmSuspendFunctionView
import org.jetbrains.kotlin.codegen.inline.FieldRemapper.Companion.foldName
@@ -578,6 +575,23 @@ class MethodInliner(
className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode
)
)
} else if (fieldInsnNode.isCheckAssertionsStatus()) {
fieldInsnNode.owner = inlineCallSiteInfo.ownerClassName
if (inliningContext.isInliningLambda) {
if (inliningContext.lambdaInfo!!.isCrossInline) {
assert(inliningContext.parent?.parent is RegeneratedClassContext) {
"$inliningContext grandparent shall be RegeneratedClassContext but got ${inliningContext.parent?.parent}"
}
inliningContext.parent!!.parent!!.generateAssertField = true
} else {
assert(inliningContext.parent != null) {
"$inliningContext parent shall not be null"
}
inliningContext.parent!!.generateAssertField = true
}
} else {
inliningContext.generateAssertField = true
}
}
}
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.codegen.inline
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.BaseExpressionCodegen
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.SamWrapperCodegen.SAM_WRAPPER_SUFFIX
import org.jetbrains.kotlin.codegen.`when`.WhenByEnumsMapping
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
@@ -258,6 +255,7 @@ private fun String.isInteger(radix: Int = 10) = toIntOrNull(radix) != null
internal fun isCapturedFieldName(fieldName: String): Boolean {
// TODO: improve this heuristic
return fieldName.startsWith(CAPTURED_FIELD_PREFIX) && !fieldName.startsWith(NON_CAPTURED_FIELD_PREFIX)
&& fieldName != ASSERTIONS_DISABLED_FIELD_NAME
|| AsmUtil.CAPTURED_THIS_FIELD == fieldName
|| AsmUtil.CAPTURED_RECEIVER_FIELD == fieldName
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -27,6 +27,9 @@ class IrInlineCodegen(
typeParameterMappings: TypeParameterMappings,
sourceCompiler: SourceCompilerForInline
) : InlineCodegen<ExpressionCodegen>(codegen, state, function, typeParameterMappings, sourceCompiler), IrCallGenerator {
override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
// TODO: JVM assertions are not implemented yet in IR backend
}
override fun putClosureParametersOnStack(next: LambdaInfo, functionReferenceReceiver: StackValue?) {
val lambdaInfo = next as IrExpressionLambdaImpl
@@ -5,6 +5,8 @@
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
package test
inline fun inlineMe() {
assert(false) { "FROM INLINED" }
}
@@ -12,6 +14,8 @@ inline fun inlineMe() {
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
class CheckerJvmAssertInlineFunctionAssertionsDisabled {
fun check() {
inlineMe()
@@ -3,6 +3,8 @@
// WITH_RUNTIME
// FULL_JDK
package test
inline fun inlineMe() {
assert(false) { "FROM INLINED" }
}
@@ -10,6 +12,8 @@ inline fun inlineMe() {
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
class CheckerJvmAssertInlineFunctionAssertionsEnabled {
fun check() {
inlineMe()
@@ -5,6 +5,8 @@
// WITH_RUNTIME
// NO_CHECK_LAMBDA_INLINING
package test
inline fun call(c: () -> Unit) {
c()
}
@@ -12,6 +14,8 @@ inline fun call(c: () -> Unit) {
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
interface Checker {
fun checkTrue(): Boolean
fun checkFalse(): Boolean
@@ -0,0 +1,46 @@
// TARGET_BACKEND: JVM
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// WITH_RUNTIME
// FULL_JDK
package test
var result = "OK"
class State {
companion object {
inline fun inlineMe() {
assert(false) { "FROM INLINED" }
}
}
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
class CheckerJvmAssertInlineFunctionAssertionsEnabled {
fun check() {
State.inlineMe()
throw RuntimeException("FAIL 0")
}
}
class Dummy
fun enableAssertions(): CheckerJvmAssertInlineFunctionAssertionsEnabled {
val loader = Dummy::class.java.classLoader
loader.setDefaultAssertionStatus(true)
val c = loader.loadClass("CheckerJvmAssertInlineFunctionAssertionsEnabled")
return c.newInstance() as CheckerJvmAssertInlineFunctionAssertionsEnabled
}
fun box(): String {
var c = enableAssertions()
try {
c.check()
return "FAIL 2"
} catch (ignore: AssertionError) {}
return result
}
@@ -5,6 +5,8 @@
// WITH_RUNTIME
// NO_CHECK_LAMBDA_INLINING
package test
object CrossinlineLambdaContainer {
inline fun call(crossinline c: () -> Unit) {
val l = { c() }
@@ -15,7 +17,7 @@ object CrossinlineLambdaContainer {
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import CrossinlineLambdaContainer.call
import test.CrossinlineLambdaContainer.call
interface Checker {
fun checkTrue(): Boolean
@@ -102,9 +104,7 @@ class ShouldBeEnabled : Checker {
fun setDesiredAssertionStatus(v: Boolean): Checker {
val loader = Checker::class.java.classLoader
loader.setClassAssertionStatus("ShouldBeEnabled", true)
loader.setClassAssertionStatus("ShouldBeDisabled", false)
loader.setClassAssertionStatus("CrossinlineLambdaContainer", v)
loader.setDefaultAssertionStatus(v)
val c = loader.loadClass(if (v) "ShouldBeEnabled" else "ShouldBeDisabled")
return c.newInstance() as Checker
}
@@ -0,0 +1,237 @@
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// WITH_RUNTIME
// NO_CHECK_LAMBDA_INLINING
package test
object CrossinlineLambdaContainer {
inline fun call(b: Boolean, crossinline c: () -> Unit) {
val l = {
assert(b) { "FROM INLINED" }
c()
}
l()
}
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.CrossinlineLambdaContainer.call
interface Checker {
fun checkTrueTrue(): Boolean
fun checkTrueFalse(): Boolean
fun checkFalseTrue(): Boolean
fun checkFalseFalse(): Boolean
fun checkTrueWithMessageTrue(): Boolean
fun checkTrueWithMessageFalse(): Boolean
fun checkFalseWithMessageTrue(): Boolean
fun checkFalseWithMessageFalse(): Boolean
}
class ShouldBeDisabled : Checker {
override fun checkTrueTrue(): Boolean {
var hit = false
val l = { hit = true; true }
call(true) {
assert(l())
}
return hit
}
override fun checkTrueFalse(): Boolean {
var hit = false
val l = { hit = true; true }
call(false) {
assert(l())
}
return hit
}
override fun checkFalseTrue(): Boolean {
var hit = false
val l = { hit = true; false }
call(true) {
assert(l())
}
return hit
}
override fun checkFalseFalse(): Boolean {
var hit = false
val l = { hit = true; false }
call(false) {
assert(l())
}
return hit
}
override fun checkTrueWithMessageTrue(): Boolean {
var hit = false
val l = { hit = true; true }
call(true) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkTrueWithMessageFalse(): Boolean {
var hit = false
val l = { hit = true; true }
call(false) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkFalseWithMessageTrue(): Boolean {
var hit = false
val l = { hit = true; false }
call(true) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkFalseWithMessageFalse(): Boolean {
var hit = false
val l = { hit = true; false }
call(false) {
assert(l()) { "BOOYA" }
}
return hit
}
}
class ShouldBeEnabled : Checker {
override fun checkTrueTrue(): Boolean {
var hit = false
val l = { hit = true; true }
call(true) {
assert(l())
}
return hit
}
override fun checkTrueFalse(): Boolean {
var hit = false
val l = { hit = true; true }
call(false) {
assert(l())
}
return hit
}
override fun checkFalseTrue(): Boolean {
var hit = false
val l = { hit = true; false }
call(true) {
assert(l())
}
return hit
}
override fun checkFalseFalse(): Boolean {
var hit = false
val l = { hit = true; false }
call(false) {
assert(l())
}
return hit
}
override fun checkTrueWithMessageTrue(): Boolean {
var hit = false
val l = { hit = true; true }
call(true) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkTrueWithMessageFalse(): Boolean {
var hit = false
val l = { hit = true; true }
call(false) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkFalseWithMessageTrue(): Boolean {
var hit = false
val l = { hit = true; false }
call(true) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkFalseWithMessageFalse(): Boolean {
var hit = false
val l = { hit = true; false }
call(false) {
assert(l()) { "BOOYA" }
}
return hit
}
}
fun setDesiredAssertionStatus(v: Boolean): Checker {
val loader = Checker::class.java.classLoader
loader.setDefaultAssertionStatus(v)
val c = loader.loadClass(if (v) "ShouldBeEnabled" else "ShouldBeDisabled")
return c.newInstance() as Checker
}
fun box(): String {
var c = setDesiredAssertionStatus(false)
if (c.checkTrueTrue()) return "FAIL 00"
if (c.checkTrueFalse()) return "FAIL 01"
if (c.checkTrueWithMessageTrue()) return "FAIL 10"
if (c.checkTrueWithMessageFalse()) return "FAIL 11"
if (c.checkFalseTrue()) return "FAIL 20"
if (c.checkFalseFalse()) return "FAIL 21"
if (c.checkFalseWithMessageTrue()) return "FAIL 30"
if (c.checkFalseWithMessageFalse()) return "FAIL 31"
c = setDesiredAssertionStatus(true)
if (!c.checkTrueTrue()) return "FAIL 40"
try {
c.checkTrueFalse()
return "FAIL 41"
} catch (ignore: AssertionError) {
}
if (!c.checkTrueWithMessageTrue()) return "FAIL 50"
try {
c.checkTrueWithMessageFalse()
return "FAIL 51"
} catch (ignore: AssertionError) {
}
try {
c.checkFalseTrue()
return "FAIL 60"
} catch (ignore: AssertionError) {
}
try {
c.checkFalseFalse()
return "FAIL 61"
} catch (ignore: AssertionError) {
}
try {
c.checkFalseWithMessageTrue()
return "FAIL 70"
} catch (ignore: AssertionError) {
}
try {
c.checkFalseWithMessageFalse()
return "FAIL 71"
} catch (ignore: AssertionError) {
}
return "OK"
}
@@ -0,0 +1,214 @@
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// WITH_RUNTIME
// NO_CHECK_LAMBDA_INLINING
package test
object CrossinlineLambdaContainer {
inline fun call(b: Boolean, crossinline c: () -> Unit) {
val l = {
assert(b) { "FROM INLINED" }
c()
}
l()
}
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.CrossinlineLambdaContainer.call
interface Checker {
fun checkTrueTrue(): Boolean
fun checkTrueFalse(): Boolean
fun checkFalseTrue(): Boolean
fun checkFalseFalse(): Boolean
fun checkTrueWithMessageTrue(): Boolean
fun checkTrueWithMessageFalse(): Boolean
fun checkFalseWithMessageTrue(): Boolean
fun checkFalseWithMessageFalse(): Boolean
}
class ShouldBeDisabled : Checker {
override fun checkTrueTrue(): Boolean {
var hit = false
val l = { hit = true; true }
call(true) {
assert(l())
}
return hit
}
override fun checkTrueFalse(): Boolean {
var hit = false
val l = { hit = true; true }
call(false) {
assert(l())
}
return hit
}
override fun checkFalseTrue(): Boolean {
var hit = false
val l = { hit = true; false }
call(true) {
assert(l())
}
return hit
}
override fun checkFalseFalse(): Boolean {
var hit = false
val l = { hit = true; false }
call(false) {
assert(l())
}
return hit
}
override fun checkTrueWithMessageTrue(): Boolean {
var hit = false
val l = { hit = true; true }
call(true) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkTrueWithMessageFalse(): Boolean {
var hit = false
val l = { hit = true; true }
call(false) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkFalseWithMessageTrue(): Boolean {
var hit = false
val l = { hit = true; false }
call(true) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkFalseWithMessageFalse(): Boolean {
var hit = false
val l = { hit = true; false }
call(false) {
assert(l()) { "BOOYA" }
}
return hit
}
}
class ShouldBeEnabled : Checker {
override fun checkTrueTrue(): Boolean {
var hit = false
val l = { hit = true; true }
call(true) {
assert(l())
}
return hit
}
override fun checkTrueFalse(): Boolean {
var hit = false
val l = { hit = true; true }
call(false) {
assert(l())
}
return hit
}
override fun checkFalseTrue(): Boolean {
var hit = false
val l = { hit = true; false }
call(true) {
assert(l())
}
return hit
}
override fun checkFalseFalse(): Boolean {
var hit = false
val l = { hit = true; false }
call(false) {
assert(l())
}
return hit
}
override fun checkTrueWithMessageTrue(): Boolean {
var hit = false
val l = { hit = true; true }
call(true) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkTrueWithMessageFalse(): Boolean {
var hit = false
val l = { hit = true; true }
call(false) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkFalseWithMessageTrue(): Boolean {
var hit = false
val l = { hit = true; false }
call(true) {
assert(l()) { "BOOYA" }
}
return hit
}
override fun checkFalseWithMessageFalse(): Boolean {
var hit = false
val l = { hit = true; false }
call(false) {
assert(l()) { "BOOYA" }
}
return hit
}
}
fun setDesiredAssertionStatus(v: Boolean): Checker {
val loader = Checker::class.java.classLoader
loader.setDefaultAssertionStatus(false)
loader.setPackageAssertionStatus("test", v)
val c = loader.loadClass(if (v) "ShouldBeEnabled" else "ShouldBeDisabled")
return c.newInstance() as Checker
}
fun box(): String {
var c = setDesiredAssertionStatus(false)
if (c.checkTrueTrue()) return "FAIL 00"
if (c.checkTrueFalse()) return "FAIL 01"
if (c.checkTrueWithMessageTrue()) return "FAIL 10"
if (c.checkTrueWithMessageFalse()) return "FAIL 11"
if (c.checkFalseTrue()) return "FAIL 20"
if (c.checkFalseFalse()) return "FAIL 21"
if (c.checkFalseWithMessageTrue()) return "FAIL 30"
if (c.checkFalseWithMessageFalse()) return "FAIL 31"
c = setDesiredAssertionStatus(true)
if (c.checkTrueTrue()) return "FAIL 100"
if (c.checkTrueFalse()) return "FAIL 101"
if (c.checkTrueWithMessageTrue()) return "FAIL 110"
if (c.checkTrueWithMessageFalse()) return "FAIL 111"
if (c.checkFalseTrue()) return "FAIL 120"
if (c.checkFalseFalse()) return "FAIL 121"
if (c.checkFalseWithMessageTrue()) return "FAIL 130"
if (c.checkFalseWithMessageFalse()) return "FAIL 131"
return "OK"
}
@@ -0,0 +1,48 @@
// TARGET_BACKEND: JVM
// FILE: inline.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
// WITH_RUNTIME
// FULL_JDK
package test
class A {
inline fun a() {
assert(false) { "from inlined" }
}
}
class B {
inline fun b() {
A().a()
error("FAIL 0")
}
}
// FILE: inlineSite.kt
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
import test.*
class Checker {
fun check() {
B().b()
error("FAIL 1")
}
}
class Dummy
fun enableAssertions(): Checker {
val loader = Dummy::class.java.classLoader
loader.setDefaultAssertionStatus(true)
val c = loader.loadClass("Checker")
return c.newInstance() as Checker
}
fun box(): String {
var c = enableAssertions()
try {
c.check()
return "FAIL 2"
} catch (ignore: AssertionError) {}
return "OK"
}
@@ -0,0 +1,14 @@
// IGNORE_BACKEND: JVM_IR
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
inline fun inlineMe(crossinline c : () -> Unit) = { c() }
class A {
fun inlineSite() {
inlineMe {
assert(true)
}
}
}
// 1 GETSTATIC A\$inlineSite\$\$inlined\$inlineMe\$1.\$assertionsDisabled
@@ -0,0 +1,21 @@
// IGNORE_BACKEND: JVM_IR
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
inline fun inlineMe(crossinline c : () -> Unit) = {
assert(true)
c()
}
class A {
fun inlineSite() {
inlineMe { }
}
}
// inlineSite:
// 1 GETSTATIC A\$inlineSite\$\$inlined\$inlineMe\$1.\$assertionsDisabled
// A.<clinit>:
// 1 LDC LA\$inlineSite\$\$inlined\$inlineMe\$1;.class\s*INVOKEVIRTUAL java/lang/Class.desiredAssertionStatus \(\)Z
// 1 PUTSTATIC A\$inlineSite\$\$inlined\$inlineMe\$1.\$assertionsDisabled : Z
// in declaration site and in inline site
// 2 INVOKEVIRTUAL java/lang/Class.desiredAssertionStatus \(\)Z
@@ -0,0 +1,18 @@
// IGNORE_BACKEND: JVM_IR
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
inline fun inlineMe() = assert(true)
class A {
fun inlineSite() {
inlineMe()
}
}
// A.inlineSite:
// 1 GETSTATIC A.\$assertionsDisabled
// A.<clinit>:
// 1 LDC LA;.class\s*INVOKEVIRTUAL java/lang/Class.desiredAssertionStatus \(\)Z
// 1 PUTSTATIC A.\$assertionsDisabled : Z
// in declaration site and in inline site
// 2 INVOKEVIRTUAL java/lang/Class.desiredAssertionStatus \(\)Z
@@ -0,0 +1,14 @@
// IGNORE_BACKEND: JVM_IR
// KOTLIN_CONFIGURATION_FLAGS: ASSERTIONS_MODE=jvm
inline fun inlineMe(c: () -> Unit) = c()
class A {
fun inlineSite() {
inlineMe {
assert(true)
}
}
}
// 1 GETSTATIC A.\$assertionsDisabled
@@ -640,10 +640,30 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
runTest("compiler/testData/codegen/boxInline/assert/jvmAssertInlineLambda.kt");
}
@TestMetadata("jvmCompanion.kt")
public void testJvmCompanion() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCompanion.kt");
}
@TestMetadata("jvmCrossinlineLambda.kt")
public void testJvmCrossinlineLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambda.kt");
}
@TestMetadata("jvmCrossinlineLambda2.kt")
public void testJvmCrossinlineLambda2() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambda2.kt");
}
@TestMetadata("jvmCrossinlineLambdaDeclarationSite.kt")
public void testJvmCrossinlineLambdaDeclarationSite() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambdaDeclarationSite.kt");
}
@TestMetadata("jvmDoubleInline.kt")
public void testJvmDoubleInline() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/builders")
@@ -402,6 +402,39 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/assert")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Assert extends AbstractBytecodeTextTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInAssert() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/assert"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("jvmCrossinline.kt")
public void testJvmCrossinline() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/assert/jvmCrossinline.kt");
}
@TestMetadata("jvmCrossinlineAssertInLambda.kt")
public void testJvmCrossinlineAssertInLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/assert/jvmCrossinlineAssertInLambda.kt");
}
@TestMetadata("jvmInline.kt")
public void testJvmInline() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/assert/jvmInline.kt");
}
@TestMetadata("jvmInlineLambda.kt")
public void testJvmInlineLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/assert/jvmInlineLambda.kt");
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/boxing")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -640,10 +640,30 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
runTest("compiler/testData/codegen/boxInline/assert/jvmAssertInlineLambda.kt");
}
@TestMetadata("jvmCompanion.kt")
public void testJvmCompanion() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCompanion.kt");
}
@TestMetadata("jvmCrossinlineLambda.kt")
public void testJvmCrossinlineLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambda.kt");
}
@TestMetadata("jvmCrossinlineLambda2.kt")
public void testJvmCrossinlineLambda2() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambda2.kt");
}
@TestMetadata("jvmCrossinlineLambdaDeclarationSite.kt")
public void testJvmCrossinlineLambdaDeclarationSite() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambdaDeclarationSite.kt");
}
@TestMetadata("jvmDoubleInline.kt")
public void testJvmDoubleInline() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/builders")
@@ -640,10 +640,30 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
runTest("compiler/testData/codegen/boxInline/assert/jvmAssertInlineLambda.kt");
}
@TestMetadata("jvmCompanion.kt")
public void testJvmCompanion() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCompanion.kt");
}
@TestMetadata("jvmCrossinlineLambda.kt")
public void testJvmCrossinlineLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambda.kt");
}
@TestMetadata("jvmCrossinlineLambda2.kt")
public void testJvmCrossinlineLambda2() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambda2.kt");
}
@TestMetadata("jvmCrossinlineLambdaDeclarationSite.kt")
public void testJvmCrossinlineLambdaDeclarationSite() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmCrossinlineLambdaDeclarationSite.kt");
}
@TestMetadata("jvmDoubleInline.kt")
public void testJvmDoubleInline() throws Exception {
runTest("compiler/testData/codegen/boxInline/assert/jvmDoubleInline.kt");
}
}
@TestMetadata("compiler/testData/codegen/boxInline/builders")
@@ -402,6 +402,39 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/assert")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Assert extends AbstractIrBytecodeTextTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
public void testAllFilesPresentInAssert() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/assert"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@TestMetadata("jvmCrossinline.kt")
public void testJvmCrossinline() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/assert/jvmCrossinline.kt");
}
@TestMetadata("jvmCrossinlineAssertInLambda.kt")
public void testJvmCrossinlineAssertInLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/assert/jvmCrossinlineAssertInLambda.kt");
}
@TestMetadata("jvmInline.kt")
public void testJvmInline() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/assert/jvmInline.kt");
}
@TestMetadata("jvmInlineLambda.kt")
public void testJvmInlineLambda() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/assert/jvmInlineLambda.kt");
}
}
@TestMetadata("compiler/testData/codegen/bytecodeText/boxing")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)