Merge "Revert "Support code between def and use in IfWithConstantSimplifier"" into ub-jack
diff --git a/build.xml b/build.xml
index 285e4f5..95ee120 100644
--- a/build.xml
+++ b/build.xml
@@ -954,12 +954,14 @@
<exclude name="com/android/jack/frontend/test007/**"/>
<exclude name="com/android/jack/jill/test001/**"/>
<exclude name="com/android/jack/jill/test002/**"/>
+ <exclude name="com/android/jack/jill/test003/**"/>
<exclude name="com/android/jack/optimizations/lambdas/test001/**"/>
<exclude name="com/android/jack/optimizations/lambdas/test002/**"/>
<exclude name="com/android/jack/optimizations/lambdas/test003/**"/>
<exclude name="com/android/jack/optimizations/lambdas/test004/**"/>
<exclude name="com/android/jack/optimizations/lambdas/test005/**"/>
<exclude name="com/android/jack/optimizations/lambdas/test006/**"/>
+ <exclude name="com/android/jack/optimizations/lambdas/test007/**"/>
<exclude name="com/android/jack/sourcepath/test002/jack/Sourcepath002.java"/>
<exclude name="com/android/jack/shrob/test062/jack/**"/>
<classpath>
diff --git a/jack-api/src/com/android/jack/api/v03/Api03Config.java b/jack-api/src/com/android/jack/api/v03/Api03Config.java
index 5deb735..a70f57a 100644
--- a/jack-api/src/com/android/jack/api/v03/Api03Config.java
+++ b/jack-api/src/com/android/jack/api/v03/Api03Config.java
@@ -20,7 +20,7 @@
import com.android.jack.api.v02.Api02Config;
import java.io.File;
-import java.util.Collection;
+import java.util.List;
import javax.annotation.Nonnull;
@@ -33,12 +33,12 @@
* @param pluginNames Plugin names, each name must be unique
* @throws ConfigurationException if something is wrong in Jack's configuration
*/
- void setPluginNames(@Nonnull Collection<String> pluginNames) throws ConfigurationException;
+ void setPluginNames(@Nonnull List<String> pluginNames) throws ConfigurationException;
/**
* Sets the path where to find Jack plugins.
- * @param pluginPath A collection of jar files where Jack plugins reside
+ * @param pluginPath The plugin path as a list
* @throws ConfigurationException if something is wrong in Jack's configuration
*/
- void setPluginPath(@Nonnull Collection<File> pluginPath) throws ConfigurationException;
+ void setPluginPath(@Nonnull List<File> pluginPath) throws ConfigurationException;
}
diff --git a/jack-api/src/com/android/jack/api/v04c/Api04CandidateConfig.java b/jack-api/src/com/android/jack/api/v04/Api04Config.java
similarity index 92%
rename from jack-api/src/com/android/jack/api/v04c/Api04CandidateConfig.java
rename to jack-api/src/com/android/jack/api/v04/Api04Config.java
index 690970f..87665aa 100644
--- a/jack-api/src/com/android/jack/api/v04c/Api04CandidateConfig.java
+++ b/jack-api/src/com/android/jack/api/v04/Api04Config.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.jack.api.v04c;
+package com.android.jack.api.v04;
import com.android.jack.api.v01.ConfigurationException;
import com.android.jack.api.v03.Api03Config;
@@ -26,7 +26,7 @@
/**
* A configuration for API level 04 of the Jack compiler compatible with API level 03
*/
-public interface Api04CandidateConfig extends Api03Config {
+public interface Api04Config extends Api03Config {
/**
* Set the default {@link Charset} used when no charset is specified by file with
* {@link HasCharset}.
diff --git a/jack-api/src/com/android/jack/api/v04c/HasCharset.java b/jack-api/src/com/android/jack/api/v04/HasCharset.java
similarity index 87%
rename from jack-api/src/com/android/jack/api/v04c/HasCharset.java
rename to jack-api/src/com/android/jack/api/v04/HasCharset.java
index a94a5b0..ec97efd 100644
--- a/jack-api/src/com/android/jack/api/v04c/HasCharset.java
+++ b/jack-api/src/com/android/jack/api/v04/HasCharset.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.jack.api.v04c;
+package com.android.jack.api.v04;
import java.io.File;
import java.nio.charset.Charset;
@@ -23,7 +23,7 @@
/**
* A {@link File} with a {@link Charset} different from the default one (
- * {@link Api04CandidateConfig#setDefaultCharset(Charset)}) must implement that interface.
+ * {@link Api04Config#setDefaultCharset(Charset)}) must implement that interface.
*/
public interface HasCharset {
/**
diff --git a/jack-tests/.classpath b/jack-tests/.classpath
index ce416be..f80657a 100644
--- a/jack-tests/.classpath
+++ b/jack-tests/.classpath
@@ -2,7 +2,7 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
- <classpathentry excluding="com/android/jack/annotation/test014/jack/|com/android/jack/annotation/test015/jack/|com/android/jack/annotation/test016/jack/|com/android/jack/annotation/test017/jack/|com/android/jack/classpath/test002/lib1override/|com/android/jack/compiletime/test*/**|com/android/jack/enums/test003/link/Other.java|com/android/jack/enums/test003/link/Values.java|com/android/jack/error/test001/jack/A.java|com/android/jack/error/test002/jack/A.java|com/android/jack/frontend/test002/jack/PackageName/ClassInConflictingPackage.java|com/android/jack/frontend/test005/jack/|com/android/jack/frontend/test006/jack/|com/android/jack/frontend/test007/jack/|com/android/jack/frontend/test007/jackduplicate/|com/android/jack/frontend/test008/jack/NoOuterContext.java|com/android/jack/frontend/test010/jack/UnusedLocalVar.java|com/android/jack/frontend/test013/jack/ExtendingInnerOnly.java|com/android/jack/frontend/test014/jack/ExtendingInnerInStaticContext.java|com/android/jack/frontend/test015/jack/WithOuterContextButStatic.java|com/android/jack/frontend/test016/jack/WithDuplicated.java|com/android/jack/frontend/test017/jack/InvalidQualification.java|com/android/jack/jarjar/test003/dontcompile/|com/android/jack/jarjar/test004/dontcompile/|com/android/jack/java8/annotation/|com/android/jack/java8/defaultmethod/|com/android/jack/java8/gwt/|com/android/jack/java8/inference/|com/android/jack/java8/intersectiontype/|com/android/jack/java8/lambda/|com/android/jack/java8/methodref/|com/android/jack/java8/retrolambda/|com/android/jack/java8/staticmethod/|com/android/jack/java8/variable/|com/android/jack/lookup/test001/liboverride/|com/android/jack/nopackage/test*/**|com/android/jack/optimizations/lambdas/test*/**|com/android/jack/jarjar/test006/dontcompile/|com/android/jack/java8/bridges/|com/android/jack/jill/test001/|com/android/jack/jill/test002/|com/android/jack/sourcepath/test002/jack/Sourcepath002.java|com/android/jack/annotation/test019/jack/|com/android/jack/frontend/test018/jack/|com/android/jack/annotation/test020/jack/|com/android/jack/assign/test002/jack/|com/android/jack/annotation/processor/sample2/src/|com/android/jack/shrob/test062/jack/Tests.java|com/android/jack/shrob/test062/jack/A.java|com/android/jack/coverage/test006_v1/jack/|com/android/jack/coverage/test006_v2/jack/" kind="src" path="tests"/>
+ <classpathentry excluding="com/android/jack/annotation/test014/jack/|com/android/jack/annotation/test015/jack/|com/android/jack/annotation/test016/jack/|com/android/jack/annotation/test017/jack/|com/android/jack/classpath/test002/lib1override/|com/android/jack/compiletime/test*/**|com/android/jack/enums/test003/link/Other.java|com/android/jack/enums/test003/link/Values.java|com/android/jack/error/test001/jack/A.java|com/android/jack/error/test002/jack/A.java|com/android/jack/frontend/test002/jack/PackageName/ClassInConflictingPackage.java|com/android/jack/frontend/test005/jack/|com/android/jack/frontend/test006/jack/|com/android/jack/frontend/test007/jack/|com/android/jack/frontend/test007/jackduplicate/|com/android/jack/frontend/test008/jack/NoOuterContext.java|com/android/jack/frontend/test010/jack/UnusedLocalVar.java|com/android/jack/frontend/test013/jack/ExtendingInnerOnly.java|com/android/jack/frontend/test014/jack/ExtendingInnerInStaticContext.java|com/android/jack/frontend/test015/jack/WithOuterContextButStatic.java|com/android/jack/frontend/test016/jack/WithDuplicated.java|com/android/jack/frontend/test017/jack/InvalidQualification.java|com/android/jack/jarjar/test003/dontcompile/|com/android/jack/jarjar/test004/dontcompile/|com/android/jack/java8/annotation/|com/android/jack/java8/defaultmethod/|com/android/jack/java8/gwt/|com/android/jack/java8/inference/|com/android/jack/java8/intersectiontype/|com/android/jack/java8/lambda/|com/android/jack/java8/methodref/|com/android/jack/java8/retrolambda/|com/android/jack/java8/staticmethod/|com/android/jack/java8/variable/|com/android/jack/lookup/test001/liboverride/|com/android/jack/nopackage/test*/**|com/android/jack/optimizations/lambdas/test*/**|com/android/jack/jarjar/test006/dontcompile/|com/android/jack/java8/bridges/|com/android/jack/jill/test001/|com/android/jack/jill/test002/|com/android/jack/jill/test003/|com/android/jack/sourcepath/test002/jack/Sourcepath002.java|com/android/jack/annotation/test019/jack/|com/android/jack/frontend/test018/jack/|com/android/jack/annotation/test020/jack/|com/android/jack/assign/test002/jack/|com/android/jack/annotation/processor/sample2/src/|com/android/jack/shrob/test062/jack/Tests.java|com/android/jack/shrob/test062/jack/A.java|com/android/jack/coverage/test006_v1/jack/|com/android/jack/coverage/test006_v2/jack/" kind="src" path="tests"/>
<classpathentry kind="lib" path="libs/junit4.jar"/>
<classpathentry kind="lib" path="libs/antlr-runtime-lib.jar"/>
<classpathentry kind="lib" path="libs/dx-ref.jar"/>
diff --git a/jack-tests/src/com/android/jack/test/toolchain/JackApiV04Toolchain.java b/jack-tests/src/com/android/jack/test/toolchain/JackApiV04Toolchain.java
index 3764363..ee1cb29 100644
--- a/jack-tests/src/com/android/jack/test/toolchain/JackApiV04Toolchain.java
+++ b/jack-tests/src/com/android/jack/test/toolchain/JackApiV04Toolchain.java
@@ -26,7 +26,7 @@
import com.android.jack.api.v01.ReporterKind;
import com.android.jack.api.v01.VerbosityLevel;
import com.android.jack.api.v02.JavaSourceVersion;
-import com.android.jack.api.v04c.Api04CandidateConfig;
+import com.android.jack.api.v04.Api04Config;
import com.android.jack.test.TestConfigurationException;
import com.android.sched.util.log.LoggerFactory;
import com.android.sched.vfs.Container;
@@ -47,11 +47,11 @@
public class JackApiV04Toolchain extends JackApiToolchainBase implements JackApiV04 {
@Nonnull
- private Api04CandidateConfig apiV04Config;
+ private Api04Config apiV04Config;
JackApiV04Toolchain(@CheckForNull File jackPrebuilt) {
- super(jackPrebuilt, Api04CandidateConfig.class);
- apiV04Config = (Api04CandidateConfig) config;
+ super(jackPrebuilt, Api04Config.class);
+ apiV04Config = (Api04Config) config;
addProperty(Options.USE_DEFAULT_LIBRARIES.getName(), "false");
}
diff --git a/jack-tests/tests/com/android/jack/annotations/ForceInMainDex.java b/jack-tests/tests/com/android/jack/annotations/ForceInMainDex.java
index e37c392..466a685 100644
--- a/jack-tests/tests/com/android/jack/annotations/ForceInMainDex.java
+++ b/jack-tests/tests/com/android/jack/annotations/ForceInMainDex.java
@@ -24,7 +24,7 @@
/**
* Indicate that the type must always be in the main dex.
*/
-@Retention(RetentionPolicy.SOURCE)
+@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface ForceInMainDex {
diff --git a/jack-tests/tests/com/android/jack/annotations/MultiDexInstaller.java b/jack-tests/tests/com/android/jack/annotations/MultiDexInstaller.java
index b8d03dc..3f6cfb1 100644
--- a/jack-tests/tests/com/android/jack/annotations/MultiDexInstaller.java
+++ b/jack-tests/tests/com/android/jack/annotations/MultiDexInstaller.java
@@ -25,7 +25,7 @@
* Indicate that the element may be used during the multidex legacy support installation. As such it
* must be kept in main dex along with its dependencies.
*/
-@Retention(RetentionPolicy.SOURCE)
+@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR})
public @interface MultiDexInstaller {
diff --git a/jack-tests/tests/com/android/jack/jill/JillTests.java b/jack-tests/tests/com/android/jack/jill/JillTests.java
index 08c2e50..1dec89a 100644
--- a/jack-tests/tests/com/android/jack/jill/JillTests.java
+++ b/jack-tests/tests/com/android/jack/jill/JillTests.java
@@ -17,6 +17,7 @@
package com.android.jack.jill;
import com.android.jack.test.TestsProperties;
+import com.android.jack.test.junit.KnownIssue;
import com.android.jack.test.junit.Runtime;
import com.android.jack.test.runner.RuntimeRunner;
import com.android.jack.test.toolchain.AbstractTestTools;
@@ -45,6 +46,12 @@
runJillTest("002");
}
+ @Test
+ @Runtime
+ public void test003() throws Exception {
+ runJillTest("003");
+ }
+
private static void runJillTest(@Nonnull String testNumber) throws Exception {
String jackFolder = getJackFolder(testNumber);
String jasminFolder = getJasminFolder(testNumber);
diff --git a/jack-tests/tests/com/android/jack/jill/test003/jack/Test003.java b/jack-tests/tests/com/android/jack/jill/test003/jack/Test003.java
new file mode 100644
index 0000000..2bdc26d
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/jill/test003/jack/Test003.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.jack.jill.test003.jack;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+public class Test003 {
+
+ @Test
+ public void test001() {
+ Assert.assertEquals(1.0 > 2.0, External.greaterThan1(1.0, 2.0));
+ Assert.assertEquals(2.0 > 1.0, External.greaterThan1(2.0, 1.0));
+ Assert.assertEquals(2.0 > 2.0, External.greaterThan1(2.0, 2.0));
+ Assert.assertEquals(2.0 > Double.NaN, External.greaterThan1(2.0, Double.NaN));
+ Assert.assertEquals(Double.NaN > Double.NaN, External.greaterThan1(Double.NaN, Double.NaN));
+ Assert.assertEquals(Double.NaN > 2.0, External.greaterThan1(Double.NaN, 2.0));
+ }
+
+ @Test
+ public void test002() {
+ Assert.assertEquals(1.0 > 2.0, External.greaterThan2(1.0, 2.0));
+ Assert.assertEquals(2.0 > 1.0, External.greaterThan2(2.0, 1.0));
+ Assert.assertEquals(2.0 > 2.0, External.greaterThan2(2.0, 2.0));
+ Assert.assertEquals(2.0 > Double.NaN, External.greaterThan2(2.0, Double.NaN));
+ Assert.assertEquals(Double.NaN > Double.NaN, External.greaterThan2(Double.NaN, Double.NaN));
+ Assert.assertEquals(Double.NaN > 2.0, External.greaterThan2(Double.NaN, 2.0));
+ }
+
+ @Test
+ public void test003() {
+ Assert.assertEquals(1.0 > 2.0, External.greaterThan3(1.0, 2.0));
+ Assert.assertEquals(2.0 > 1.0, External.greaterThan3(2.0, 1.0));
+ Assert.assertEquals(2.0 > 2.0, External.greaterThan3(2.0, 2.0));
+ Assert.assertEquals(2.0 > Double.NaN, External.greaterThan3(2.0, Double.NaN));
+ Assert.assertEquals(Double.NaN > Double.NaN, External.greaterThan3(Double.NaN, Double.NaN));
+ Assert.assertEquals(Double.NaN > 2.0, External.greaterThan3(Double.NaN, 2.0));
+ }
+}
\ No newline at end of file
diff --git a/jack-tests/tests/com/android/jack/jill/test003/jasmin/External.j b/jack-tests/tests/com/android/jack/jill/test003/jasmin/External.j
new file mode 100644
index 0000000..73fbe02
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/jill/test003/jasmin/External.j
@@ -0,0 +1,77 @@
+; Copyright (C) 2016 The Android Open Source Project
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+; http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+
+.class public com/android/jack/jill/test003/jack/External
+.super java/lang/Object
+
+.method public <init>()V
+ aload_0
+ invokespecial java/lang/Object/<init>()V
+ return
+.end method
+
+.method public static greaterThan1(DD)Z
+ .limit locals 4
+ .limit stack 3
+ dload_0
+ dload_2
+ dcmpl
+ aconst_null
+ swap
+ ifle if_label
+ pop
+ iconst_1
+ ireturn
+if_label:
+ pop
+ iconst_0
+ ireturn
+.end method
+
+.method public static greaterThan2(DD)Z
+ .limit locals 4
+ .limit stack 5
+ aconst_null
+ dload_0
+ dload_2
+ dcmpl
+ swap
+ pop
+ ifle if_label
+ iconst_1
+ ireturn
+if_label:
+ iconst_0
+ ireturn
+.end method
+
+.method public static greaterThan3(DD)Z
+ .limit locals 4
+ .limit stack 3
+ dload_0
+ dload_2
+ dcmpl
+ iconst_1
+ iconst_2
+ iadd
+ swap
+ ifle if_label
+ pop
+ iconst_1
+ ireturn
+if_label:
+ pop
+ iconst_0
+ ireturn
+.end method
diff --git a/jack-tests/tests/com/android/jack/jill/test003/jasmin/jarInput.jar b/jack-tests/tests/com/android/jack/jill/test003/jasmin/jarInput.jar
new file mode 100644
index 0000000..6e92ca3
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/jill/test003/jasmin/jarInput.jar
Binary files differ
diff --git a/jack-tests/tests/com/android/jack/optimizations/lambdas/LambdaClassesValidator.java b/jack-tests/tests/com/android/jack/optimizations/lambdas/LambdaClassesValidator.java
index 4185cd5..87b0007 100644
--- a/jack-tests/tests/com/android/jack/optimizations/lambdas/LambdaClassesValidator.java
+++ b/jack-tests/tests/com/android/jack/optimizations/lambdas/LambdaClassesValidator.java
@@ -83,28 +83,31 @@
// Interfaces
List<String> items = new ArrayList<>(type.getInterfaceNames());
- print(sb, "implements", items);
+ print(sb, "implements", items, false);
// Fields
items.clear();
for (DexField field : type.getFields()) {
items.add(field.getId());
}
- print(sb, "fields", items);
+ print(sb, "fields", items, true);
// Methods
items.clear();
for (DexMethod method : type.getMethods()) {
items.add(method.getId());
}
- print(sb, "methods", items);
+ print(sb, "methods", items, true);
}
private static void print(
- @Nonnull StringBuilder sb, @Nonnull String header, @Nonnull List<String> items) {
+ @Nonnull StringBuilder sb, @Nonnull String header,
+ @Nonnull List<String> items, boolean ordered) {
if (items.size() > 0) {
sb.append(" - ").append(header).append(":\n");
- Collections.sort(items);
+ if (ordered) {
+ Collections.sort(items);
+ }
for (String item : items) {
sb.append(" ").append(item).append('\n');
}
diff --git a/jack-tests/tests/com/android/jack/optimizations/lambdas/LambdaTests.java b/jack-tests/tests/com/android/jack/optimizations/lambdas/LambdaTests.java
index 280a1db..5d9ee8b 100644
--- a/jack-tests/tests/com/android/jack/optimizations/lambdas/LambdaTests.java
+++ b/jack-tests/tests/com/android/jack/optimizations/lambdas/LambdaTests.java
@@ -69,24 +69,26 @@
Class(@Nonnull String name, @Nonnull String... interfaces) {
builder.append(name).append("\n");
- impl(interfaces, " - implements:\n");
+ printImpl(interfaces, " - implements:\n", false);
}
@Nonnull
Class methods(@Nonnull String... signatures) {
- return impl(signatures, " - methods:\n");
+ return printImpl(signatures, " - methods:\n", true);
}
@Nonnull
Class fields(@Nonnull String... fields) {
- return impl(fields, " - fields:\n");
+ return printImpl(fields, " - fields:\n", true);
}
@Nonnull
- private Class impl(@Nonnull String[] names, @Nonnull String str) {
+ private Class printImpl(@Nonnull String[] names, @Nonnull String str, boolean ordered) {
if (names.length > 0) {
builder.append(str);
- Arrays.sort(names);
+ if (ordered) {
+ Arrays.sort(names);
+ }
for (String n : names) {
builder.append(" ").append(n).append("\n");
}
@@ -635,4 +637,43 @@
config(LambdaGroupingScope.PACKAGE, /* interfaces: */false, /* stateless: */false),
new LambdaClassesValidator(TEST006_PACKAGE));
}
+
+ // ===============================================================================================
+
+ @Nonnull
+ private static final String PKG_007 = "com.android.jack.optimizations.lambdas.test007";
+
+ @Nonnull
+ private static final String TEST007_DEFAULT = "" +
+ new Class(lambda(PKG_007, 0), types(PKG_007, "Ic", "Ia", "Ib"))
+ .methods("<init>()V", "$m$0()Ljava/lang/String;", "m()Ljava/lang/String;") +
+ new Class(lambda(PKG_007, 1), types(PKG_007, "Ic", "Iaa"))
+ .methods("<init>()V", "$m$0()Ljava/lang/String;", "m()Ljava/lang/String;") +
+ new Class(lambda(PKG_007, 2), types(PKG_007, "Ic", "Ib"))
+ .methods("<init>()V", "$m$0()Ljava/lang/String;", "m()Ljava/lang/String;") +
+ new Class(lambda(PKG_007, 3), types(PKG_007, "Ic", "Ib", "Ia"))
+ .methods("<init>()V", "$m$0()Ljava/lang/String;", "m()Ljava/lang/String;") +
+ "";
+
+ @Nonnull
+ private static final String TEST007_MERGE_INTERFACES = "" +
+ new Class(lambda(PKG_007, 0), types(PKG_007, "Ia", "Iaa", "Ib", "Ic"))
+ .fields("$id:B")
+ .methods("<init>(B)V", "m()Ljava/lang/String;",
+ "$m$0()Ljava/lang/String;", "$m$1()Ljava/lang/String;",
+ "$m$2()Ljava/lang/String;", "$m$3()Ljava/lang/String;") +
+ "";
+
+
+ @Test
+ @Runtime
+ public void test007() throws Exception {
+ compileAndValidate(PKG_007,
+ config(LambdaGroupingScope.TYPE, /* interfaces: */false, /* stateless: */false),
+ new LambdaClassesValidator(TEST007_DEFAULT));
+
+ compileAndValidate(PKG_007,
+ config(LambdaGroupingScope.TYPE, /* interfaces: */true, /* stateless: */false),
+ new LambdaClassesValidator(TEST007_MERGE_INTERFACES));
+ }
}
diff --git a/jack-api/src/com/android/jack/api/v04c/HasCharset.java b/jack-tests/tests/com/android/jack/optimizations/lambdas/test007/dx/Tests.java
similarity index 60%
copy from jack-api/src/com/android/jack/api/v04c/HasCharset.java
copy to jack-tests/tests/com/android/jack/optimizations/lambdas/test007/dx/Tests.java
index a94a5b0..f8d4ba1 100644
--- a/jack-api/src/com/android/jack/api/v04c/HasCharset.java
+++ b/jack-tests/tests/com/android/jack/optimizations/lambdas/test007/dx/Tests.java
@@ -14,21 +14,18 @@
* limitations under the License.
*/
-package com.android.jack.api.v04c;
+package com.android.jack.optimizations.lambdas.test007.dx;
-import java.io.File;
-import java.nio.charset.Charset;
+import com.android.jack.optimizations.lambdas.test007.jack.*;
-import javax.annotation.Nonnull;
+import junit.framework.Assert;
+import org.junit.Test;
-/**
- * A {@link File} with a {@link Charset} different from the default one (
- * {@link Api04CandidateConfig#setDefaultCharset(Charset)}) must implement that interface.
- */
-public interface HasCharset {
- /**
- * @return the {@link Charset}
- */
- @Nonnull
- Charset getCharset();
+/** Just touch all the classes */
+public class Tests {
+ @Test
+ public void test001() throws Throwable {
+ Assert.assertEquals(
+ "Ia&Ic&Ib Ib&Ic&Ia Iaa&Ic&Ia Ib&Ic", A.test());
+ }
}
diff --git a/jack-api/src/com/android/jack/api/v04c/HasCharset.java b/jack-tests/tests/com/android/jack/optimizations/lambdas/test007/jack/A.java
similarity index 60%
copy from jack-api/src/com/android/jack/api/v04c/HasCharset.java
copy to jack-tests/tests/com/android/jack/optimizations/lambdas/test007/jack/A.java
index a94a5b0..cfc733e 100644
--- a/jack-api/src/com/android/jack/api/v04c/HasCharset.java
+++ b/jack-tests/tests/com/android/jack/optimizations/lambdas/test007/jack/A.java
@@ -14,21 +14,27 @@
* limitations under the License.
*/
-package com.android.jack.api.v04c;
+package com.android.jack.optimizations.lambdas.test007.jack;
-import java.io.File;
-import java.nio.charset.Charset;
+interface Ia {
+}
-import javax.annotation.Nonnull;
+interface Iaa extends Ia {
+}
-/**
- * A {@link File} with a {@link Charset} different from the default one (
- * {@link Api04CandidateConfig#setDefaultCharset(Charset)}) must implement that interface.
- */
-public interface HasCharset {
- /**
- * @return the {@link Charset}
- */
- @Nonnull
- Charset getCharset();
+interface Ib {
+}
+
+interface Ic {
+ String m();
+}
+
+public class A {
+ public static String test() {
+ return
+ ((Ia & Ic & Ib) () -> "Ia&Ic&Ib ").m() +
+ ((Ib & Ic & Ia) () -> "Ib&Ic&Ia ").m() +
+ ((Iaa & Ic & Ia) () -> "Iaa&Ic&Ia ").m() +
+ ((Ib & Ic) () -> "Ib&Ic").m();
+ }
}
diff --git a/jack/src/com/android/jack/api/impl/JackProviderImpl.java b/jack/src/com/android/jack/api/impl/JackProviderImpl.java
index 6e241e9..1192187 100644
--- a/jack/src/com/android/jack/api/impl/JackProviderImpl.java
+++ b/jack/src/com/android/jack/api/impl/JackProviderImpl.java
@@ -31,9 +31,9 @@
import com.android.jack.api.v02.impl.Api02Feature;
import com.android.jack.api.v03.Api03Config;
import com.android.jack.api.v03.impl.Api03Feature;
+import com.android.jack.api.v04.Api04Config;
import com.android.jack.api.v04.impl.Api04ConfigImpl;
import com.android.jack.api.v04.impl.Api04Feature;
-import com.android.jack.api.v04c.Api04CandidateConfig;
import com.android.jack.management.CleanCodeRequest;
import com.android.jack.management.CleanDiskRequest;
import com.android.jack.management.CleanMemoryRequest;
@@ -63,13 +63,13 @@
impl.put(Api01Config.class, Api04ConfigImpl.class);
impl.put(Api02Config.class, Api04ConfigImpl.class);
impl.put(Api03Config.class, Api04ConfigImpl.class);
- impl.put(Api04CandidateConfig.class, Api04ConfigImpl.class);
+ impl.put(Api04Config.class, Api04ConfigImpl.class);
impl.put(Cli01Config.class, Cli01ConfigImpl.class);
features.put(Api01Config.class, Api01Feature.class);
features.put(Api02Config.class, Api02Feature.class);
features.put(Api03Config.class, Api03Feature.class);
- features.put(Api04CandidateConfig.class, Api04Feature.class);
+ features.put(Api04Config.class, Api04Feature.class);
features.put(Cli01Config.class, Api04Feature.class);
}
diff --git a/jack/src/com/android/jack/api/v03/impl/Api03ConfigImpl.java b/jack/src/com/android/jack/api/v03/impl/Api03ConfigImpl.java
index 4222b89..9b6ead1 100644
--- a/jack/src/com/android/jack/api/v03/impl/Api03ConfigImpl.java
+++ b/jack/src/com/android/jack/api/v03/impl/Api03ConfigImpl.java
@@ -22,7 +22,7 @@
import com.android.jack.api.v03.Api03Config;
import java.io.File;
-import java.util.Collection;
+import java.util.List;
import javax.annotation.Nonnull;
@@ -35,12 +35,12 @@
}
@Override
- public void setPluginPath(@Nonnull Collection<File> pluginPath) {
+ public void setPluginPath(@Nonnull List<File> pluginPath) {
options.setPluginPath(Joiner.on(File.pathSeparator).join(pluginPath));
}
@Override
- public void setPluginNames(@Nonnull Collection<String> pluginNames) {
+ public void setPluginNames(@Nonnull List<String> pluginNames) {
options.setPluginNames(Joiner.on(',').join(pluginNames));
}
}
diff --git a/jack/src/com/android/jack/api/v04/impl/Api04ConfigImpl.java b/jack/src/com/android/jack/api/v04/impl/Api04ConfigImpl.java
index c4ec09c..48d4a45 100644
--- a/jack/src/com/android/jack/api/v04/impl/Api04ConfigImpl.java
+++ b/jack/src/com/android/jack/api/v04/impl/Api04ConfigImpl.java
@@ -17,8 +17,8 @@
package com.android.jack.api.v04.impl;
import com.android.jack.api.v03.impl.Api03ConfigImpl;
-import com.android.jack.api.v04c.Api04CandidateConfig;
-import com.android.jack.api.v04c.HasCharset;
+import com.android.jack.api.v04.Api04Config;
+import com.android.jack.api.v04.HasCharset;
import java.io.File;
import java.nio.charset.Charset;
@@ -31,7 +31,7 @@
/**
* A configuration implementation for API level 04 of the Jack compiler.
*/
-public class Api04ConfigImpl extends Api03ConfigImpl implements Api04CandidateConfig {
+public class Api04ConfigImpl extends Api03ConfigImpl implements Api04Config {
public Api04ConfigImpl() {
super();
}
diff --git a/jack/src/com/android/jack/transformations/lambda/LambdaCollection.java b/jack/src/com/android/jack/transformations/lambda/LambdaCollection.java
index d09beb1..381585f 100644
--- a/jack/src/com/android/jack/transformations/lambda/LambdaCollection.java
+++ b/jack/src/com/android/jack/transformations/lambda/LambdaCollection.java
@@ -158,8 +158,8 @@
private Key createKey(@Nonnull String lambdaId, @Nonnull JLambda lambda,
@Nonnull JDefinedClassOrInterface currentType) {
- String interfaceSignatureId =
- mergeInterfaces ? "" : LambdaInterfaceSignature.forLambda(lambda).getUniqueId();
+ String interfaceSignatureId = mergeInterfaces ? "" :
+ LambdaInterfaceSignature.forLambda(lambda, /* normalize = */ false).getUniqueId();
String scopeId;
switch (groupingScope) {
diff --git a/jack/src/com/android/jack/transformations/lambda/LambdaGroupClassFinalizer.java b/jack/src/com/android/jack/transformations/lambda/LambdaGroupClassFinalizer.java
index fa6521b..3b70569 100644
--- a/jack/src/com/android/jack/transformations/lambda/LambdaGroupClassFinalizer.java
+++ b/jack/src/com/android/jack/transformations/lambda/LambdaGroupClassFinalizer.java
@@ -102,6 +102,8 @@
private final boolean simplifyStateless =
ThreadConfig.get(Options.LAMBDA_SIMPLIFY_STATELESS).booleanValue();
+ private final boolean mergeInterfaces =
+ ThreadConfig.get(Options.LAMBDA_MERGE_INTERFACES).booleanValue();
@Nonnull
private final JPhantomLookup phantomLookup =
Jack.getSession().getPhantomLookup();
@@ -272,9 +274,7 @@
JDefinedClass groupClass = this.group.getGroupClass();
// Add implements clause
- List<JInterface> interfaces =
- LambdaInterfaceSignature.normalizeInterfaces(this.group.getLambdas());
- for (JInterface inter : interfaces) {
+ for (JInterface inter : getInterfaces()) {
groupClass.addImplements(inter);
}
@@ -312,6 +312,20 @@
request.commit();
}
+ @Nonnull
+ private List<JInterface> getInterfaces() {
+ List<JLambda> lambdas = this.group.getLambdas();
+ if (mergeInterfaces) {
+ return LambdaInterfaceSignature.normalizeInterfaces(lambdas);
+ }
+
+ // If there is no interface merging, we use non-normalized interface signature
+ // which means that all the lambdas in the group should have the same
+ // set and order of the interfaces, so we just take them from the first one.
+ assert lambdas.size() > 0;
+ return LambdaInterfaceSignature.extractOrderedInterfaces(lambdas.get(0));
+ }
+
/**
* Create a static constructor of the lambda group class in a form:
* <pre>
diff --git a/jack/src/com/android/jack/transformations/lambda/LambdaInterfaceSignature.java b/jack/src/com/android/jack/transformations/lambda/LambdaInterfaceSignature.java
index b959978..6e24e9b 100644
--- a/jack/src/com/android/jack/transformations/lambda/LambdaInterfaceSignature.java
+++ b/jack/src/com/android/jack/transformations/lambda/LambdaInterfaceSignature.java
@@ -36,6 +36,28 @@
* by a particular lambda class, i.e. essentially the transitive closure of the
* interfaces the class explicitly specifies in its 'implements' clause.
*
+ * Interface signature can be normalized or not. If it is normalized, it represents
+ * interfaces in a way, when order and set of interfaces 'directly' implemented
+ * by the lambda does not make difference, like in the example below. If the signature
+ * is not normalized, the set and order of 'directly' implemented interfaces matter.
+ *
+ * <pre>
+ * interface A {}
+ * interface B extends A {}
+ * interface C { void m(); }
+ *
+ * class Foo {
+ * void bar() {
+ * ((C & A & B) () -> {}).m();
+ * ((C & B & A) () -> {}).m();
+ * ((C & B) () -> {}).m();
+ * }
+ * }
+ * </pre>
+ *
+ * In the example above, normalized interface signature of these three
+ * lambdas will be the same, but not normalized signature will be different.
+ *
* NOTE: interface signature is used for hashing and sorting purposes only, it is
* not intended to actually store the exact set of the interfaces.
*/
@@ -51,19 +73,25 @@
@Nonnull
private final String allInterfaces;
- private LambdaInterfaceSignature(@Nonnull JLambda lambda) {
+ private LambdaInterfaceSignature(@Nonnull JLambda lambda, boolean normalize) {
StringBuilder sb = new StringBuilder();
- List<JInterface> interfaces = new ArrayList<>(lambda.getInterfaceBounds());
- interfaces.add(lambda.getType());
- for (String key : getNormalizedInterfacesMap(interfaces).keySet()) {
- sb.append(key);
+ List<JInterface> interfaces = extractOrderedInterfaces(lambda);
+ if (normalize) {
+ for (String key : getNormalizedInterfacesMap(interfaces).keySet()) {
+ sb.append(key);
+ }
+ } else {
+ for (JInterface inter : interfaces) {
+ sb.append(FORMATTER.getName(inter));
+ }
}
allInterfaces = sb.toString();
}
/** create an interface signature for a given lambda */
- static LambdaInterfaceSignature forLambda(@Nonnull JLambda lambda) {
- return new LambdaInterfaceSignature(lambda);
+ @Nonnull
+ static LambdaInterfaceSignature forLambda(@Nonnull JLambda lambda, boolean normalize) {
+ return new LambdaInterfaceSignature(lambda, normalize);
}
/** A short id that can be used to uniquely identify and sort interface signatures */
@@ -73,6 +101,23 @@
}
/**
+ * Extracts interfaces from lambda in the order they should be present
+ * in the implementation class.
+ */
+ @Nonnull
+ static List<JInterface> extractOrderedInterfaces(@Nonnull JLambda lambda) {
+ ArrayList<JInterface> interfaces = new ArrayList<>();
+ JInterface mainInterface = lambda.getType();
+ interfaces.add(mainInterface);
+ for (JInterface bound : lambda.getInterfaceBounds()) {
+ if (!bound.isSameType(mainInterface)) {
+ interfaces.add(bound);
+ }
+ }
+ return interfaces;
+ }
+
+ /**
* Returns a normalized set of interfaces implemented by a given list of lambdas.
*
* We call a set of interfaces normalized if removing any of the interfaces from
@@ -88,8 +133,7 @@
static List<JInterface> normalizeInterfaces(@Nonnull List<JLambda> lambdas) {
ArrayList<JInterface> interfaces = new ArrayList<>();
for (JLambda lambda : lambdas) {
- interfaces.addAll(lambda.getInterfaceBounds());
- interfaces.add(lambda.getType());
+ interfaces.addAll(extractOrderedInterfaces(lambda));
}
return new ArrayList<>(getNormalizedInterfacesMap(interfaces).values());
}
diff --git a/jill/src/com/android/jill/frontend/java/MethodBodyWriter.java b/jill/src/com/android/jill/frontend/java/MethodBodyWriter.java
index 7410744..cf109c1 100644
--- a/jill/src/com/android/jill/frontend/java/MethodBodyWriter.java
+++ b/jill/src/com/android/jill/frontend/java/MethodBodyWriter.java
@@ -2058,40 +2058,63 @@
// be use to known the type of variable to read and nextFrame must be use to known the type
// of variable to write.
Variable tmpVar = getTempVarFromTopOfStackMinus1(frame);
+ boolean topMinus1IsVirtual = isVirtualStackVariable(frame, TOP_OF_STACK - 1);
+ boolean topIsVirtual = isVirtualStackVariable(frame, TOP_OF_STACK);
- // tmpVar = frame.stack[frame.stack.size() + TOP_OF_STACK - 1]
- writeDebugBegin(currentClass, currentLine);
- writer.writeCatchBlockIds(currentCatchList);
- writer.writeKeyword(Token.EXPRESSION_STATEMENT);
- writer.writeOpen();
- writeDebugBegin(currentClass, currentLine);
- writer.writeKeyword(Token.ASG_OPERATION);
- writer.writeOpen();
- writeLocalRef(tmpVar);
- writeStackAccess(frame, TOP_OF_STACK - 1);
- writeDebugEnd(currentClass, currentLine);
- writer.writeClose();
- writeDebugEnd(currentClass, currentLine);
- writer.writeClose();
+ if (topMinus1IsVirtual) {
+ // Virtual swap, stack variables will be transform as below:
+ // var_stk_top = value_stk_top; var_stk_top-1 is virtual
+ // =>
+ // var_stk_top is virtual, var_stk_top-1 = value_stk_top
+ cmpOperands.put(getStackVariable(nextFrame, TOP_OF_STACK),
+ cmpOperands.remove(getStackVariable(frame, TOP_OF_STACK - 1)));
+ } else {
+ // tmpVar = frame.stack[frame.stack.size() + TOP_OF_STACK - 1]
+ writeDebugBegin(currentClass, currentLine);
+ writer.writeCatchBlockIds(currentCatchList);
+ writer.writeKeyword(Token.EXPRESSION_STATEMENT);
+ writer.writeOpen();
+ writeDebugBegin(currentClass, currentLine);
+ writer.writeKeyword(Token.ASG_OPERATION);
+ writer.writeOpen();
+ writeLocalRef(tmpVar);
+ writeStackAccess(frame, TOP_OF_STACK - 1);
+ writeDebugEnd(currentClass, currentLine);
+ writer.writeClose();
+ writeDebugEnd(currentClass, currentLine);
+ writer.writeClose();
+ }
- // nexFrame.stack[nexFrame.stack.size() + TOP_OF_STACK - 1] =
- // frame.stack[frame.stack.size() + TOP_OF_STACK]
- writeAssign(frame, TOP_OF_STACK, nextFrame, TOP_OF_STACK - 1);
+ if (topIsVirtual) {
+ // Virtual swap, stack variables will be transform as below:
+ // var_stk_top is virtual; var_stk_top-1 = value_stk_top-1
+ // =>
+ // var_stk_top = value_stk_top-1, var_stk_top-1 is virtual
+ cmpOperands.put(getStackVariable(nextFrame, TOP_OF_STACK - 1),
+ cmpOperands.remove(getStackVariable(frame, TOP_OF_STACK)));
+ } else {
+ // nexFrame.stack[nexFrame.stack.size() + TOP_OF_STACK - 1] =
+ // frame.stack[frame.stack.size() + TOP_OF_STACK]
+ writeAssign(frame, TOP_OF_STACK, nextFrame, TOP_OF_STACK - 1);
+ }
- // nextFrame.stack[nextFrame.stack.size() + TOP_OF_STACK] = tmpVar
- writeDebugBegin(currentClass, currentLine);
- writer.writeCatchBlockIds(currentCatchList);
- writer.writeKeyword(Token.EXPRESSION_STATEMENT);
- writer.writeOpen();
- writeDebugBegin(currentClass, currentLine);
- writer.writeKeyword(Token.ASG_OPERATION);
- writer.writeOpen();
- writeStackAccess(nextFrame, TOP_OF_STACK);
- writeLocalRef(tmpVar);
- writeDebugEnd(currentClass, currentLine);
- writer.writeClose();
- writeDebugEnd(currentClass, currentLine);
- writer.writeClose();
+ // No need to assign the variable (nextFrame, top_of_stack) because it is virtual variable
+ if (!topMinus1IsVirtual) {
+ // nextFrame.stack[nextFrame.stack.size() + TOP_OF_STACK] = tmpVar
+ writeDebugBegin(currentClass, currentLine);
+ writer.writeCatchBlockIds(currentCatchList);
+ writer.writeKeyword(Token.EXPRESSION_STATEMENT);
+ writer.writeOpen();
+ writeDebugBegin(currentClass, currentLine);
+ writer.writeKeyword(Token.ASG_OPERATION);
+ writer.writeOpen();
+ writeStackAccess(nextFrame, TOP_OF_STACK);
+ writeLocalRef(tmpVar);
+ writeDebugEnd(currentClass, currentLine);
+ writer.writeClose();
+ writeDebugEnd(currentClass, currentLine);
+ writer.writeClose();
+ }
break;
}
case DUP: {
@@ -2195,6 +2218,11 @@
}
}
+ private boolean isVirtualStackVariable(@Nonnull Frame<BasicValue> frame, int stackIdx) {
+ Variable stackVar = getStackVariable(frame, stackIdx);
+ return cmpOperands.containsKey(stackVar);
+ }
+
private void writeInsn(@Nonnull Frame<BasicValue> nextFrame, @Nonnull LdcInsnNode ldcInsn)
throws IOException {
writeDebugBegin(currentClass, currentLine);