blob: aba1f31cb0b32259cd282a1882f7c2f4bb54a58d [file] [log] [blame]
// Copyright (c) 2019, 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.ir.optimize.outliner.primitivetypes;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.CodeMatchers;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class PrimitiveTypesTest extends TestBase {
private final TestParameters parameters;
@Parameterized.Parameters(name = "{0}")
public static TestParametersCollection data() {
return getTestParameters().withAllRuntimes().build();
}
public PrimitiveTypesTest(TestParameters parameters) {
this.parameters = parameters;
}
private void validateOutlining(CodeInspector inspector, Class<?> testClass, String argumentType) {
ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
MethodSubject outline0Method =
outlineClass.method(
"java.lang.String", "outline0", ImmutableList.of(argumentType, argumentType));
assertThat(outline0Method, isPresent());
ClassSubject classSubject = inspector.clazz(testClass);
assertThat(
classSubject.uniqueMethodWithName("method1"), CodeMatchers.invokesMethod(outline0Method));
assertThat(
classSubject.uniqueMethodWithName("method2"), CodeMatchers.invokesMethod(outline0Method));
}
public void runTest(Class<?> testClass, String argumentType, String expectedOutput)
throws Exception {
testForR8(parameters.getBackend())
.enableInliningAnnotations()
.enableClassInliningAnnotations()
.addProgramClasses(testClass)
.addProgramClasses(MyStringBuilder.class)
.addKeepMainRule(testClass)
.setMinApi(parameters.getRuntime())
.noMinification()
.addOptionsModification(
options -> {
options.outline.threshold = 2;
options.outline.minSize = 2;
})
.compile()
.inspect(inspector -> validateOutlining(inspector, testClass, argumentType))
.run(parameters.getRuntime(), testClass)
.assertSuccessWithOutput(expectedOutput);
}
@Test
public void testBoolean() throws Exception {
runTest(TestClassBoolean.class, "boolean", StringUtils.lines("truetrue", "falsefalse"));
}
@Test
public void testShort() throws Exception {
runTest(TestClassShort.class, "short", StringUtils.lines("11", "22"));
}
@Test
public void testByte() throws Exception {
runTest(TestClassByte.class, "byte", StringUtils.lines("33", "44"));
}
@Test
public void testChar() throws Exception {
runTest(TestClassChar.class, "char", StringUtils.lines("AA", "BB"));
}
// StringBuilder wrapper for testing, as StringBuilder does not have append methods with
// byte or short but only int.
@NeverClassInline
public static class MyStringBuilder {
private final StringBuilder sb = new StringBuilder();
@NeverInline
public MyStringBuilder append(byte b) {
sb.append(b);
return this;
}
@NeverInline
public MyStringBuilder append(short s) {
sb.append(s);
return this;
}
@NeverInline
public String toString() {
return sb.toString();
}
}
static class TestClassBoolean {
@NeverInline
public static String method1(boolean b) {
StringBuilder sb = new StringBuilder();
sb.append(b);
sb.append(b);
return sb.toString();
}
@NeverInline
public static String method2(boolean b) {
StringBuilder sb = new StringBuilder();
sb.append(b);
sb.append(b);
return sb.toString();
}
public static void main(String[] args) {
System.out.println(method1(true));
System.out.println(method2(false));
}
}
static class TestClassByte {
@NeverInline
public static String method1(byte b) {
MyStringBuilder sb = new MyStringBuilder();
sb.append(b);
sb.append(b);
return sb.toString();
}
@NeverInline
public static String method2(byte b) {
MyStringBuilder sb = new MyStringBuilder();
sb.append(b);
sb.append(b);
return sb.toString();
}
public static void main(String[] args) {
System.out.println(method1((byte) 3));
System.out.println(method2((byte) 4));
}
}
static class TestClassShort {
@NeverInline
public static String method1(short s) {
MyStringBuilder sb = new MyStringBuilder();
sb.append(s);
sb.append(s);
return sb.toString();
}
@NeverInline
public static String method2(short s) {
MyStringBuilder sb = new MyStringBuilder();
sb.append(s);
sb.append(s);
return sb.toString();
}
public static void main(String[] args) {
System.out.println(method1((short) 1));
System.out.println(method2((short) 2));
}
}
static class TestClassChar {
@NeverInline
public static String method1(char c) {
StringBuilder sb = new StringBuilder();
sb.append(c);
sb.append(c);
return sb.toString();
}
@NeverInline
public static String method2(char c) {
StringBuilder sb = new StringBuilder();
sb.append(c);
sb.append(c);
return sb.toString();
}
public static void main(String[] args) {
System.out.println(method1('A'));
System.out.println(method2('B'));
}
}
}