blob: a0049f44bb2a80593d3c7f0be09df931810af7a8 [file] [log] [blame]
// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.rewrite.assertions;
import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.AssertionsConfiguration;
import com.android.tools.r8.D8TestBuilder;
import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@RunWith(Parameterized.class)
public class AssertionConfigurationKotlinTest extends KotlinTestBase implements Opcodes {
private static class KotlinCompilationKey {
KotlinTargetVersion targetVersion;
boolean useJvmAssertions;
private KotlinCompilationKey(KotlinTargetVersion targetVersion, boolean useJvmAssertions) {
this.targetVersion = targetVersion;
this.useJvmAssertions = useJvmAssertions;
}
@Override
public int hashCode() {
return Objects.hash(targetVersion, useJvmAssertions);
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (getClass() != other.getClass()) {
return false;
}
KotlinCompilationKey kotlinCompilationKey = (KotlinCompilationKey) other;
return targetVersion == kotlinCompilationKey.targetVersion
&& useJvmAssertions == kotlinCompilationKey.useJvmAssertions;
}
}
private static final Package pkg = AssertionConfigurationKotlinTest.class.getPackage();
private static final String kotlintestclasesPackage = pkg.getName() + ".kotlintestclasses";
private static final String testClassKt = kotlintestclasesPackage + ".TestClassKt";
private static final String class1 = kotlintestclasesPackage + ".Class1";
private static final String class2 = kotlintestclasesPackage + ".Class2";
private static final Map<KotlinCompilationKey, Path> kotlinClasses = new HashMap<>();
private final TestParameters parameters;
private final boolean kotlinStdlibAsLibrary;
private final boolean useJvmAssertions;
private final KotlinCompilationKey kotlinCompilationKey;
@Parameterized.Parameters(name = "{0}, {1}, kotlin-stdlib as library: {2}, -Xassertions=jvm: {3}")
public static Collection<Object[]> data() {
return buildParameters(
getTestParameters().withAllRuntimesAndApiLevels().build(),
KotlinTargetVersion.values(),
BooleanUtils.values(),
BooleanUtils.values());
}
public AssertionConfigurationKotlinTest(
TestParameters parameters,
KotlinTargetVersion targetVersion,
boolean kotlinStdlibAsClasspath,
boolean useJvmAssertions) {
super(targetVersion);
this.parameters = parameters;
this.kotlinStdlibAsLibrary = kotlinStdlibAsClasspath;
this.useJvmAssertions = useJvmAssertions;
this.kotlinCompilationKey = new KotlinCompilationKey(targetVersion, useJvmAssertions);
}
@BeforeClass
public static void compileKotlin() throws Exception {
for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
for (boolean useJvmAssertions : BooleanUtils.values()) {
Path ktClasses =
kotlinc(KOTLINC, targetVersion)
.addSourceFiles(getKotlinFilesInTestPackage(pkg))
.setUseJvmAssertions(useJvmAssertions)
.compile();
kotlinClasses.put(new KotlinCompilationKey(targetVersion, useJvmAssertions), ktClasses);
}
}
}
private Path kotlinStdlibLibraryForRuntime() throws Exception {
Path kotlinStdlibCf = ToolHelper.getKotlinStdlibJar();
if (parameters.getRuntime().isCf()) {
return kotlinStdlibCf;
}
Path kotlinStdlibDex = temp.newFolder().toPath().resolve("kotlin-stdlib-dex.jar");
testForD8()
.addProgramFiles(kotlinStdlibCf)
.setMinApi(parameters.getApiLevel())
.compile()
.writeToZip(kotlinStdlibDex);
return kotlinStdlibDex;
}
private void runD8Test(
ThrowableConsumer<D8TestBuilder> builderConsumer,
ThrowingConsumer<CodeInspector, RuntimeException> inspector,
List<String> outputLines)
throws Exception {
if (kotlinStdlibAsLibrary) {
testForD8()
.addClasspathFiles(ToolHelper.getKotlinStdlibJar())
.addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
.setMinApi(parameters.getApiLevel())
.apply(builderConsumer)
.addRunClasspathFiles(kotlinStdlibLibraryForRuntime())
.run(
parameters.getRuntime(),
getClass().getPackage().getName() + ".kotlintestclasses.TestClassKt")
.inspect(inspector)
.assertSuccessWithOutputLines(outputLines);
} else {
testForD8()
.addProgramFiles(ToolHelper.getKotlinStdlibJar())
.addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
.setMinApi(parameters.getApiLevel())
.apply(builderConsumer)
.run(
parameters.getRuntime(),
getClass().getPackage().getName() + ".kotlintestclasses.TestClassKt")
.inspect(inspector)
.assertSuccessWithOutputLines(outputLines);
}
}
public void runR8Test(
ThrowableConsumer<R8FullTestBuilder> builderConsumer,
ThrowingConsumer<CodeInspector, RuntimeException> inspector,
List<String> outputLines)
throws Exception {
runR8Test(builderConsumer, inspector, outputLines, false);
}
public void runR8Test(
ThrowableConsumer<R8FullTestBuilder> builderConsumer,
ThrowingConsumer<CodeInspector, RuntimeException> inspector,
List<String> outputLines,
boolean enableJvmAssertions)
throws Exception {
testForR8(parameters.getBackend())
.applyIf(
kotlinStdlibAsLibrary,
b -> {
b.addClasspathFiles(ToolHelper.getKotlinStdlibJar());
b.addRunClasspathFiles(kotlinStdlibLibraryForRuntime());
},
b -> b.addProgramFiles(ToolHelper.getKotlinStdlibJar()))
.addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
.addKeepMainRule(testClassKt)
.addKeepClassAndMembersRules(class1, class2)
.setMinApi(parameters.getApiLevel())
.apply(builderConsumer)
.allowDiagnosticWarningMessages(!kotlinStdlibAsLibrary)
.addRunClasspathFiles(kotlinStdlibLibraryForRuntime())
.compile()
.assertAllWarningMessagesMatch(equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
.enableRuntimeAssertions(enableJvmAssertions)
.run(parameters.getRuntime(), testClassKt)
.inspect(inspector)
.assertSuccessWithOutputLines(outputLines);
}
private List<String> allAssertionsExpectedLines() {
return ImmutableList.of("AssertionError in Class1", "AssertionError in Class2", "DONE");
}
private List<String> noAllAssertionsExpectedLines() {
return ImmutableList.of("DONE");
}
private void checkAssertionCodeRemoved(ClassSubject subject, boolean isR8) {
assertThat(subject, isPresent());
if (subject.getOriginalName().equals("kotlin._Assertions")) {
assert !kotlinStdlibAsLibrary;
// With R8 the static-put of the kotlin._Assertions.INSTANCE field is removed as well,
// as is not used.
assertEquals(
(isR8 ? 0 : 1),
subject
.uniqueMethodWithName("<clinit>")
.streamInstructions()
.filter(InstructionSubject::isStaticPut)
.count());
assertFalse(
subject
.uniqueMethodWithName("<clinit>")
.streamInstructions()
.anyMatch(InstructionSubject::isConstNumber));
} else {
// The value of kotlin._Assertions.ENABLED is propagated from the assertions configuration
// for the class kotlin._Assertions.
assertFalse(
subject
.uniqueMethodWithName("m")
.streamInstructions()
.anyMatch(InstructionSubject::isThrow));
}
}
private void checkAssertionCodeRemoved(CodeInspector inspector, String clazz, boolean isR8) {
checkAssertionCodeRemoved(inspector.clazz(clazz), isR8);
}
private void checkAssertionCodeEnabled(ClassSubject subject, boolean isR8) {
assertThat(subject, isPresent());
if (subject.getOriginalName().equals("kotlin._Assertions")) {
assert !kotlinStdlibAsLibrary;
// With R8 the static-put of the kotlin._Assertions.INSTANCE field is removed as is not used.
assertEquals(
isR8 ? 1 : 2,
subject
.uniqueMethodWithName("<clinit>")
.streamInstructions()
.filter(InstructionSubject::isStaticPut)
.count());
assertTrue(
subject
.uniqueMethodWithName("<clinit>")
.streamInstructions()
.anyMatch(instruction -> instruction.isConstNumber(1)));
} else {
assertTrue(
subject
.uniqueMethodWithName("m")
.streamInstructions()
.anyMatch(InstructionSubject::isThrow));
}
}
private void checkAssertionCodeEnabled(CodeInspector inspector, String clazz, boolean isR8) {
checkAssertionCodeEnabled(inspector.clazz(clazz), isR8);
}
private void checkAssertionCodeLeft(CodeInspector inspector, String clazz, boolean isR8) {
ClassSubject subject = inspector.clazz(clazz);
if (clazz.equals("kotlin._Assertions")) {
assert !kotlinStdlibAsLibrary;
if (isR8 && useJvmAssertions) {
// When JVM assertions are used the class kotlin._Assertions is unused.
assertThat(subject, not(isPresent()));
return;
}
assertThat(subject, isPresent());
// With R8 the static-put of the kotlin._Assertions.INSTANCE field is removed as is not used.
assertEquals(
isR8 ? 1 : 2,
subject
.uniqueMethodWithName("<clinit>")
.streamInstructions()
.filter(InstructionSubject::isStaticPut)
.count());
assertFalse(
subject
.uniqueMethodWithName("<clinit>")
.streamInstructions()
.anyMatch(InstructionSubject::isConstNumber));
} else {
assertThat(subject, isPresent());
MethodSubject clinit = subject.uniqueMethodWithName("<clinit>");
if (useJvmAssertions) {
assertTrue(clinit.streamInstructions().anyMatch(InstructionSubject::isStaticPut));
} else {
assertThat(clinit, not(isPresent()));
}
assertTrue(
subject
.uniqueMethodWithName("m")
.streamInstructions()
.anyMatch(InstructionSubject::isThrow));
}
}
private void checkAssertionCodeRemoved(CodeInspector inspector, boolean isR8) {
if (isR8) {
assertThat(inspector.clazz("kotlin._Assertions"), not(isPresent()));
} else if (!kotlinStdlibAsLibrary) {
checkAssertionCodeRemoved(inspector, "kotlin._Assertions", isR8);
}
checkAssertionCodeRemoved(inspector, class1, isR8);
checkAssertionCodeRemoved(inspector, class2, isR8);
}
private void checkAssertionCodeEnabled(CodeInspector inspector, boolean isR8) {
if (isR8) {
assertThat(inspector.clazz("kotlin._Assertions"), not(isPresent()));
} else if (!kotlinStdlibAsLibrary) {
checkAssertionCodeEnabled(inspector, "kotlin._Assertions", isR8);
}
checkAssertionCodeEnabled(inspector, class1, isR8);
checkAssertionCodeEnabled(inspector, class2, isR8);
}
private void checkAssertionCodeLeft(CodeInspector inspector, boolean isR8) {
if (!kotlinStdlibAsLibrary) {
checkAssertionCodeLeft(inspector, "kotlin._Assertions", isR8);
}
checkAssertionCodeLeft(inspector, class1, isR8);
checkAssertionCodeLeft(inspector, class2, isR8);
}
@Test
public void testAssertionsForDex() throws Exception {
Assume.assumeTrue(parameters.isDexRuntime());
// Leaving assertions in or disabling them on Dalvik/Art means no assertions.
runD8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::passthroughAllAssertions),
inspector -> checkAssertionCodeLeft(inspector, false),
noAllAssertionsExpectedLines());
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::passthroughAllAssertions),
inspector -> checkAssertionCodeLeft(inspector, true),
noAllAssertionsExpectedLines());
runD8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::disableAllAssertions),
inspector -> checkAssertionCodeRemoved(inspector, false),
noAllAssertionsExpectedLines());
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::disableAllAssertions),
inspector -> checkAssertionCodeRemoved(inspector, true),
noAllAssertionsExpectedLines());
// Compile time enabling assertions gives assertions on Dalvik/Art.
runD8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::enableAllAssertions),
inspector -> checkAssertionCodeEnabled(inspector, false),
allAssertionsExpectedLines());
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::enableAllAssertions),
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines());
if (useJvmAssertions) {
// Enabling for the kotlin generated Java classes should enable all.
runD8Test(
builder ->
builder
.addAssertionsConfiguration(b -> b.setEnable().setScopeClass(class1).build())
.addAssertionsConfiguration(b -> b.setEnable().setScopeClass(class2).build()),
inspector -> {
// The default is applied to kotlin._Assertions (which for DEX is remove).
if (!kotlinStdlibAsLibrary) {
checkAssertionCodeRemoved(inspector, "kotlin._Assertions", false);
}
checkAssertionCodeEnabled(inspector, class1, false);
checkAssertionCodeEnabled(inspector, class2, false);
},
allAssertionsExpectedLines());
} else {
// Enabling for the class kotlin._Assertions should enable all.
runD8Test(
builder ->
builder.addAssertionsConfiguration(
b -> b.setEnable().setScopeClass("kotlin._Assertions").build()),
inspector -> checkAssertionCodeEnabled(inspector, false),
allAssertionsExpectedLines());
}
if (useJvmAssertions) {
// Enabling for the kotlin generated Java classes should enable all.
runR8Test(
builder ->
builder
.addAssertionsConfiguration(b -> b.setEnable().setScopeClass(class1).build())
.addAssertionsConfiguration(b -> b.setEnable().setScopeClass(class2).build()),
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines());
} else {
// Enabling for the class kotlin._Assertions should enable all.
runR8Test(
builder ->
builder.addAssertionsConfiguration(
b -> b.setEnable().setScopeClass("kotlin._Assertions").build()),
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines());
}
if (useJvmAssertions) {
// Enabling for the Java package for the kotlin test classes package should enable all.
runD8Test(
builder ->
builder.addAssertionsConfiguration(
b -> b.setEnable().setScopePackage(kotlintestclasesPackage).build()),
inspector -> {
// The default is applied to kotlin._Assertions (which for DEX is remove).
if (!kotlinStdlibAsLibrary) {
checkAssertionCodeRemoved(inspector, "kotlin._Assertions", false);
}
checkAssertionCodeEnabled(inspector, class1, false);
checkAssertionCodeEnabled(inspector, class2, false);
},
allAssertionsExpectedLines());
} else {
// Enabling for the kotlin package (containing kotlin._Assertions) should enable all.
runD8Test(
builder ->
builder.addAssertionsConfiguration(
b -> b.setEnable().setScopePackage("kotlin").build()),
inspector -> checkAssertionCodeEnabled(inspector, false),
allAssertionsExpectedLines());
}
if (useJvmAssertions) {
// Enabling for the Java package for the kotlin test classes package should enable all.
runR8Test(
builder ->
builder.addAssertionsConfiguration(
b -> b.setEnable().setScopePackage(kotlintestclasesPackage).build()),
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines());
} else {
// Enabling for the kotlin package (containing kotlin._Assertions) should enable all.
runR8Test(
builder ->
builder.addAssertionsConfiguration(
b -> b.setEnable().setScopePackage("kotlin").build()),
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines());
}
}
@Test
public void testAssertionsForCfEnableWithStackMap() throws Exception {
Assume.assumeTrue(parameters.isCfRuntime());
Assume.assumeTrue(useJvmAssertions);
Assume.assumeTrue(kotlinCompilationKey.targetVersion == KotlinTargetVersion.JAVA_8);
// Compile time enabling or disabling assertions means the -ea flag has no effect.
runR8Test(
builder -> {
builder.addAssertionsConfiguration(AssertionsConfiguration.Builder::enableAllAssertions);
builder.addOptionsModification(options -> options.testing.readInputStackMaps = true);
},
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines());
runR8Test(
builder -> {
builder.addAssertionsConfiguration(AssertionsConfiguration.Builder::enableAllAssertions);
builder.addOptionsModification(options -> options.testing.readInputStackMaps = true);
},
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines(),
true);
}
@Test
public void testAssertionsForCfPassThrough() throws Exception {
Assume.assumeTrue(parameters.isCfRuntime());
// Leaving assertion code means assertions are controlled by the -ea flag.
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::passthroughAllAssertions),
inspector -> checkAssertionCodeLeft(inspector, true),
noAllAssertionsExpectedLines());
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::passthroughAllAssertions),
inspector -> checkAssertionCodeLeft(inspector, true),
allAssertionsExpectedLines(),
true);
}
@Test
public void testAssertionsForCfEnable() throws Exception {
Assume.assumeTrue(parameters.isCfRuntime());
// Compile time enabling or disabling assertions means the -ea flag has no effect.
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::enableAllAssertions),
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines());
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::enableAllAssertions),
inspector -> checkAssertionCodeEnabled(inspector, true),
allAssertionsExpectedLines(),
true);
}
@Test
public void testAssertionsForCfDisable() throws Exception {
Assume.assumeTrue(parameters.isCfRuntime());
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::disableAllAssertions),
inspector -> checkAssertionCodeRemoved(inspector, true),
noAllAssertionsExpectedLines());
runR8Test(
builder ->
builder.addAssertionsConfiguration(
AssertionsConfiguration.Builder::disableAllAssertions),
inspector -> checkAssertionCodeRemoved(inspector, true),
noAllAssertionsExpectedLines(),
true);
}
@Test
public void TestWithModifiedKotlinAssertions() throws Exception {
Assume.assumeTrue(parameters.isDexRuntime());
testForD8()
.addProgramClassFileData(dumpModifiedKotlinAssertions())
.addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
.setMinApi(parameters.getApiLevel())
.addAssertionsConfiguration(AssertionsConfiguration.Builder::passthroughAllAssertions)
.run(
parameters.getRuntime(),
getClass().getPackage().getName() + ".kotlintestclasses.TestClassKt")
.assertSuccessWithOutputLines(noAllAssertionsExpectedLines());
testForD8()
.addProgramClassFileData(dumpModifiedKotlinAssertions())
.addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
.setMinApi(parameters.getApiLevel())
.addAssertionsConfiguration(AssertionsConfiguration.Builder::enableAllAssertions)
.run(
parameters.getRuntime(),
getClass().getPackage().getName() + ".kotlintestclasses.TestClassKt")
.assertSuccessWithOutputLines(allAssertionsExpectedLines());
testForD8()
.addProgramClassFileData(dumpModifiedKotlinAssertions())
.addProgramFiles(kotlinClasses.get(kotlinCompilationKey))
.setMinApi(parameters.getApiLevel())
.addAssertionsConfiguration(AssertionsConfiguration.Builder::disableAllAssertions)
.run(
parameters.getRuntime(),
getClass().getPackage().getName() + ".kotlintestclasses.TestClassKt")
.assertSuccessWithOutputLines(noAllAssertionsExpectedLines());
}
// Slightly modified version of kotlin._Assertions to hit all code paths in the assertion
// rewriter. See "Code added" below.
public static byte[] dumpModifiedKotlinAssertions() {
ClassWriter classWriter = new ClassWriter(0);
FieldVisitor fieldVisitor;
MethodVisitor methodVisitor;
classWriter.visit(
V1_6,
ACC_PUBLIC | ACC_FINAL | ACC_SUPER,
"kotlin/_Assertions",
null,
"java/lang/Object",
null);
{
fieldVisitor =
classWriter.visitField(ACC_PUBLIC | ACC_FINAL | ACC_STATIC, "ENABLED", "Z", null, null);
fieldVisitor.visitEnd();
}
{
fieldVisitor =
classWriter.visitField(
ACC_PUBLIC | ACC_FINAL | ACC_STATIC, "INSTANCE", "Lkotlin/_Assertions;", null, null);
fieldVisitor.visitEnd();
}
{
methodVisitor =
classWriter.visitMethod(
ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC | ACC_DEPRECATED,
"ENABLED$annotations",
"()V",
null,
null);
methodVisitor.visitCode();
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
}
{
methodVisitor = classWriter.visitMethod(ACC_PRIVATE, "<init>", "()V", null, null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
}
{
methodVisitor = classWriter.visitMethod(ACC_STATIC, "<clinit>", "()V", null, null);
methodVisitor.visitCode();
methodVisitor.visitTypeInsn(NEW, "kotlin/_Assertions");
methodVisitor.visitInsn(DUP);
methodVisitor.visitMethodInsn(INVOKESPECIAL, "kotlin/_Assertions", "<init>", "()V", false);
methodVisitor.visitVarInsn(ASTORE, 0);
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitFieldInsn(
PUTSTATIC, "kotlin/_Assertions", "INSTANCE", "Lkotlin/_Assertions;");
// Code added (added an additional call to getClass().desiredAssertionStatus() which
// result is not assigned to ENABLED).
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL, "java/lang/Class", "desiredAssertionStatus", "()Z", false);
methodVisitor.visitInsn(POP);
// End code added.
methodVisitor.visitVarInsn(ALOAD, 0);
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
methodVisitor.visitMethodInsn(
INVOKEVIRTUAL, "java/lang/Class", "desiredAssertionStatus", "()Z", false);
methodVisitor.visitFieldInsn(PUTSTATIC, "kotlin/_Assertions", "ENABLED", "Z");
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 1);
methodVisitor.visitEnd();
}
classWriter.visitEnd();
return classWriter.toByteArray();
}
}