summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/004-JniTest/src/Main.java2
-rw-r--r--test/004-ReferenceMap/stack_walk_refmap_jni.cc10
-rw-r--r--test/079-phantom/src/Bitmap.java5
-rw-r--r--test/088-monitor-verification/smali/NullLocks.smali28
-rw-r--r--test/088-monitor-verification/src/Main.java45
-rw-r--r--test/088-monitor-verification/src/TwoPath.java53
-rw-r--r--test/131-structural-change/expected.txt1
-rw-r--r--test/131-structural-change/src/Main.java6
-rw-r--r--test/141-class-unload/expected.txt1
-rw-r--r--test/141-class-unload/src/Main.java24
-rw-r--r--test/454-get-vreg/get_vreg_jni.cc17
-rw-r--r--test/457-regs/regs_jni.cc5
-rw-r--r--test/466-get-live-vreg/get_live_vreg_jni.cc3
-rw-r--r--test/529-checker-unresolved/expected.txt2
-rw-r--r--test/529-checker-unresolved/src/Main.java16
-rw-r--r--test/529-checker-unresolved/src/Unresolved.java10
-rw-r--r--test/536-checker-intrinsic-optimization/expected.txt0
-rw-r--r--test/536-checker-intrinsic-optimization/info.txt0
-rw-r--r--test/536-checker-intrinsic-optimization/src/Main.java71
-rw-r--r--test/536-checker-needs-access-check/expected.txt4
-rw-r--r--test/536-checker-needs-access-check/info.txt1
-rw-r--r--test/536-checker-needs-access-check/src/Main.java82
-rw-r--r--test/536-checker-needs-access-check/src/other/InaccessibleClass.java20
-rw-r--r--test/536-checker-needs-access-check/src/other/InaccessibleClassProxy.java23
-rw-r--r--test/536-checker-needs-access-check/src2/other/InaccessibleClass.java20
-rw-r--r--test/536-checker-needs-access-check/src2/other/InaccessibleClassProxy.java23
-rw-r--r--test/537-checker-arraycopy/expected.txt0
-rw-r--r--test/537-checker-arraycopy/info.txt1
-rw-r--r--test/537-checker-arraycopy/src/Main.java71
-rw-r--r--test/537-checker-debuggable/expected.txt0
-rw-r--r--test/537-checker-debuggable/info.txt1
-rw-r--r--test/537-checker-debuggable/smali/TestCase.smali42
-rw-r--r--test/537-checker-debuggable/src/Main.java23
-rw-r--r--test/537-checker-inline-and-unverified/expected.txt0
-rw-r--r--test/537-checker-inline-and-unverified/info.txt1
-rw-r--r--test/537-checker-inline-and-unverified/src/Main.java59
-rw-r--r--test/537-checker-inline-and-unverified/src/other/InaccessibleClass.java20
-rw-r--r--test/537-checker-inline-and-unverified/src2/other/InaccessibleClass.java20
-rw-r--r--test/538-checker-embed-constants/expected.txt0
-rw-r--r--test/538-checker-embed-constants/info.txt1
-rw-r--r--test/538-checker-embed-constants/src/Main.java290
-rw-r--r--test/539-checker-arm64-encodable-immediates/expected.txt0
-rw-r--r--test/539-checker-arm64-encodable-immediates/info.txt2
-rw-r--r--test/539-checker-arm64-encodable-immediates/src/Main.java52
-rw-r--r--test/540-checker-rtp-bug/expected.txt1
-rw-r--r--test/540-checker-rtp-bug/info.txt1
-rw-r--r--test/540-checker-rtp-bug/src/Main.java102
-rwxr-xr-xtest/955-lambda-smali/run2
-rwxr-xr-xtest/960-default-smali/build33
-rw-r--r--test/960-default-smali/expected.txt84
-rw-r--r--test/960-default-smali/info.txt19
-rwxr-xr-xtest/960-default-smali/run21
-rw-r--r--test/960-default-smali/smali/A.smali38
-rw-r--r--test/960-default-smali/smali/Attendant.smali53
-rw-r--r--test/960-default-smali/smali/B.smali38
-rw-r--r--test/960-default-smali/smali/C.smali37
-rw-r--r--test/960-default-smali/smali/D.smali38
-rw-r--r--test/960-default-smali/smali/E.smali38
-rw-r--r--test/960-default-smali/smali/Extension.smali30
-rw-r--r--test/960-default-smali/smali/F.smali47
-rw-r--r--test/960-default-smali/smali/G.smali37
-rw-r--r--test/960-default-smali/smali/Greeter.smali40
-rw-r--r--test/960-default-smali/smali/Greeter2.smali39
-rw-r--r--test/960-default-smali/smali/Greeter3.smali40
-rw-r--r--test/960-default-smali/smali/H.smali28
-rw-r--r--test/960-default-smali/smali/I.smali28
-rw-r--r--test/960-default-smali/smali/J.smali29
-rw-r--r--test/960-default-smali/smali/classes.xml127
-rwxr-xr-xtest/960-default-smali/util-src/generate_smali.py376
-rwxr-xr-xtest/961-default-iface-resolution-generated/build47
-rw-r--r--test/961-default-iface-resolution-generated/expected.txt1
-rw-r--r--test/961-default-iface-resolution-generated/info.txt17
-rwxr-xr-xtest/961-default-iface-resolution-generated/run21
-rwxr-xr-xtest/961-default-iface-resolution-generated/util-src/generate_smali.py466
-rwxr-xr-xtest/962-iface-static/build30
-rw-r--r--test/962-iface-static/expected.txt3
-rw-r--r--test/962-iface-static/info.txt4
-rwxr-xr-xtest/962-iface-static/run21
-rw-r--r--test/962-iface-static/smali/Displayer.smali45
-rw-r--r--test/962-iface-static/smali/Main.smali40
-rw-r--r--test/962-iface-static/smali/iface.smali43
-rwxr-xr-xtest/963-default-range-smali/build30
-rw-r--r--test/963-default-range-smali/expected.txt2
-rw-r--r--test/963-default-range-smali/info.txt4
-rwxr-xr-xtest/963-default-range-smali/run21
-rw-r--r--test/963-default-range-smali/smali/A.smali29
-rw-r--r--test/963-default-range-smali/smali/Main.smali77
-rw-r--r--test/963-default-range-smali/smali/iface.smali40
-rwxr-xr-xtest/964-default-iface-init-generated/build45
-rw-r--r--test/964-default-iface-init-generated/expected.txt1
-rw-r--r--test/964-default-iface-init-generated/info.txt17
-rwxr-xr-xtest/964-default-iface-init-generated/run21
-rw-r--r--test/964-default-iface-init-generated/smali/Displayer.smali45
-rwxr-xr-xtest/964-default-iface-init-generated/util-src/generate_smali.py531
-rw-r--r--test/Android.run-test.mk34
-rwxr-xr-xtest/etc/default-build2
-rwxr-xr-xtest/run-all-tests5
-rwxr-xr-xtest/run-test32
-rw-r--r--test/utils/python/testgen/mixins.py135
-rw-r--r--test/utils/python/testgen/utils.py80
100 files changed, 4199 insertions, 71 deletions
diff --git a/test/004-JniTest/src/Main.java b/test/004-JniTest/src/Main.java
index dd88db0b7c..ee3a3b9830 100644
--- a/test/004-JniTest/src/Main.java
+++ b/test/004-JniTest/src/Main.java
@@ -120,7 +120,7 @@ public class Main {
private static void testRemoveLocalObject() {
removeLocalObject(new Object());
}
-
+
private static native short shortMethod(short s1, short s2, short s3, short s4, short s5, short s6, short s7,
short s8, short s9, short s10);
diff --git a/test/004-ReferenceMap/stack_walk_refmap_jni.cc b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
index 285df18c72..f8d321cbec 100644
--- a/test/004-ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/004-ReferenceMap/stack_walk_refmap_jni.cc
@@ -22,11 +22,11 @@ namespace art {
#define CHECK_REGS_CONTAIN_REFS(dex_pc, abort_if_not_found, ...) do { \
int t[] = {__VA_ARGS__}; \
int t_size = sizeof(t) / sizeof(*t); \
- uintptr_t native_quick_pc = m->ToNativeQuickPc(dex_pc, \
+ uintptr_t native_quick_pc = GetCurrentCode().ToNativeQuickPc(dex_pc, \
/* is_catch_handler */ false, \
abort_if_not_found); \
if (native_quick_pc != UINTPTR_MAX) { \
- CheckReferences(t, t_size, m->NativeQuickPcOffset(native_quick_pc)); \
+ CheckReferences(t, t_size, GetCurrentCode().NativeQuickPcOffset(native_quick_pc)); \
} \
} while (false);
@@ -49,7 +49,7 @@ struct ReferenceMap2Visitor : public CheckReferenceMapVisitor {
CHECK_REGS_CONTAIN_REFS(0x06U, true, 8, 1); // v8: this, v1: x
CHECK_REGS_CONTAIN_REFS(0x08U, true, 8, 3, 1); // v8: this, v3: y, v1: x
CHECK_REGS_CONTAIN_REFS(0x0cU, true, 8, 3, 1); // v8: this, v3: y, v1: x
- if (!m->IsOptimized(sizeof(void*))) {
+ if (!GetCurrentCode().IsOptimized(sizeof(void*))) {
CHECK_REGS_CONTAIN_REFS(0x0eU, true, 8, 3, 1); // v8: this, v3: y, v1: x
}
CHECK_REGS_CONTAIN_REFS(0x10U, true, 8, 3, 1); // v8: this, v3: y, v1: x
@@ -65,7 +65,7 @@ struct ReferenceMap2Visitor : public CheckReferenceMapVisitor {
// Note that v0: ex can be eliminated because it's a dead merge of two different exceptions.
CHECK_REGS_CONTAIN_REFS(0x18U, true, 8, 2, 1); // v8: this, v2: y, v1: x (dead v0: ex)
CHECK_REGS_CONTAIN_REFS(0x1aU, true, 8, 5, 2, 1); // v8: this, v5: x[1], v2: y, v1: x (dead v0: ex)
- if (!m->IsOptimized(sizeof(void*))) {
+ if (!GetCurrentCode().IsOptimized(sizeof(void*))) {
// v8: this, v5: x[1], v2: y, v1: x (dead v0: ex)
CHECK_REGS_CONTAIN_REFS(0x1dU, true, 8, 5, 2, 1);
// v5 is removed from the root set because there is a "merge" operation.
@@ -74,7 +74,7 @@ struct ReferenceMap2Visitor : public CheckReferenceMapVisitor {
}
CHECK_REGS_CONTAIN_REFS(0x21U, true, 8, 2, 1); // v8: this, v2: y, v1: x (dead v0: ex)
- if (!m->IsOptimized(sizeof(void*))) {
+ if (!GetCurrentCode().IsOptimized(sizeof(void*))) {
CHECK_REGS_CONTAIN_REFS(0x27U, true, 8, 4, 2, 1); // v8: this, v4: ex, v2: y, v1: x
}
CHECK_REGS_CONTAIN_REFS(0x29U, true, 8, 4, 2, 1); // v8: this, v4: ex, v2: y, v1: x
diff --git a/test/079-phantom/src/Bitmap.java b/test/079-phantom/src/Bitmap.java
index 85eb3ccb97..ff43749e76 100644
--- a/test/079-phantom/src/Bitmap.java
+++ b/test/079-phantom/src/Bitmap.java
@@ -125,7 +125,6 @@ class PhantomWrapper extends PhantomReference {
*/
class BitmapWatcher extends Thread {
ReferenceQueue<PhantomWrapper> mQueue;
- volatile boolean mQuit = false;
BitmapWatcher(ReferenceQueue<PhantomWrapper> queue) {
mQueue = queue;
@@ -133,7 +132,7 @@ class BitmapWatcher extends Thread {
}
public void run() {
- while (!mQuit) {
+ while (true) {
try {
PhantomWrapper ref = (PhantomWrapper) mQueue.remove();
//System.out.println("dequeued ref " + ref.mNativeData +
@@ -142,12 +141,12 @@ class BitmapWatcher extends Thread {
//ref.clear();
} catch (InterruptedException ie) {
System.out.println("intr");
+ break;
}
}
}
public void shutDown() {
- mQuit = true;
interrupt();
}
}
diff --git a/test/088-monitor-verification/smali/NullLocks.smali b/test/088-monitor-verification/smali/NullLocks.smali
new file mode 100644
index 0000000000..8262f19e22
--- /dev/null
+++ b/test/088-monitor-verification/smali/NullLocks.smali
@@ -0,0 +1,28 @@
+.class public LNullLocks;
+
+.super Ljava/lang/Object;
+
+.method public static run(Z)V
+ .registers 3
+
+ invoke-static {}, LMain;->assertIsManaged()V
+
+ if-eqz v2, :Lfalse
+
+ const v0, 0 # Null.
+ monitor-enter v0
+ const v1, 0 # Another null. This should be detected as an alias, such that the exit
+ # will not fail verification.
+ monitor-exit v1
+
+ monitor-enter v0
+ monitor-exit v1
+
+ monitor-enter v1
+ monitor-exit v0
+
+:Lfalse
+
+ return-void
+
+.end method
diff --git a/test/088-monitor-verification/src/Main.java b/test/088-monitor-verification/src/Main.java
index 218805543e..212c894bd5 100644
--- a/test/088-monitor-verification/src/Main.java
+++ b/test/088-monitor-verification/src/Main.java
@@ -27,6 +27,13 @@ public class Main {
*/
public static void main(String[] args) {
System.loadLibrary(args[0]);
+ if (!hasOatFile() || runtimeIsSoftFail() || isInterpreted()) {
+ // Some tests ensure that the verifier was able to guarantee balanced locking by
+ // asserting that the test function is running as compiled code. But skip this now,
+ // as this seems to be a non-compiled code test configuration.
+ disableStackFrameAsserts();
+ }
+
Main m = new Main();
m.recursiveSync(0);
@@ -49,7 +56,7 @@ public class Main {
Object obj1 = new Object();
Object obj2 = new Object();
- m.twoPath(obj1, obj2, 0);
+ TwoPath.twoPath(obj1, obj2, 0);
System.out.println("twoPath ok");
m.triplet(obj1, obj2, 0);
@@ -62,6 +69,7 @@ public class Main {
* Recursive synchronized method.
*/
synchronized void recursiveSync(int iter) {
+ assertIsManaged();
if (iter < 40) {
recursiveSync(iter+1);
} else {
@@ -73,6 +81,7 @@ public class Main {
* Tests simple nesting, with and without a throw.
*/
void nestedMayThrow(boolean doThrow) {
+ assertIsManaged();
synchronized (this) {
synchronized (Main.class) {
synchronized (new Object()) {
@@ -90,6 +99,7 @@ public class Main {
* Exercises bug 3215458.
*/
void constantLock() {
+ assertIsManaged();
Class thing = Thread.class;
synchronized (Thread.class) {}
}
@@ -98,6 +108,7 @@ public class Main {
* Confirms that we can have 32 nested monitors on one method.
*/
void notExcessiveNesting() {
+ assertIsManaged();
synchronized (this) { // 1
synchronized (this) { // 2
synchronized (this) { // 3
@@ -138,6 +149,7 @@ public class Main {
* method.
*/
void notNested() {
+ assertIsManaged();
synchronized (this) {} // 1
synchronized (this) {} // 2
synchronized (this) {} // 3
@@ -178,25 +190,6 @@ public class Main {
private void doNothing(Object obj) {}
/**
- * Conditionally uses one of the synchronized objects.
- */
- public void twoPath(Object obj1, Object obj2, int x) {
- Object localObj;
-
- synchronized (obj1) {
- synchronized(obj2) {
- if (x == 0) {
- localObj = obj2;
- } else {
- localObj = obj1;
- }
- }
- }
-
- doNothing(localObj);
- }
-
- /**
* Lock the monitor two or three times, and make use of the locked or
* unlocked object.
*/
@@ -220,19 +213,16 @@ public class Main {
// Smali testing code.
private static void runSmaliTests() {
- if (!hasOatFile() || runtimeIsSoftFail() || isInterpreted()) {
- // Skip test, this seems to be a non-compiled code test configuration.
- return;
- }
-
runTest("OK", new Object[] { new Object(), new Object() }, null);
runTest("TooDeep", new Object[] { new Object() }, null);
runTest("NotStructuredOverUnlock", new Object[] { new Object() },
IllegalMonitorStateException.class);
- runTest("NotStructuredUnderUnlock", new Object[] { new Object() }, null);
- // TODO: new IllegalMonitorStateException());
+ runTest("NotStructuredUnderUnlock", new Object[] { new Object() },
+ IllegalMonitorStateException.class);
runTest("UnbalancedJoin", new Object[] { new Object(), new Object() }, null);
runTest("UnbalancedStraight", new Object[] { new Object(), new Object() }, null);
+ runTest("NullLocks", new Object[] { false }, null);
+ runTest("NullLocks", new Object[] { true }, NullPointerException.class);
}
private static void runTest(String className, Object[] parameters, Class<?> excType) {
@@ -282,4 +272,5 @@ public class Main {
public static native boolean hasOatFile();
public static native boolean runtimeIsSoftFail();
public static native boolean isInterpreted();
+ public static native void disableStackFrameAsserts();
}
diff --git a/test/088-monitor-verification/src/TwoPath.java b/test/088-monitor-verification/src/TwoPath.java
new file mode 100644
index 0000000000..bdc15ad82e
--- /dev/null
+++ b/test/088-monitor-verification/src/TwoPath.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/*
+ * Test case for conditionally using one of two synchronized objects.
+ *
+ * This code cannot be verified at the moment, as the join point merges a register with two
+ * different lock options. Do not put it into Main to avoid the whole class being run in the
+ * interpreter.
+ */
+public class TwoPath {
+
+ /**
+ * Conditionally uses one of the synchronized objects.
+ */
+ public static void twoPath(Object obj1, Object obj2, int x) {
+ Main.assertIsManaged();
+
+ Object localObj;
+
+ synchronized (obj1) {
+ synchronized(obj2) {
+ if (x == 0) {
+ localObj = obj2;
+ } else {
+ localObj = obj1;
+ }
+ }
+ }
+
+ doNothing(localObj);
+ }
+
+ private static void doNothing(Object o) {
+ }
+}
diff --git a/test/131-structural-change/expected.txt b/test/131-structural-change/expected.txt
index cc7713d252..1d19278f1e 100644
--- a/test/131-structural-change/expected.txt
+++ b/test/131-structural-change/expected.txt
@@ -1,2 +1,3 @@
+JNI_OnLoad called
Should really reach here.
Done.
diff --git a/test/131-structural-change/src/Main.java b/test/131-structural-change/src/Main.java
index 6cbbd12387..c7488992df 100644
--- a/test/131-structural-change/src/Main.java
+++ b/test/131-structural-change/src/Main.java
@@ -35,7 +35,7 @@ public class Main {
e.printStackTrace(System.out);
}
- boolean haveOatFile = hasOat();
+ boolean haveOatFile = hasOatFile();
boolean gotError = false;
try {
Class<?> bClass = getClass().getClassLoader().loadClass("B");
@@ -45,10 +45,10 @@ public class Main {
e.printStackTrace(System.out);
}
if (haveOatFile ^ gotError) {
- System.out.println("Did not get expected error.");
+ System.out.println("Did not get expected error. " + haveOatFile + " " + gotError);
}
System.out.println("Done.");
}
- private native static boolean hasOat();
+ private native static boolean hasOatFile();
}
diff --git a/test/141-class-unload/expected.txt b/test/141-class-unload/expected.txt
index 53d7abecaf..11de660c43 100644
--- a/test/141-class-unload/expected.txt
+++ b/test/141-class-unload/expected.txt
@@ -21,3 +21,4 @@ null
JNI_OnLoad called
class null false test
JNI_OnUnload called
+Number of loaded unload-ex maps 0
diff --git a/test/141-class-unload/src/Main.java b/test/141-class-unload/src/Main.java
index 3cc43accbe..0640b364c9 100644
--- a/test/141-class-unload/src/Main.java
+++ b/test/141-class-unload/src/Main.java
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
@@ -43,11 +46,28 @@ public class Main {
testStackTrace(constructor);
// Stress test to make sure we dont leak memory.
stressTest(constructor);
+ // Test that the oat files are unloaded.
+ testOatFilesUnloaded(getPid());
} catch (Exception e) {
System.out.println(e);
}
}
+ private static void testOatFilesUnloaded(int pid) throws Exception {
+ BufferedReader reader = new BufferedReader(new FileReader ("/proc/" + pid + "/maps"));
+ String line;
+ int count = 0;
+ Runtime.getRuntime().gc();
+ System.runFinalization();
+ while ((line = reader.readLine()) != null) {
+ if (line.contains("@141-class-unload-ex.jar")) {
+ System.out.println(line);
+ ++count;
+ }
+ }
+ System.out.println("Number of loaded unload-ex maps " + count);
+ }
+
private static void stressTest(Constructor constructor) throws Exception {
for (int i = 0; i <= 100; ++i) {
setUpUnloadLoader(constructor, false);
@@ -163,4 +183,8 @@ public class Main {
loadLibrary.invoke(intHolder, nativeLibraryName);
return new WeakReference(loader);
}
+
+ private static int getPid() throws Exception {
+ return Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
+ }
}
diff --git a/test/454-get-vreg/get_vreg_jni.cc b/test/454-get-vreg/get_vreg_jni.cc
index 9facfdb076..0ee2ff9fda 100644
--- a/test/454-get-vreg/get_vreg_jni.cc
+++ b/test/454-get-vreg/get_vreg_jni.cc
@@ -15,6 +15,7 @@
*/
#include "arch/context.h"
+#include "art_code.h"
#include "art_method-inl.h"
#include "jni.h"
#include "scoped_thread_state_change.h"
@@ -45,10 +46,14 @@ class TestVisitor : public StackVisitor {
CHECK_EQ(value, 42u);
bool success = GetVReg(m, 1, kIntVReg, &value);
- if (m->IsOptimized(sizeof(void*))) CHECK(!success);
+ if (!IsCurrentFrameInInterpreter() && GetCurrentCode().IsOptimized(sizeof(void*))) {
+ CHECK(!success);
+ }
success = GetVReg(m, 2, kIntVReg, &value);
- if (m->IsOptimized(sizeof(void*))) CHECK(!success);
+ if (!IsCurrentFrameInInterpreter() && GetCurrentCode().IsOptimized(sizeof(void*))) {
+ CHECK(!success);
+ }
CHECK(GetVReg(m, 3, kReferenceVReg, &value));
CHECK_EQ(reinterpret_cast<mirror::Object*>(value), this_value_);
@@ -78,10 +83,14 @@ class TestVisitor : public StackVisitor {
CHECK_EQ(value, 42u);
bool success = GetVRegPair(m, 2, kLongLoVReg, kLongHiVReg, &value);
- if (m->IsOptimized(sizeof(void*))) CHECK(!success);
+ if (!IsCurrentFrameInInterpreter() && GetCurrentCode().IsOptimized(sizeof(void*))) {
+ CHECK(!success);
+ }
success = GetVRegPair(m, 4, kLongLoVReg, kLongHiVReg, &value);
- if (m->IsOptimized(sizeof(void*))) CHECK(!success);
+ if (!IsCurrentFrameInInterpreter() && GetCurrentCode().IsOptimized(sizeof(void*))) {
+ CHECK(!success);
+ }
uint32_t value32 = 0;
CHECK(GetVReg(m, 6, kReferenceVReg, &value32));
diff --git a/test/457-regs/regs_jni.cc b/test/457-regs/regs_jni.cc
index c21168b81e..6fcebdb8b5 100644
--- a/test/457-regs/regs_jni.cc
+++ b/test/457-regs/regs_jni.cc
@@ -15,6 +15,7 @@
*/
#include "arch/context.h"
+#include "art_code.h"
#include "art_method-inl.h"
#include "jni.h"
#include "scoped_thread_state_change.h"
@@ -63,7 +64,9 @@ class TestVisitor : public StackVisitor {
CHECK_EQ(value, 1u);
bool success = GetVReg(m, 2, kIntVReg, &value);
- if (m->IsOptimized(sizeof(void*))) CHECK(!success);
+ if (!IsCurrentFrameInInterpreter() && GetCurrentCode().IsOptimized(sizeof(void*))) {
+ CHECK(!success);
+ }
CHECK(GetVReg(m, 3, kReferenceVReg, &value));
CHECK_EQ(value, 1u);
diff --git a/test/466-get-live-vreg/get_live_vreg_jni.cc b/test/466-get-live-vreg/get_live_vreg_jni.cc
index 7e9a583faf..2a56a7fce7 100644
--- a/test/466-get-live-vreg/get_live_vreg_jni.cc
+++ b/test/466-get-live-vreg/get_live_vreg_jni.cc
@@ -15,6 +15,7 @@
*/
#include "arch/context.h"
+#include "art_code.h"
#include "art_method-inl.h"
#include "jni.h"
#include "scoped_thread_state_change.h"
@@ -43,7 +44,7 @@ class TestVisitor : public StackVisitor {
found_method_ = true;
uint32_t value = 0;
if (GetCurrentQuickFrame() != nullptr &&
- m->IsOptimized(sizeof(void*)) &&
+ GetCurrentCode().IsOptimized(sizeof(void*)) &&
!Runtime::Current()->IsDebuggable()) {
CHECK_EQ(GetVReg(m, 0, kIntVReg, &value), false);
} else {
diff --git a/test/529-checker-unresolved/expected.txt b/test/529-checker-unresolved/expected.txt
index 358048c75b..1e7dbfed2e 100644
--- a/test/529-checker-unresolved/expected.txt
+++ b/test/529-checker-unresolved/expected.txt
@@ -3,3 +3,5 @@ UnresolvedClass.staticMethod()
UnresolvedClass.virtualMethod()
UnresolvedClass.interfaceMethod()
UnresolvedClass.superMethod()
+instanceof ok
+checkcast ok
diff --git a/test/529-checker-unresolved/src/Main.java b/test/529-checker-unresolved/src/Main.java
index adb5adae82..5219c04c37 100644
--- a/test/529-checker-unresolved/src/Main.java
+++ b/test/529-checker-unresolved/src/Main.java
@@ -114,16 +114,30 @@ public class Main extends UnresolvedSuperClass {
expectEquals(o, c.instanceObject);
}
+ static public void testInstanceOf(Object o) {
+ if (o instanceof UnresolvedSuperClass) {
+ System.out.println("instanceof ok");
+ }
+ }
+
+ static public UnresolvedSuperClass testCheckCast(Object o) {
+ UnresolvedSuperClass c = (UnresolvedSuperClass) o;
+ System.out.println("checkcast ok");
+ return c;
+ }
/// CHECK-START: void Main.main(java.lang.String[]) register (before)
/// CHECK: InvokeUnresolved invoke_type:direct
static public void main(String[] args) {
UnresolvedClass c = new UnresolvedClass();
+ Main m = new Main();
callInvokeUnresolvedStatic();
callInvokeUnresolvedVirtual(c);
callInvokeUnresolvedInterface(c);
- callInvokeUnresolvedSuper(new Main());
+ callInvokeUnresolvedSuper(m);
callUnresolvedStaticFieldAccess();
callUnresolvedInstanceFieldAccess(c);
+ testInstanceOf(m);
+ testCheckCast(m);
}
public static void expectEquals(byte expected, byte result) {
diff --git a/test/529-checker-unresolved/src/Unresolved.java b/test/529-checker-unresolved/src/Unresolved.java
index 03ceb6857b..20ac6e0b89 100644
--- a/test/529-checker-unresolved/src/Unresolved.java
+++ b/test/529-checker-unresolved/src/Unresolved.java
@@ -58,13 +58,3 @@ class UnresolvedClass extends UnresolvedSuperClass implements UnresolvedInterfac
public Object instanceObject;
}
-final class UnresolvedFinalClass {
- public void directMethod() {
- System.out.println("UnresolvedFinalClass.directMethod()");
- }
-}
-
-class UnresolvedAtRuntime {
- public void unresolvedAtRuntime() { }
-}
-
diff --git a/test/536-checker-intrinsic-optimization/expected.txt b/test/536-checker-intrinsic-optimization/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/536-checker-intrinsic-optimization/expected.txt
diff --git a/test/536-checker-intrinsic-optimization/info.txt b/test/536-checker-intrinsic-optimization/info.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/536-checker-intrinsic-optimization/info.txt
diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java
new file mode 100644
index 0000000000..1b784ae367
--- /dev/null
+++ b/test/536-checker-intrinsic-optimization/src/Main.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+
+public class Main {
+ public static void main(String[] args) {
+ stringEqualsSame();
+ stringArgumentNotNull("Foo");
+ }
+
+ /// CHECK-START: boolean Main.stringEqualsSame() instruction_simplifier (before)
+ /// CHECK: InvokeStaticOrDirect
+
+ /// CHECK-START: boolean Main.stringEqualsSame() register (before)
+ /// CHECK: <<Const1:i\d+>> IntConstant 1
+ /// CHECK: Return [<<Const1>>]
+
+ /// CHECK-START: boolean Main.stringEqualsSame() register (before)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ public static boolean stringEqualsSame() {
+ return $inline$callStringEquals("obj", "obj");
+ }
+
+ /// CHECK-START: boolean Main.stringEqualsNull() register (after)
+ /// CHECK: <<Invoke:z\d+>> InvokeStaticOrDirect
+ /// CHECK: Return [<<Invoke>>]
+ public static boolean stringEqualsNull() {
+ String o = (String)myObject;
+ return $inline$callStringEquals(o, o);
+ }
+
+ public static boolean $inline$callStringEquals(String a, String b) {
+ return a.equals(b);
+ }
+
+ /// CHECK-START-X86: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after)
+ /// CHECK: InvokeStaticOrDirect
+ /// CHECK-NOT: test
+ public static boolean stringArgumentNotNull(Object obj) {
+ obj.getClass();
+ return "foo".equals(obj);
+ }
+
+ // Test is very brittle as it depends on the order we emit instructions.
+ /// CHECK-START-X86: boolean Main.stringArgumentIsString() disassembly (after)
+ /// CHECK: InvokeStaticOrDirect
+ /// CHECK: test
+ /// CHECK: jz/eq
+ // Check that we don't try to compare the classes.
+ /// CHECK-NOT: mov
+ /// CHECK: cmp
+ public static boolean stringArgumentIsString() {
+ return "foo".equals(myString);
+ }
+
+ static String myString;
+ static Object myObject;
+}
diff --git a/test/536-checker-needs-access-check/expected.txt b/test/536-checker-needs-access-check/expected.txt
new file mode 100644
index 0000000000..4acae95b70
--- /dev/null
+++ b/test/536-checker-needs-access-check/expected.txt
@@ -0,0 +1,4 @@
+Got expected error instanceof
+Got expected error instanceof null
+Got expected error checkcast null
+Got expected error instanceof (keep LoadClass with access check)
diff --git a/test/536-checker-needs-access-check/info.txt b/test/536-checker-needs-access-check/info.txt
new file mode 100644
index 0000000000..3413cf3625
--- /dev/null
+++ b/test/536-checker-needs-access-check/info.txt
@@ -0,0 +1 @@
+Verifies that we don't remove type checks when we need to check for access rights.
diff --git a/test/536-checker-needs-access-check/src/Main.java b/test/536-checker-needs-access-check/src/Main.java
new file mode 100644
index 0000000000..7bd49c1c8c
--- /dev/null
+++ b/test/536-checker-needs-access-check/src/Main.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+import other.InaccessibleClass;
+import other.InaccessibleClassProxy;
+
+public class Main {
+ public static void main(String[] args) {
+ try {
+ testInstanceOf();
+ } catch (IllegalAccessError e) {
+ System.out.println("Got expected error instanceof");
+ }
+
+ try {
+ testInstanceOfNull();
+ } catch (IllegalAccessError e) {
+ System.out.println("Got expected error instanceof null");
+ }
+
+ try {
+ testCheckCastNull();
+ } catch (IllegalAccessError e) {
+ System.out.println("Got expected error checkcast null");
+ }
+
+ try {
+ testDontGvnLoadClassWithAccessChecks(new Object());
+ } catch (IllegalAccessError e) {
+ System.out.println("Got expected error instanceof (keep LoadClass with access check)");
+ }
+ }
+
+ /// CHECK-START: boolean Main.testInstanceOf() register (after)
+ /// CHECK: InstanceOf
+ public static boolean testInstanceOf() {
+ return ic instanceof InaccessibleClass;
+ }
+
+ /// CHECK-START: boolean Main.testInstanceOfNull() register (after)
+ /// CHECK: InstanceOf
+ public static boolean testInstanceOfNull() {
+ return null instanceof InaccessibleClass;
+ }
+
+ // TODO: write a test for for CheckCast with not null constant (after RTP can parse arguments).
+
+ /// CHECK-START: other.InaccessibleClass Main.testCheckCastNull() register (after)
+ /// CHECK: CheckCast
+ public static InaccessibleClass testCheckCastNull() {
+ return (InaccessibleClass) null;
+ }
+
+ /// CHECK-START: boolean Main.testDontGvnLoadClassWithAccessChecks(java.lang.Object) inliner (before)
+ /// CHECK: InvokeStaticOrDirect
+
+ /// CHECK-START: boolean Main.testDontGvnLoadClassWithAccessChecks(java.lang.Object) inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+
+ /// CHECK-START: boolean Main.testDontGvnLoadClassWithAccessChecks(java.lang.Object) GVN (after)
+ /// CHECK: LoadClass needs_access_check:false
+ /// CHECK: LoadClass needs_access_check:true
+ public static boolean testDontGvnLoadClassWithAccessChecks(Object o) {
+ InaccessibleClassProxy.test(o);
+ return ic instanceof InaccessibleClass;
+ }
+
+ public static InaccessibleClass ic;
+}
diff --git a/test/536-checker-needs-access-check/src/other/InaccessibleClass.java b/test/536-checker-needs-access-check/src/other/InaccessibleClass.java
new file mode 100644
index 0000000000..de2e1d7830
--- /dev/null
+++ b/test/536-checker-needs-access-check/src/other/InaccessibleClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 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 other;
+
+public class InaccessibleClass {
+}
diff --git a/test/536-checker-needs-access-check/src/other/InaccessibleClassProxy.java b/test/536-checker-needs-access-check/src/other/InaccessibleClassProxy.java
new file mode 100644
index 0000000000..4c005e4dfe
--- /dev/null
+++ b/test/536-checker-needs-access-check/src/other/InaccessibleClassProxy.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 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 other;
+
+public class InaccessibleClassProxy {
+ public static boolean test(Object o) {
+ return o instanceof InaccessibleClass;
+ }
+}
diff --git a/test/536-checker-needs-access-check/src2/other/InaccessibleClass.java b/test/536-checker-needs-access-check/src2/other/InaccessibleClass.java
new file mode 100644
index 0000000000..273226375e
--- /dev/null
+++ b/test/536-checker-needs-access-check/src2/other/InaccessibleClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 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 other;
+
+/*package*/ class InaccessibleClass {
+}
diff --git a/test/536-checker-needs-access-check/src2/other/InaccessibleClassProxy.java b/test/536-checker-needs-access-check/src2/other/InaccessibleClassProxy.java
new file mode 100644
index 0000000000..4c005e4dfe
--- /dev/null
+++ b/test/536-checker-needs-access-check/src2/other/InaccessibleClassProxy.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 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 other;
+
+public class InaccessibleClassProxy {
+ public static boolean test(Object o) {
+ return o instanceof InaccessibleClass;
+ }
+}
diff --git a/test/537-checker-arraycopy/expected.txt b/test/537-checker-arraycopy/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/537-checker-arraycopy/expected.txt
diff --git a/test/537-checker-arraycopy/info.txt b/test/537-checker-arraycopy/info.txt
new file mode 100644
index 0000000000..ea88f89306
--- /dev/null
+++ b/test/537-checker-arraycopy/info.txt
@@ -0,0 +1 @@
+Test for edge cases of System.arraycopy.
diff --git a/test/537-checker-arraycopy/src/Main.java b/test/537-checker-arraycopy/src/Main.java
new file mode 100644
index 0000000000..30ccc56b80
--- /dev/null
+++ b/test/537-checker-arraycopy/src/Main.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+
+public class Main {
+ public static void main(String[] args) {
+ arraycopy();
+ try {
+ arraycopy(new Object());
+ throw new Error("Should not be here");
+ } catch (ArrayStoreException ase) {
+ // Ignore.
+ }
+ try {
+ arraycopy(null);
+ throw new Error("Should not be here");
+ } catch (NullPointerException npe) {
+ // Ignore.
+ }
+
+ try {
+ arraycopy(new Object[1]);
+ throw new Error("Should not be here");
+ } catch (ArrayIndexOutOfBoundsException aiooe) {
+ // Ignore.
+ }
+
+ arraycopy(new Object[2]);
+ arraycopy(new Object[2], 0);
+
+ try {
+ arraycopy(new Object[1], 1);
+ throw new Error("Should not be here");
+ } catch (ArrayIndexOutOfBoundsException aiooe) {
+ // Ignore.
+ }
+ }
+
+ /// CHECK-START-X86_64: void Main.arraycopy() disassembly (after)
+ /// CHECK: InvokeStaticOrDirect
+ /// CHECK-NOT: test
+ /// CHECK-NOT: call
+ /// CHECK: ReturnVoid
+ // Checks that the call is intrinsified and that there is no test instruction
+ // when we know the source and destination are not null.
+ public static void arraycopy() {
+ Object[] obj = new Object[4];
+ System.arraycopy(obj, 1, obj, 0, 1);
+ }
+
+ public static void arraycopy(Object obj) {
+ System.arraycopy(obj, 1, obj, 0, 1);
+ }
+
+ public static void arraycopy(Object[] obj, int pos) {
+ System.arraycopy(obj, pos, obj, 0, obj.length);
+ }
+}
diff --git a/test/537-checker-debuggable/expected.txt b/test/537-checker-debuggable/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/537-checker-debuggable/expected.txt
diff --git a/test/537-checker-debuggable/info.txt b/test/537-checker-debuggable/info.txt
new file mode 100644
index 0000000000..25597d3f13
--- /dev/null
+++ b/test/537-checker-debuggable/info.txt
@@ -0,0 +1 @@
+Test that CHECK-START-DEBUGGABLE runs only on --debuggable code. \ No newline at end of file
diff --git a/test/537-checker-debuggable/smali/TestCase.smali b/test/537-checker-debuggable/smali/TestCase.smali
new file mode 100644
index 0000000000..8e6c7ef727
--- /dev/null
+++ b/test/537-checker-debuggable/smali/TestCase.smali
@@ -0,0 +1,42 @@
+# Copyright (C) 2015 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 LTestCase;
+
+.super Ljava/lang/Object;
+
+# The phi in this method has no actual uses but one environment use. It will
+# be eliminated in normal mode but kept live in debuggable mode. Test that
+# Checker runs the correct test for each compilation mode.
+
+## CHECK-START: int TestCase.deadPhi(int, int, int) ssa_builder (after)
+## CHECK-NOT: Phi
+
+## CHECK-START-DEBUGGABLE: int TestCase.deadPhi(int, int, int) ssa_builder (after)
+## CHECK: Phi
+
+.method public static deadPhi(III)I
+ .registers 8
+
+ move v0, p1
+ if-eqz p0, :after
+ move v0, p2
+ :after
+ # v0 = Phi [p1, p2] with no uses
+
+ invoke-static {}, Ljava/lang/System;->nanoTime()J # create an env use
+
+ :return
+ return p2
+.end method
diff --git a/test/537-checker-debuggable/src/Main.java b/test/537-checker-debuggable/src/Main.java
new file mode 100644
index 0000000000..a572648109
--- /dev/null
+++ b/test/537-checker-debuggable/src/Main.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+public class Main {
+
+ // Workaround for b/18051191.
+ class InnerClass {}
+
+ public static void main(String[] args) { }
+}
diff --git a/test/537-checker-inline-and-unverified/expected.txt b/test/537-checker-inline-and-unverified/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/537-checker-inline-and-unverified/expected.txt
diff --git a/test/537-checker-inline-and-unverified/info.txt b/test/537-checker-inline-and-unverified/info.txt
new file mode 100644
index 0000000000..ec12327408
--- /dev/null
+++ b/test/537-checker-inline-and-unverified/info.txt
@@ -0,0 +1 @@
+Checks that unverified methods are not inlined.
diff --git a/test/537-checker-inline-and-unverified/src/Main.java b/test/537-checker-inline-and-unverified/src/Main.java
new file mode 100644
index 0000000000..bdc14b027c
--- /dev/null
+++ b/test/537-checker-inline-and-unverified/src/Main.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+import other.InaccessibleClass;
+
+public class Main {
+ public static void main(String[] args) {
+ try {
+ testNoInline();
+ } catch (IllegalAccessError e) {
+ // expected
+ }
+ testInline();
+ }
+
+ /// CHECK-START: void Main.testNoInline() inliner (before)
+ /// CHECK: InvokeStaticOrDirect method_name:Main.$opt$noinline$testNoInline
+
+ /// CHECK-START: void Main.testNoInline() inliner (after)
+ /// CHECK: InvokeStaticOrDirect method_name:Main.$opt$noinline$testNoInline
+ public static void testNoInline() {
+ $opt$noinline$testNoInline();
+ }
+
+ /// CHECK-START: void Main.testInline() inliner (before)
+ /// CHECK: InvokeStaticOrDirect method_name:Main.$opt$inline$testInline
+
+ /// CHECK-START: void Main.testInline() inliner (after)
+ /// CHECK-NOT: InvokeStaticOrDirect
+ public static void testInline() {
+ $opt$inline$testInline();
+ }
+
+ public static boolean $opt$noinline$testNoInline() {
+ try {
+ return null instanceof InaccessibleClass;
+ } catch (IllegalAccessError e) {
+ // expected
+ }
+ return false;
+ }
+
+ public static boolean $opt$inline$testInline() {
+ return null instanceof Main;
+ }
+}
diff --git a/test/537-checker-inline-and-unverified/src/other/InaccessibleClass.java b/test/537-checker-inline-and-unverified/src/other/InaccessibleClass.java
new file mode 100644
index 0000000000..de2e1d7830
--- /dev/null
+++ b/test/537-checker-inline-and-unverified/src/other/InaccessibleClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 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 other;
+
+public class InaccessibleClass {
+}
diff --git a/test/537-checker-inline-and-unverified/src2/other/InaccessibleClass.java b/test/537-checker-inline-and-unverified/src2/other/InaccessibleClass.java
new file mode 100644
index 0000000000..ff11d7adc9
--- /dev/null
+++ b/test/537-checker-inline-and-unverified/src2/other/InaccessibleClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 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 other;
+
+/* package */ class InaccessibleClass {
+}
diff --git a/test/538-checker-embed-constants/expected.txt b/test/538-checker-embed-constants/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/538-checker-embed-constants/expected.txt
diff --git a/test/538-checker-embed-constants/info.txt b/test/538-checker-embed-constants/info.txt
new file mode 100644
index 0000000000..5a722ecf12
--- /dev/null
+++ b/test/538-checker-embed-constants/info.txt
@@ -0,0 +1 @@
+Test embedding of constants in assembler instructions.
diff --git a/test/538-checker-embed-constants/src/Main.java b/test/538-checker-embed-constants/src/Main.java
new file mode 100644
index 0000000000..d8618e30fb
--- /dev/null
+++ b/test/538-checker-embed-constants/src/Main.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+public class Main {
+
+ public static void assertIntEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ public static void assertLongEquals(long expected, long result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ /// CHECK-START-ARM: int Main.and255(int) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #255
+ /// CHECK: and {{r\d+}}, {{r\d+}}, #255
+
+ public static int and255(int arg) {
+ return arg & 255;
+ }
+
+ /// CHECK-START-ARM: int Main.and511(int) disassembly (after)
+ /// CHECK: movw {{r\d+}}, #511
+ /// CHECK: and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+
+ public static int and511(int arg) {
+ return arg & 511;
+ }
+
+ /// CHECK-START-ARM: int Main.andNot15(int) disassembly (after)
+ /// CHECK-NOT: mvn {{r\d+}}, #15
+ /// CHECK: bic {{r\d+}}, {{r\d+}}, #15
+
+ public static int andNot15(int arg) {
+ return arg & ~15;
+ }
+
+ /// CHECK-START-ARM: int Main.or255(int) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #255
+ /// CHECK: orr {{r\d+}}, {{r\d+}}, #255
+
+ public static int or255(int arg) {
+ return arg | 255;
+ }
+
+ /// CHECK-START-ARM: int Main.or511(int) disassembly (after)
+ /// CHECK: movw {{r\d+}}, #511
+ /// CHECK: orr{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+
+ public static int or511(int arg) {
+ return arg | 511;
+ }
+
+ /// CHECK-START-ARM: int Main.orNot15(int) disassembly (after)
+ /// CHECK-NOT: mvn {{r\d+}}, #15
+ /// CHECK: orn {{r\d+}}, {{r\d+}}, #15
+
+ public static int orNot15(int arg) {
+ return arg | ~15;
+ }
+
+ /// CHECK-START-ARM: int Main.xor255(int) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #255
+ /// CHECK: eor {{r\d+}}, {{r\d+}}, #255
+
+ public static int xor255(int arg) {
+ return arg ^ 255;
+ }
+
+ /// CHECK-START-ARM: int Main.xor511(int) disassembly (after)
+ /// CHECK: movw {{r\d+}}, #511
+ /// CHECK: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+
+ public static int xor511(int arg) {
+ return arg ^ 511;
+ }
+
+ /// CHECK-START-ARM: int Main.xorNot15(int) disassembly (after)
+ /// CHECK: mvn {{r\d+}}, #15
+ /// CHECK: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+
+ public static int xorNot15(int arg) {
+ return arg ^ ~15;
+ }
+
+ /// CHECK-START-ARM: long Main.and255(long) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #255
+ /// CHECK-NOT: and
+ /// CHECK-NOT: bic
+ /// CHECK-DAG: and {{r\d+}}, {{r\d+}}, #255
+ /// CHECK-DAG: movs {{r\d+}}, #0
+ /// CHECK-NOT: and
+ /// CHECK-NOT: bic
+
+ public static long and255(long arg) {
+ return arg & 255L;
+ }
+
+ /// CHECK-START-ARM: long Main.and511(long) disassembly (after)
+ /// CHECK: movw {{r\d+}}, #511
+ /// CHECK-NOT: and
+ /// CHECK-NOT: bic
+ /// CHECK-DAG: and{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-DAG: movs {{r\d+}}, #0
+ /// CHECK-NOT: and
+ /// CHECK-NOT: bic
+
+ public static long and511(long arg) {
+ return arg & 511L;
+ }
+
+ /// CHECK-START-ARM: long Main.andNot15(long) disassembly (after)
+ /// CHECK-NOT: mvn {{r\d+}}, #15
+ /// CHECK-NOT: and
+ /// CHECK-NOT: bic
+ /// CHECK: bic {{r\d+}}, {{r\d+}}, #15
+ /// CHECK-NOT: and
+ /// CHECK-NOT: bic
+
+ public static long andNot15(long arg) {
+ return arg & ~15L;
+ }
+
+ /// CHECK-START-ARM: long Main.and0xfffffff00000000f(long) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #15
+ /// CHECK-NOT: mvn {{r\d+}}, #15
+ /// CHECK-NOT: and
+ /// CHECK-NOT: bic
+ /// CHECK-DAG: and {{r\d+}}, {{r\d+}}, #15
+ /// CHECK-DAG: bic {{r\d+}}, {{r\d+}}, #15
+ /// CHECK-NOT: and
+ /// CHECK-NOT: bic
+
+ public static long and0xfffffff00000000f(long arg) {
+ return arg & 0xfffffff00000000fL;
+ }
+
+ /// CHECK-START-ARM: long Main.or255(long) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #255
+ /// CHECK-NOT: orr
+ /// CHECK-NOT: orn
+ /// CHECK: orr {{r\d+}}, {{r\d+}}, #255
+ /// CHECK-NOT: orr
+ /// CHECK-NOT: orn
+
+ public static long or255(long arg) {
+ return arg | 255L;
+ }
+
+ /// CHECK-START-ARM: long Main.or511(long) disassembly (after)
+ /// CHECK: movw {{r\d+}}, #511
+ /// CHECK-NOT: orr
+ /// CHECK-NOT: orn
+ /// CHECK: orr{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: orr
+ /// CHECK-NOT: orn
+
+ public static long or511(long arg) {
+ return arg | 511L;
+ }
+
+ /// CHECK-START-ARM: long Main.orNot15(long) disassembly (after)
+ /// CHECK-NOT: mvn {{r\d+}}, #15
+ /// CHECK-NOT: orr
+ /// CHECK-NOT: orn
+ /// CHECK-DAG: orn {{r\d+}}, {{r\d+}}, #15
+ /// CHECK-DAG: mvn {{r\d+}}, #0
+ /// CHECK-NOT: orr
+ /// CHECK-NOT: orn
+
+ public static long orNot15(long arg) {
+ return arg | ~15L;
+ }
+
+ /// CHECK-START-ARM: long Main.or0xfffffff00000000f(long) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #15
+ /// CHECK-NOT: mvn {{r\d+}}, #15
+ /// CHECK-NOT: orr
+ /// CHECK-NOT: orn
+ /// CHECK-DAG: orr {{r\d+}}, {{r\d+}}, #15
+ /// CHECK-DAG: orn {{r\d+}}, {{r\d+}}, #15
+ /// CHECK-NOT: orr
+ /// CHECK-NOT: orn
+
+ public static long or0xfffffff00000000f(long arg) {
+ return arg | 0xfffffff00000000fL;
+ }
+
+ /// CHECK-START-ARM: long Main.xor255(long) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #255
+ /// CHECK-NOT: eor
+ /// CHECK: eor {{r\d+}}, {{r\d+}}, #255
+ /// CHECK-NOT: eor
+
+ public static long xor255(long arg) {
+ return arg ^ 255L;
+ }
+
+ /// CHECK-START-ARM: long Main.xor511(long) disassembly (after)
+ /// CHECK: movw {{r\d+}}, #511
+ /// CHECK-NOT: eor
+ /// CHECK-DAG: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: eor
+
+ public static long xor511(long arg) {
+ return arg ^ 511L;
+ }
+
+ /// CHECK-START-ARM: long Main.xorNot15(long) disassembly (after)
+ /// CHECK-DAG: mvn {{r\d+}}, #15
+ /// CHECK-DAG: mov.w {{r\d+}}, #-1
+ /// CHECK-NOT: eor
+ /// CHECK-DAG: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-DAG: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: eor
+
+ public static long xorNot15(long arg) {
+ return arg ^ ~15L;
+ }
+
+ // Note: No support for partial long constant embedding.
+ /// CHECK-START-ARM: long Main.xor0xfffffff00000000f(long) disassembly (after)
+ /// CHECK-DAG: movs {{r\d+}}, #15
+ /// CHECK-DAG: mvn {{r\d+}}, #15
+ /// CHECK-NOT: eor
+ /// CHECK-DAG: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-DAG: eor{{(\.w)?}} {{r\d+}}, {{r\d+}}, {{r\d+}}
+ /// CHECK-NOT: eor
+
+ public static long xor0xfffffff00000000f(long arg) {
+ return arg ^ 0xfffffff00000000fL;
+ }
+
+ /// CHECK-START-ARM: long Main.xor0xf00000000000000f(long) disassembly (after)
+ /// CHECK-NOT: movs {{r\d+}}, #15
+ /// CHECK-NOT: mov.w {{r\d+}}, #-268435456
+ /// CHECK-NOT: eor
+ /// CHECK-DAG: eor {{r\d+}}, {{r\d+}}, #15
+ /// CHECK-DAG: eor {{r\d+}}, {{r\d+}}, #-268435456
+ /// CHECK-NOT: eor
+
+ public static long xor0xf00000000000000f(long arg) {
+ return arg ^ 0xf00000000000000fL;
+ }
+
+ public static void main(String[] args) {
+ int arg = 0x87654321;
+ assertIntEquals(and255(arg), 0x21);
+ assertIntEquals(and511(arg), 0x121);
+ assertIntEquals(andNot15(arg), 0x87654320);
+ assertIntEquals(or255(arg), 0x876543ff);
+ assertIntEquals(or511(arg), 0x876543ff);
+ assertIntEquals(orNot15(arg), 0xfffffff1);
+ assertIntEquals(xor255(arg), 0x876543de);
+ assertIntEquals(xor511(arg), 0x876542de);
+ assertIntEquals(xorNot15(arg), 0x789abcd1);
+
+ long longArg = 0x1234567887654321L;
+ assertLongEquals(and255(longArg), 0x21L);
+ assertLongEquals(and511(longArg), 0x121L);
+ assertLongEquals(andNot15(longArg), 0x1234567887654320L);
+ assertLongEquals(and0xfffffff00000000f(longArg), 0x1234567000000001L);
+ assertLongEquals(or255(longArg), 0x12345678876543ffL);
+ assertLongEquals(or511(longArg), 0x12345678876543ffL);
+ assertLongEquals(orNot15(longArg), 0xfffffffffffffff1L);
+ assertLongEquals(or0xfffffff00000000f(longArg), 0xfffffff88765432fL);
+ assertLongEquals(xor255(longArg), 0x12345678876543deL);
+ assertLongEquals(xor511(longArg), 0x12345678876542deL);
+ assertLongEquals(xorNot15(longArg), 0xedcba987789abcd1L);
+ assertLongEquals(xor0xfffffff00000000f(longArg), 0xedcba9888765432eL);
+ assertLongEquals(xor0xf00000000000000f(longArg), 0xe23456788765432eL);
+ }
+}
diff --git a/test/539-checker-arm64-encodable-immediates/expected.txt b/test/539-checker-arm64-encodable-immediates/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/539-checker-arm64-encodable-immediates/expected.txt
diff --git a/test/539-checker-arm64-encodable-immediates/info.txt b/test/539-checker-arm64-encodable-immediates/info.txt
new file mode 100644
index 0000000000..efeef33231
--- /dev/null
+++ b/test/539-checker-arm64-encodable-immediates/info.txt
@@ -0,0 +1,2 @@
+Basic tests that check the compiler recognizes when constant values can be
+encoded in the immediate field of instructions.
diff --git a/test/539-checker-arm64-encodable-immediates/src/Main.java b/test/539-checker-arm64-encodable-immediates/src/Main.java
new file mode 100644
index 0000000000..7e3ff9fde8
--- /dev/null
+++ b/test/539-checker-arm64-encodable-immediates/src/Main.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+
+public class Main {
+
+ public static void assertLongEquals(long expected, long result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ /**
+ * Test that the `-1` constant is not synthesized in a register and that we
+ * instead simply switch between `add` and `sub` instructions with the
+ * constant embedded.
+ * We need two uses (or more) of the constant because the compiler always
+ * delegates the immediate value handling to VIXL when there is only one use.
+ */
+
+ /// CHECK-START-ARM64: long Main.addM1(long) register (after)
+ /// CHECK: <<Arg:j\d+>> ParameterValue
+ /// CHECK: <<ConstM1:j\d+>> LongConstant -1
+ /// CHECK-NOT: ParallelMove
+ /// CHECK: Add [<<Arg>>,<<ConstM1>>]
+ /// CHECK: Sub [<<Arg>>,<<ConstM1>>]
+
+ /// CHECK-START-ARM64: long Main.addM1(long) disassembly (after)
+ /// CHECK: sub x{{\d+}}, x{{\d+}}, #0x1
+ /// CHECK: add x{{\d+}}, x{{\d+}}, #0x1
+
+ public static long addM1(long arg) {
+ return (arg + (-1)) | (arg - (-1));
+ }
+
+ public static void main(String[] args) {
+ assertLongEquals(14, addM1(7));
+ }
+}
diff --git a/test/540-checker-rtp-bug/expected.txt b/test/540-checker-rtp-bug/expected.txt
new file mode 100644
index 0000000000..2cf2842aa5
--- /dev/null
+++ b/test/540-checker-rtp-bug/expected.txt
@@ -0,0 +1 @@
+instanceof failed
diff --git a/test/540-checker-rtp-bug/info.txt b/test/540-checker-rtp-bug/info.txt
new file mode 100644
index 0000000000..852cd7c1b4
--- /dev/null
+++ b/test/540-checker-rtp-bug/info.txt
@@ -0,0 +1 @@
+Test that we set the proper types for objects (b/25008765).
diff --git a/test/540-checker-rtp-bug/src/Main.java b/test/540-checker-rtp-bug/src/Main.java
new file mode 100644
index 0000000000..e9f16c04d9
--- /dev/null
+++ b/test/540-checker-rtp-bug/src/Main.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+final class Final {
+ public String toString() {
+ return "final";
+ }
+}
+
+public class Main {
+ /// CHECK-START: Final Main.testKeepCheckCast(java.lang.Object, boolean) reference_type_propagation (after)
+ /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
+ /// CHECK: <<Class:l\d+>> LoadClass
+ /// CHECK: CheckCast [<<Phi>>,<<Class>>]
+ /// CHECK: <<Ret:l\d+>> BoundType [<<Phi>>] klass:Final
+ /// CHECK: Return [<<Ret>>]
+
+ /// CHECK-START: Final Main.testKeepCheckCast(java.lang.Object, boolean) instruction_simplifier_after_types (after)
+ /// CHECK: <<Phi:l\d+>> Phi
+ /// CHECK: <<Class:l\d+>> LoadClass
+ /// CHECK: CheckCast [<<Phi>>,<<Class>>]
+ /// CHECK: <<Ret:l\d+>> BoundType [<<Phi>>]
+ /// CHECK: Return [<<Ret>>]
+ public static Final testKeepCheckCast(Object o, boolean cond) {
+ Object x = new Final();
+ while (cond) {
+ x = o;
+ cond = false;
+ }
+ return (Final) x;
+ }
+
+ /// CHECK-START: void Main.testKeepInstanceOf(java.lang.Object, boolean) reference_type_propagation (after)
+ /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
+ /// CHECK: <<Class:l\d+>> LoadClass
+ /// CHECK: InstanceOf [<<Phi>>,<<Class>>]
+
+ /// CHECK-START: void Main.testKeepInstanceOf(java.lang.Object, boolean) dead_code_elimination (after)
+ /// CHECK: <<Phi:l\d+>> Phi
+ /// CHECK: <<Class:l\d+>> LoadClass
+ /// CHECK: InstanceOf [<<Phi>>,<<Class>>]
+ public static void testKeepInstanceOf(Object o, boolean cond) {
+ Object x = new Final();
+ while (cond) {
+ x = o;
+ cond = false;
+ }
+ if (x instanceof Final) {
+ System.out.println("instanceof succeed");
+ } else {
+ System.out.println("instanceof failed");
+ }
+ }
+
+ /// CHECK-START: java.lang.String Main.testNoInline(java.lang.Object, boolean) reference_type_propagation (after)
+ /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
+ /// CHECK: <<NC:l\d+>> NullCheck [<<Phi>>]
+ /// CHECK: <<Ret:l\d+>> InvokeVirtual [<<NC>>] method_name:java.lang.Object.toString
+ /// CHECK: Return [<<Ret>>]
+
+ /// CHECK-START: java.lang.String Main.testNoInline(java.lang.Object, boolean) inliner (after)
+ /// CHECK: <<Phi:l\d+>> Phi
+ /// CHECK: <<NC:l\d+>> NullCheck [<<Phi>>]
+ /// CHECK: <<Ret:l\d+>> InvokeVirtual [<<NC>>] method_name:java.lang.Object.toString
+ /// CHECK: Return [<<Ret>>]
+ public static String testNoInline(Object o, boolean cond) {
+ Object x = new Final();
+ while (cond) {
+ x = o;
+ cond = false;
+ }
+ return x.toString();
+ }
+
+ public static void main(String[] args) {
+ try {
+ testKeepCheckCast(new Object(), true);
+ throw new Error("Expected check cast exception");
+ } catch (ClassCastException e) {
+ // expected
+ }
+
+ testKeepInstanceOf(new Object(), true);
+
+ if ("final".equals(testNoInline(new Object(), true))) {
+ throw new Error("Bad inlining");
+ }
+ }
+}
diff --git a/test/955-lambda-smali/run b/test/955-lambda-smali/run
index 2aeca8c8fc..b7546801b9 100755
--- a/test/955-lambda-smali/run
+++ b/test/955-lambda-smali/run
@@ -15,4 +15,4 @@
# limitations under the License.
# Ensure that the lambda experimental opcodes are turned on for dalvikvm and dex2oat
-${RUN} "$@" --runtime-option -Xexperimental-lambdas -Xcompiler-option --runtime-arg -Xcompiler-option -Xexperimental-lambdas
+${RUN} "$@" --runtime-option -Xexperimental:lambdas -Xcompiler-option --runtime-arg -Xcompiler-option -Xexperimental:lambdas
diff --git a/test/960-default-smali/build b/test/960-default-smali/build
new file mode 100755
index 0000000000..c7866878e9
--- /dev/null
+++ b/test/960-default-smali/build
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+
+# make us exit on a failure
+set -e
+
+# Generate the smali Main.smali file or fail
+./util-src/generate_smali.py ./smali
+
+if [[ $@ == *"--jvm"* ]]; then
+ # Build the Java files if we are running a --jvm test
+ mkdir -p src
+ mkdir -p classes
+ ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
+ ${JAVAC} -implicit:none -d classes $(find src -name '*.java')
+fi
+
+# Build the smali files and make a dex
+${SMALI} -JXmx256m --experimental --api-level 23 --output classes.dex $(find smali -name '*.smali')
+zip "$TEST_NAME.jar" classes.dex
diff --git a/test/960-default-smali/expected.txt b/test/960-default-smali/expected.txt
new file mode 100644
index 0000000000..7671eed5de
--- /dev/null
+++ b/test/960-default-smali/expected.txt
@@ -0,0 +1,84 @@
+Testing for type A
+A-virtual A.SayHi()='Hi '
+A-interface Greeter.SayHi()='Hi '
+A-virtual A.SayHiTwice()='Hi Hi '
+A-interface Greeter.SayHiTwice()='Hi Hi '
+End testing for type A
+Testing for type B
+B-virtual B.SayHi()='Hello '
+B-interface Greeter.SayHi()='Hello '
+B-interface Greeter2.SayHi()='Hello '
+B-virtual B.SayHiTwice()='I say Hello Hello '
+B-interface Greeter.SayHiTwice()='I say Hello Hello '
+B-interface Greeter2.SayHiTwice()='I say Hello Hello '
+End testing for type B
+Testing for type C
+C-virtual A.SayHi()='Hi '
+C-virtual C.SayHi()='Hi '
+C-interface Greeter.SayHi()='Hi '
+C-virtual A.SayHiTwice()='You don't control me'
+C-virtual C.SayHiTwice()='You don't control me'
+C-interface Greeter.SayHiTwice()='You don't control me'
+End testing for type C
+Testing for type D
+D-virtual D.GetName()='Alex '
+D-interface Greeter3.GetName()='Alex '
+D-virtual D.SayHi()='Hello Alex '
+D-interface Greeter.SayHi()='Hello Alex '
+D-interface Greeter3.SayHi()='Hello Alex '
+D-virtual D.SayHiTwice()='Hello Alex Hello Alex '
+D-interface Greeter.SayHiTwice()='Hello Alex Hello Alex '
+D-interface Greeter3.SayHiTwice()='Hello Alex Hello Alex '
+End testing for type D
+Testing for type E
+E-virtual A.SayHi()='Hi2 '
+E-virtual E.SayHi()='Hi2 '
+E-interface Greeter.SayHi()='Hi2 '
+E-interface Greeter2.SayHi()='Hi2 '
+E-virtual A.SayHiTwice()='I say Hi2 Hi2 '
+E-virtual E.SayHiTwice()='I say Hi2 Hi2 '
+E-interface Greeter.SayHiTwice()='I say Hi2 Hi2 '
+E-interface Greeter2.SayHiTwice()='I say Hi2 Hi2 '
+End testing for type E
+Testing for type F
+F-interface Attendant.GetPlace()='android'
+F-virtual F.GetPlace()='android'
+F-virtual A.SayHi()='Hi '
+F-interface Attendant.SayHi()='Hi '
+F-virtual F.SayHi()='Hi '
+F-interface Greeter.SayHi()='Hi '
+F-virtual A.SayHiTwice()='We can override both interfaces'
+F-interface Attendant.SayHiTwice()='We can override both interfaces'
+F-virtual F.SayHiTwice()='We can override both interfaces'
+F-interface Greeter.SayHiTwice()='We can override both interfaces'
+End testing for type F
+Testing for type G
+G-interface Attendant.GetPlace()='android'
+G-virtual G.GetPlace()='android'
+G-interface Attendant.SayHi()='welcome to android'
+G-virtual G.SayHi()='welcome to android'
+G-interface Attendant.SayHiTwice()='welcome to androidwelcome to android'
+G-virtual G.SayHiTwice()='welcome to androidwelcome to android'
+End testing for type G
+Testing for type H
+H-interface Extension.SayHi()='welcome '
+H-virtual H.SayHi()='welcome '
+End testing for type H
+Testing for type I
+I-virtual A.SayHi()='Hi '
+I-interface Greeter.SayHi()='Hi '
+I-interface Greeter2.SayHi()='Hi '
+I-virtual I.SayHi()='Hi '
+I-virtual A.SayHiTwice()='I say Hi Hi '
+I-interface Greeter.SayHiTwice()='I say Hi Hi '
+I-interface Greeter2.SayHiTwice()='I say Hi Hi '
+I-virtual I.SayHiTwice()='I say Hi Hi '
+End testing for type I
+Testing for type J
+J-virtual A.SayHi()='Hi '
+J-interface Greeter.SayHi()='Hi '
+J-virtual J.SayHi()='Hi '
+J-virtual A.SayHiTwice()='Hi Hi '
+J-interface Greeter.SayHiTwice()='Hi Hi '
+J-virtual J.SayHiTwice()='Hi Hi '
+End testing for type J
diff --git a/test/960-default-smali/info.txt b/test/960-default-smali/info.txt
new file mode 100644
index 0000000000..eb596e2c9f
--- /dev/null
+++ b/test/960-default-smali/info.txt
@@ -0,0 +1,19 @@
+Smali-based tests for experimental interface default methods.
+
+Obviously needs to run under ART or a Java 8 Language runtime and compiler.
+
+When run a Main.smali file will be generated by the util-src/generate_smali.py
+script. If we run with --jvm we will use the tools/extract-embedded-java script to
+turn the smali into equivalent Java using the embedded Java code.
+
+When updating be sure to write the equivalent Java code in comments of the smali
+files.
+
+Care should be taken when updating the generate_smali.py script. It must always
+return equivalent output when run multiple times.
+
+To update the test files do the following steps:
+ <Add new classes/interfaces>
+ <Add these classes/interfaces to ./smali/classes.xml>
+ JAVA_HOME="/path/to/java-8-jdk" ../run-test --use-java-home --update --jvm --host 956-default-smali
+ git add ./smali/classes.xml ./expected.txt
diff --git a/test/960-default-smali/run b/test/960-default-smali/run
new file mode 100755
index 0000000000..e378b061d9
--- /dev/null
+++ b/test/960-default-smali/run
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+
+if echo $@ | grep -q -- "--jvm"; then
+ ${RUN} "$@"
+else
+ ${RUN} "$@" --runtime-option -Xexperimental:default-methods -Xcompiler-option --runtime-arg -Xcompiler-option -Xexperimental:default-methods
+fi
diff --git a/test/960-default-smali/smali/A.smali b/test/960-default-smali/smali/A.smali
new file mode 100644
index 0000000000..e755612fbe
--- /dev/null
+++ b/test/960-default-smali/smali/A.smali
@@ -0,0 +1,38 @@
+# /*
+# * Copyright 2015 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 LA;
+.super Ljava/lang/Object;
+.implements LGreeter;
+
+# class A implements Greeter {
+# public String SayHi() {
+# return "Hi ";
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public SayHi()Ljava/lang/String;
+ .registers 1
+
+ const-string v0, "Hi "
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/Attendant.smali b/test/960-default-smali/smali/Attendant.smali
new file mode 100644
index 0000000000..ab63aeefcb
--- /dev/null
+++ b/test/960-default-smali/smali/Attendant.smali
@@ -0,0 +1,53 @@
+# /*
+# * Copyright 2015 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 abstract interface LAttendant;
+.super Ljava/lang/Object;
+
+# public interface Attendant {
+# public default String SayHi() {
+# return "welcome to " + GetPlace();
+# }
+# public default String SayHiTwice() {
+# return SayHi() + SayHi();
+# }
+#
+# public String GetPlace();
+# }
+
+.method public SayHi()Ljava/lang/String;
+ .locals 2
+ const-string v0, "welcome to "
+ invoke-interface {p0}, LAttendant;->GetPlace()Ljava/lang/String;
+ move-result-object v1
+ invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
+
+.method public SayHiTwice()Ljava/lang/String;
+ .locals 2
+ invoke-interface {p0}, LAttendant;->SayHi()Ljava/lang/String;
+ move-result-object v0
+ invoke-interface {p0}, LAttendant;->SayHi()Ljava/lang/String;
+ move-result-object v1
+ invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
+
+.method public abstract GetPlace()Ljava/lang/String;
+.end method
diff --git a/test/960-default-smali/smali/B.smali b/test/960-default-smali/smali/B.smali
new file mode 100644
index 0000000000..d847dd12ff
--- /dev/null
+++ b/test/960-default-smali/smali/B.smali
@@ -0,0 +1,38 @@
+# /*
+# * Copyright 2015 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 LB;
+.super Ljava/lang/Object;
+.implements LGreeter2;
+
+# class B implements Greeter2 {
+# public String SayHi() {
+# return "Hello ";
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public SayHi()Ljava/lang/String;
+ .registers 1
+
+ const-string v0, "Hello "
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/C.smali b/test/960-default-smali/smali/C.smali
new file mode 100644
index 0000000000..08a8508be1
--- /dev/null
+++ b/test/960-default-smali/smali/C.smali
@@ -0,0 +1,37 @@
+# /*
+# * Copyright 2015 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 LC;
+.super LA;
+
+# class C extends A {
+# public String SayHiTwice() {
+# return "You don't control me";
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, LA;-><init>()V
+ return-void
+.end method
+
+.method public SayHiTwice()Ljava/lang/String;
+ .registers 1
+
+ const-string v0, "You don't control me"
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/D.smali b/test/960-default-smali/smali/D.smali
new file mode 100644
index 0000000000..32f3b7ec8b
--- /dev/null
+++ b/test/960-default-smali/smali/D.smali
@@ -0,0 +1,38 @@
+# /*
+# * Copyright 2015 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 LD;
+.super Ljava/lang/Object;
+.implements LGreeter3;
+
+# class D implements Greeter3 {
+# public String GetName() {
+# return "Alex ";
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public GetName()Ljava/lang/String;
+ .registers 1
+
+ const-string v0, "Alex "
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/E.smali b/test/960-default-smali/smali/E.smali
new file mode 100644
index 0000000000..bae6250414
--- /dev/null
+++ b/test/960-default-smali/smali/E.smali
@@ -0,0 +1,38 @@
+# /*
+# * Copyright 2015 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 LE;
+.super LA;
+.implements LGreeter2;
+
+# class E extends A implements Greeter2 {
+# public String SayHi() {
+# return "Hi2 ";
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, LA;-><init>()V
+ return-void
+.end method
+
+.method public SayHi()Ljava/lang/String;
+ .registers 1
+
+ const-string v0, "Hi2 "
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/Extension.smali b/test/960-default-smali/smali/Extension.smali
new file mode 100644
index 0000000000..60ffa26ec6
--- /dev/null
+++ b/test/960-default-smali/smali/Extension.smali
@@ -0,0 +1,30 @@
+# /*
+# * Copyright 2015 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 abstract interface LExtension;
+.super Ljava/lang/Object;
+
+# public interface Extension {
+# public default String SayHi() {
+# return "welcome ";
+# }
+# }
+
+.method public SayHi()Ljava/lang/String;
+ .locals 1
+ const-string v0, "welcome "
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/F.smali b/test/960-default-smali/smali/F.smali
new file mode 100644
index 0000000000..3eaa089e1f
--- /dev/null
+++ b/test/960-default-smali/smali/F.smali
@@ -0,0 +1,47 @@
+# /*
+# * Copyright 2015 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 LF;
+.super LA;
+.implements LAttendant;
+
+# class F extends A implements Attendant {
+# public String GetPlace() {
+# return "android";
+# }
+# public String SayHiTwice() {
+# return "We can override both interfaces";
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public SayHiTwice()Ljava/lang/String;
+ .registers 1
+
+ const-string v0, "We can override both interfaces"
+ return-object v0
+.end method
+
+.method public GetPlace()Ljava/lang/String;
+ .registers 1
+ const-string v0, "android"
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/G.smali b/test/960-default-smali/smali/G.smali
new file mode 100644
index 0000000000..446f2a4c64
--- /dev/null
+++ b/test/960-default-smali/smali/G.smali
@@ -0,0 +1,37 @@
+# /*
+# * Copyright 2015 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 LG;
+.super Ljava/lang/Object;
+.implements LAttendant;
+
+# class G implements Attendant {
+# public String GetPlace() {
+# return "android";
+# }
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public GetPlace()Ljava/lang/String;
+ .registers 1
+ const-string v0, "android"
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/Greeter.smali b/test/960-default-smali/smali/Greeter.smali
new file mode 100644
index 0000000000..28530ffc6f
--- /dev/null
+++ b/test/960-default-smali/smali/Greeter.smali
@@ -0,0 +1,40 @@
+# /*
+# * Copyright 2015 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 abstract interface LGreeter;
+.super Ljava/lang/Object;
+
+# public interface Greeter {
+# public String SayHi();
+#
+# public default String SayHiTwice() {
+# return SayHi() + SayHi();
+# }
+# }
+
+.method public abstract SayHi()Ljava/lang/String;
+.end method
+
+.method public SayHiTwice()Ljava/lang/String;
+ .locals 2
+ invoke-interface {p0}, LGreeter;->SayHi()Ljava/lang/String;
+ move-result-object v0
+ invoke-interface {p0}, LGreeter;->SayHi()Ljava/lang/String;
+ move-result-object v1
+ invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/Greeter2.smali b/test/960-default-smali/smali/Greeter2.smali
new file mode 100644
index 0000000000..ace1798bab
--- /dev/null
+++ b/test/960-default-smali/smali/Greeter2.smali
@@ -0,0 +1,39 @@
+# /*
+# * Copyright 2015 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 abstract interface LGreeter2;
+.super Ljava/lang/Object;
+.implements LGreeter;
+
+# public interface Greeter2 extends Greeter {
+# public default String SayHiTwice() {
+# return "I say " + SayHi() + SayHi();
+# }
+# }
+
+.method public SayHiTwice()Ljava/lang/String;
+ .locals 3
+ const-string v0, "I say "
+ invoke-interface {p0}, LGreeter;->SayHi()Ljava/lang/String;
+ move-result-object v1
+ invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ invoke-interface {p0}, LGreeter;->SayHi()Ljava/lang/String;
+ move-result-object v1
+ invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/Greeter3.smali b/test/960-default-smali/smali/Greeter3.smali
new file mode 100644
index 0000000000..31fc2e79ff
--- /dev/null
+++ b/test/960-default-smali/smali/Greeter3.smali
@@ -0,0 +1,40 @@
+# /*
+# * Copyright 2015 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 abstract interface LGreeter3;
+.super Ljava/lang/Object;
+.implements LGreeter;
+
+# public interface Greeter3 extends Greeter {
+# public String GetName();
+#
+# public default String SayHi() {
+# return "Hello " + GetName();
+# }
+# }
+
+.method public abstract GetName()Ljava/lang/String;
+.end method
+
+.method public SayHi()Ljava/lang/String;
+ .locals 2
+ const-string v0, "Hello "
+ invoke-interface {p0}, LGreeter3;->GetName()Ljava/lang/String;
+ move-result-object v1
+ invoke-virtual {v0, v1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ return-object v0
+.end method
diff --git a/test/960-default-smali/smali/H.smali b/test/960-default-smali/smali/H.smali
new file mode 100644
index 0000000000..82065ea49d
--- /dev/null
+++ b/test/960-default-smali/smali/H.smali
@@ -0,0 +1,28 @@
+# /*
+# * Copyright 2015 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 LH;
+.super Ljava/lang/Object;
+.implements LExtension;
+
+# class H implements Extension {
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
diff --git a/test/960-default-smali/smali/I.smali b/test/960-default-smali/smali/I.smali
new file mode 100644
index 0000000000..72fb58afe4
--- /dev/null
+++ b/test/960-default-smali/smali/I.smali
@@ -0,0 +1,28 @@
+# /*
+# * Copyright 2015 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 LI;
+.super LA;
+.implements LGreeter2;
+
+# class I extends A implements Greeter2 {
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
diff --git a/test/960-default-smali/smali/J.smali b/test/960-default-smali/smali/J.smali
new file mode 100644
index 0000000000..93f3d6231c
--- /dev/null
+++ b/test/960-default-smali/smali/J.smali
@@ -0,0 +1,29 @@
+# /*
+# * Copyright 2015 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 LJ;
+.super LA;
+
+# class J extends A {
+# }
+
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, LA;-><init>()V
+ return-void
+.end method
+
diff --git a/test/960-default-smali/smali/classes.xml b/test/960-default-smali/smali/classes.xml
new file mode 100644
index 0000000000..0aa41f7fb6
--- /dev/null
+++ b/test/960-default-smali/smali/classes.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2015 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.
+-->
+
+<data>
+ <classes>
+ <class name="A" super="java/lang/Object">
+ <implements>
+ <item>Greeter</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="B" super="java/lang/Object">
+ <implements>
+ <item>Greeter2</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="C" super="A">
+ <implements> </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="D" super="java/lang/Object">
+ <implements>
+ <item>Greeter3</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="E" super="A">
+ <implements>
+ <item>Greeter2</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="F" super="A">
+ <implements>
+ <item>Attendant</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="G" super="java/lang/Object">
+ <implements>
+ <item>Attendant</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="H" super="java/lang/Object">
+ <implements>
+ <item>Extension</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="I" super="A">
+ <implements>
+ <item>Greeter2</item>
+ </implements>
+ <methods> </methods>
+ </class>
+
+ <class name="J" super="A">
+ <implements> </implements>
+ <methods> </methods>
+ </class>
+ </classes>
+
+ <interfaces>
+ <interface name="Extension" super="java/lang/Object">
+ <implements> </implements>
+ <methods>
+ <method type="default">SayHi</method>
+ </methods>
+ </interface>
+
+ <interface name="Greeter" super="java/lang/Object">
+ <implements> </implements>
+ <methods>
+ <method type="abstract">SayHi</method>
+ <method type="default">SayHiTwice</method>
+ </methods>
+ </interface>
+
+ <interface name="Greeter2" super="java/lang/Object">
+ <implements>
+ <item>Greeter</item>
+ </implements>
+ <methods> </methods>
+ </interface>
+
+ <interface name="Greeter3" super="java/lang/Object">
+ <implements>
+ <item>Greeter</item>
+ </implements>
+ <methods>
+ <method type="abstract">GetName</method>
+ </methods>
+ </interface>
+
+ <interface name="Attendant" super="java/lang/Object">
+ <implements> </implements>
+ <methods>
+ <method type="default">SayHi</method>
+ <method type="default">SayHiTwice</method>
+ <method type="abstract">GetPlace</method>
+ </methods>
+ </interface>
+ </interfaces>
+</data>
diff --git a/test/960-default-smali/util-src/generate_smali.py b/test/960-default-smali/util-src/generate_smali.py
new file mode 100755
index 0000000000..b2bf1f0761
--- /dev/null
+++ b/test/960-default-smali/util-src/generate_smali.py
@@ -0,0 +1,376 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015 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.
+
+"""
+Generate Smali Main file for test 960
+"""
+
+import os
+import sys
+from pathlib import Path
+
+BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+if BUILD_TOP is None:
+ print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
+ sys.exit(1)
+
+# Allow us to import utils and mixins.
+sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
+
+from testgen.utils import get_copyright
+import testgen.mixins as mixins
+
+from collections import namedtuple
+import itertools
+import functools
+import xml.etree.ElementTree as ET
+
+class MainClass(mixins.DumpMixin, mixins.Named, mixins.SmaliFileMixin):
+ """
+ A mainclass and main method for this test.
+ """
+
+ MAIN_CLASS_TEMPLATE = """{copyright}
+.class public LMain;
+.super Ljava/lang/Object;
+
+# class Main {{
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+{test_groups}
+
+{test_funcs}
+
+{main_func}
+
+# }}
+"""
+
+ MAIN_FUNCTION_TEMPLATE = """
+# public static void main(String[] args) {{
+.method public static main([Ljava/lang/String;)V
+ .locals 2
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ {test_group_invoke}
+
+ return-void
+.end method
+# }}
+"""
+
+ TEST_GROUP_INVOKE_TEMPLATE = """
+# {test_name}();
+ invoke-static {{}}, {test_name}()V
+"""
+
+ def __init__(self):
+ """
+ Initialize this MainClass
+ """
+ self.tests = set()
+ self.global_funcs = set()
+
+ def add_instance(self, it):
+ """
+ Add an instance test for the given class
+ """
+ self.tests.add(it)
+
+ def add_func(self, f):
+ """
+ Add a function to the class
+ """
+ self.global_funcs.add(f)
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return "Main"
+
+ def __str__(self):
+ """
+ Print this class
+ """
+ all_tests = sorted(self.tests)
+ test_invoke = ""
+ test_groups = ""
+ for t in all_tests:
+ test_groups += str(t)
+ for t in sorted(all_tests):
+ test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
+ main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
+
+ funcs = ""
+ for f in self.global_funcs:
+ funcs += str(f)
+ return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
+ test_groups=test_groups,
+ main_func=main_func, test_funcs=funcs)
+
+
+class InstanceTest(mixins.Named, mixins.NameComparableMixin):
+ """
+ A method that runs tests for a particular concrete type, It calls the test
+ cases for running it in all possible ways.
+ """
+
+ INSTANCE_TEST_TEMPLATE = """
+# public static void {test_name}() {{
+# System.out.println("Testing for type {ty}");
+# String s = "{ty}";
+# {ty} v = new {ty}();
+.method public static {test_name}()V
+ .locals 3
+ sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ const-string v0, "Testing for type {ty}"
+ invoke-virtual {{v2,v0}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+ const-string v0, "{ty}"
+ new-instance v1, L{ty};
+ invoke-direct {{v1}}, L{ty};-><init>()V
+
+ {invokes}
+
+ const-string v0, "End testing for type {ty}"
+ invoke-virtual {{v2,v0}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ return-void
+.end method
+# System.out.println("End testing for type {ty}");
+# }}
+"""
+
+ TEST_INVOKE_TEMPLATE = """
+# {fname}(s, v);
+ invoke-static {{v0, v1}}, {fname}(Ljava/lang/String;L{farg};)V
+"""
+
+ def __init__(self, main, ty):
+ """
+ Initialize this test group for the given type
+ """
+ self.ty = ty
+ self.main = main
+ self.funcs = set()
+ self.main.add_instance(self)
+
+ def get_name(self):
+ """
+ Get the name of this test group
+ """
+ return "TEST_NAME_"+self.ty
+
+ def add_func(self, f):
+ """
+ Add a test function to this test group
+ """
+ self.main.add_func(f)
+ self.funcs.add(f)
+
+ def __str__(self):
+ """
+ Returns the smali code for this function
+ """
+ func_invokes = ""
+ for f in sorted(self.funcs, key=lambda a: (a.func, a.farg)):
+ func_invokes += self.TEST_INVOKE_TEMPLATE.format(fname=f.get_name(),
+ farg=f.farg)
+
+ return self.INSTANCE_TEST_TEMPLATE.format(test_name=self.get_name(), ty=self.ty,
+ invokes=func_invokes)
+
+class Func(mixins.Named, mixins.NameComparableMixin):
+ """
+ A single test case that attempts to invoke a function on receiver of a given type.
+ """
+
+ TEST_FUNCTION_TEMPLATE = """
+# public static void {fname}(String s, {farg} v) {{
+# try {{
+# System.out.printf("%s-{invoke_type:<9} {farg:>9}.{callfunc}()='%s'\\n", s, v.{callfunc}());
+# return;
+# }} catch (Error e) {{
+# System.out.printf("%s-{invoke_type} on {farg}: {callfunc}() threw exception!\\n", s);
+# e.printStackTrace(System.out);
+# }}
+# }}
+.method public static {fname}(Ljava/lang/String;L{farg};)V
+ .locals 7
+ :call_{fname}_try_start
+ const/4 v0, 2
+ new-array v1,v0, [Ljava/lang/Object;
+ const/4 v0, 0
+ aput-object p0,v1,v0
+
+ sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ const-string v3, "%s-{invoke_type:<9} {farg:>9}.{callfunc}()='%s'\\n"
+
+ invoke-{invoke_type} {{p1}}, L{farg};->{callfunc}()Ljava/lang/String;
+ move-result-object v4
+ const/4 v0, 1
+ aput-object v4, v1, v0
+
+ invoke-virtual {{v2,v3,v1}}, Ljava/io/PrintStream;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
+ return-void
+ :call_{fname}_try_end
+ .catch Ljava/lang/Error; {{:call_{fname}_try_start .. :call_{fname}_try_end}} :error_{fname}_start
+ :error_{fname}_start
+ move-exception v3
+ const/4 v0, 1
+ new-array v1,v0, [Ljava/lang/Object;
+ const/4 v0, 0
+ aput-object p0, v1, v0
+ sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ const-string v4, "%s-{invoke_type} on {farg}: {callfunc}() threw exception!\\n"
+ invoke-virtual {{v2,v4,v1}}, Ljava/io/PrintStream;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
+ invoke-virtual {{v3,v2}}, Ljava/lang/Error;->printStackTrace(Ljava/io/PrintStream;)V
+ return-void
+.end method
+"""
+
+ def __init__(self, func, farg, invoke):
+ """
+ Initialize this test function for the given invoke type and argument
+ """
+ self.func = func
+ self.farg = farg
+ self.invoke = invoke
+
+ def get_name(self):
+ """
+ Get the name of this test
+ """
+ return "Test_Func_{}_{}_{}".format(self.func, self.farg, self.invoke)
+
+ def __str__(self):
+ """
+ Get the smali code for this test function
+ """
+ return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(),
+ farg=self.farg,
+ invoke_type=self.invoke,
+ callfunc=self.func)
+
+def flatten_classes(classes, c):
+ """
+ Iterate over all the classes 'c' can be used as
+ """
+ while c:
+ yield c
+ c = classes.get(c.super_class)
+
+def flatten_class_methods(classes, c):
+ """
+ Iterate over all the methods 'c' can call
+ """
+ for c1 in flatten_classes(classes, c):
+ yield from c1.methods
+
+def flatten_interfaces(dat, c):
+ """
+ Iterate over all the interfaces 'c' transitively implements
+ """
+ def get_ifaces(cl):
+ for i2 in cl.implements:
+ yield dat.interfaces[i2]
+ yield from get_ifaces(dat.interfaces[i2])
+
+ for cl in flatten_classes(dat.classes, c):
+ yield from get_ifaces(cl)
+
+def flatten_interface_methods(dat, i):
+ """
+ Iterate over all the interface methods 'c' can call
+ """
+ yield from i.methods
+ for i2 in flatten_interfaces(dat, i):
+ yield from i2.methods
+
+def make_main_class(dat):
+ """
+ Creates a Main.smali file that runs all the tests
+ """
+ m = MainClass()
+ for c in dat.classes.values():
+ i = InstanceTest(m, c.name)
+ for clazz in flatten_classes(dat.classes, c):
+ for meth in flatten_class_methods(dat.classes, clazz):
+ i.add_func(Func(meth, clazz.name, 'virtual'))
+ for iface in flatten_interfaces(dat, clazz):
+ for meth in flatten_interface_methods(dat, iface):
+ i.add_func(Func(meth, clazz.name, 'virtual'))
+ i.add_func(Func(meth, iface.name, 'interface'))
+ return m
+
+class TestData(namedtuple("TestData", ['classes', 'interfaces'])):
+ """
+ A class representing the classes.xml document.
+ """
+ pass
+
+class Clazz(namedtuple("Clazz", ["name", "methods", "super_class", "implements"])):
+ """
+ A class representing a class element in the classes.xml document.
+ """
+ pass
+
+class IFace(namedtuple("IFace", ["name", "methods", "super_class", "implements"])):
+ """
+ A class representing an interface element in the classes.xml document.
+ """
+ pass
+
+def parse_xml(xml):
+ """
+ Parse the xml description of this test.
+ """
+ classes = dict()
+ ifaces = dict()
+ root = ET.fromstring(xml)
+ for iface in root.find("interfaces"):
+ name = iface.attrib['name']
+ implements = [a.text for a in iface.find("implements")]
+ methods = [a.text for a in iface.find("methods")]
+ ifaces[name] = IFace(name = name,
+ super_class = iface.attrib['super'],
+ methods = methods,
+ implements = implements)
+ for clazz in root.find('classes'):
+ name = clazz.attrib['name']
+ implements = [a.text for a in clazz.find("implements")]
+ methods = [a.text for a in clazz.find("methods")]
+ classes[name] = Clazz(name = name,
+ super_class = clazz.attrib['super'],
+ methods = methods,
+ implements = implements)
+ return TestData(classes, ifaces)
+
+def main(argv):
+ smali_dir = Path(argv[1])
+ if not smali_dir.exists() or not smali_dir.is_dir():
+ print("{} is not a valid smali dir".format(smali_dir), file=sys.stderr)
+ sys.exit(1)
+ class_data = parse_xml((smali_dir / "classes.xml").open().read())
+ make_main_class(class_data).dump(smali_dir)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/test/961-default-iface-resolution-generated/build b/test/961-default-iface-resolution-generated/build
new file mode 100755
index 0000000000..707c17e1cf
--- /dev/null
+++ b/test/961-default-iface-resolution-generated/build
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+
+# make us exit on a failure
+set -e
+
+mkdir -p ./smali
+
+# We will be making more files than the ulimit is set to allow. Remove it temporarily.
+OLD_ULIMIT=`ulimit -S`
+ulimit -S unlimited
+
+restore_ulimit() {
+ ulimit -S "$OLD_ULIMIT"
+}
+trap 'restore_ulimit' ERR
+
+# Generate the smali files and expected.txt or fail
+./util-src/generate_smali.py ./smali ./expected.txt
+
+if [[ $@ == *"--jvm"* ]]; then
+ # Build the Java files if we are running a --jvm test
+ mkdir -p src
+ mkdir -p classes
+ ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
+ ${JAVAC} -implicit:none -d classes $(find src -name '*.java')
+fi
+
+# Build the smali files and make a dex
+${SMALI} -JXmx512m --experimental --api-level 23 --output classes.dex $(find smali -name '*.smali')
+zip $TEST_NAME.jar classes.dex
+
+# Reset the ulimit back to its initial value
+restore_ulimit
diff --git a/test/961-default-iface-resolution-generated/expected.txt b/test/961-default-iface-resolution-generated/expected.txt
new file mode 100644
index 0000000000..1ddd65d177
--- /dev/null
+++ b/test/961-default-iface-resolution-generated/expected.txt
@@ -0,0 +1 @@
+This file is generated by util-src/generate_smali.py do not directly modify!
diff --git a/test/961-default-iface-resolution-generated/info.txt b/test/961-default-iface-resolution-generated/info.txt
new file mode 100644
index 0000000000..2cd2cc75b7
--- /dev/null
+++ b/test/961-default-iface-resolution-generated/info.txt
@@ -0,0 +1,17 @@
+Smali-based tests for experimental interface default methods.
+
+This tests that interface method resolution order is correct.
+
+Obviously needs to run under ART or a Java 8 Language runtime and compiler.
+
+When run smali test files are generated by the util-src/generate_smali.py
+script. If we run with --jvm we will use the
+$(ANDROID_BUILD_TOP)/art/tools/extract-embedded-java script to turn the smali
+into equivalent Java using the embedded Java code.
+
+Care should be taken when updating the generate_smali.py script. It should always
+return equivalent output when run multiple times and the expected output should
+be valid.
+
+Do not modify the expected.txt file. It is generated on each run by
+util-src/generate_smali.py.
diff --git a/test/961-default-iface-resolution-generated/run b/test/961-default-iface-resolution-generated/run
new file mode 100755
index 0000000000..e378b061d9
--- /dev/null
+++ b/test/961-default-iface-resolution-generated/run
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+
+if echo $@ | grep -q -- "--jvm"; then
+ ${RUN} "$@"
+else
+ ${RUN} "$@" --runtime-option -Xexperimental:default-methods -Xcompiler-option --runtime-arg -Xcompiler-option -Xexperimental:default-methods
+fi
diff --git a/test/961-default-iface-resolution-generated/util-src/generate_smali.py b/test/961-default-iface-resolution-generated/util-src/generate_smali.py
new file mode 100755
index 0000000000..921a096dd3
--- /dev/null
+++ b/test/961-default-iface-resolution-generated/util-src/generate_smali.py
@@ -0,0 +1,466 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015 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.
+
+"""
+Generate Smali test files for test 961.
+"""
+
+import os
+import sys
+from pathlib import Path
+
+BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+if BUILD_TOP is None:
+ print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
+ sys.exit(1)
+
+# Allow us to import utils and mixins.
+sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
+
+from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
+import testgen.mixins as mixins
+
+from functools import total_ordering
+import itertools
+import string
+
+# The max depth the type tree can have. Includes the class object in the tree.
+# Increasing this increases the number of generated files significantly. This
+# value was chosen as it is fairly quick to run and very comprehensive, checking
+# every possible interface tree up to 5 layers deep.
+MAX_IFACE_DEPTH = 5
+
+class MainClass(mixins.DumpMixin, mixins.Named, mixins.SmaliFileMixin):
+ """
+ A Main.smali file containing the Main class and the main function. It will run
+ all the test functions we have.
+ """
+
+ MAIN_CLASS_TEMPLATE = """{copyright}
+
+.class public LMain;
+.super Ljava/lang/Object;
+
+# class Main {{
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+{test_groups}
+
+{main_func}
+
+# }}
+"""
+
+ MAIN_FUNCTION_TEMPLATE = """
+# public static void main(String[] args) {{
+.method public static main([Ljava/lang/String;)V
+ .locals 2
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ {test_group_invoke}
+
+ return-void
+.end method
+# }}
+"""
+
+ TEST_GROUP_INVOKE_TEMPLATE = """
+# {test_name}();
+ invoke-static {{}}, {test_name}()V
+"""
+
+ def __init__(self):
+ """
+ Initialize this MainClass. We start out with no tests.
+ """
+ self.tests = set()
+
+ def get_expected(self):
+ """
+ Get the expected output of this test.
+ """
+ all_tests = sorted(self.tests)
+ return filter_blanks("\n".join(a.get_expected() for a in all_tests))
+
+ def add_test(self, ty):
+ """
+ Add a test for the concrete type 'ty'
+ """
+ self.tests.add(Func(ty))
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return "Main"
+
+ def __str__(self):
+ """
+ Print the MainClass smali code.
+ """
+ all_tests = sorted(self.tests)
+ test_invoke = ""
+ test_groups = ""
+ for t in all_tests:
+ test_groups += str(t)
+ for t in all_tests:
+ test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
+ main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
+
+ return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright("smali"),
+ test_groups = test_groups,
+ main_func = main_func)
+
+class Func(mixins.Named, mixins.NameComparableMixin):
+ """
+ A function that tests the functionality of a concrete type. Should only be
+ constructed by MainClass.add_test.
+ """
+
+ TEST_FUNCTION_TEMPLATE = """
+# public static void {fname}() {{
+# try {{
+# {farg} v = new {farg}();
+# System.out.printf("%s calls default method on %s\\n",
+# v.CalledClassName(),
+# v.CalledInterfaceName());
+# return;
+# }} catch (Error e) {{
+# e.printStackTrace(System.out);
+# return;
+# }}
+# }}
+.method public static {fname}()V
+ .locals 7
+ :call_{fname}_try_start
+ new-instance v6, L{farg};
+ invoke-direct {{v6}}, L{farg};-><init>()V
+
+ const/4 v0, 2
+ new-array v1,v0, [Ljava/lang/Object;
+ const/4 v0, 0
+ invoke-virtual {{v6}}, L{farg};->CalledClassName()Ljava/lang/String;
+ move-result-object v4
+ aput-object v4,v1,v0
+
+ sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ const-string v3, "%s calls default method on %s\\n"
+
+ invoke-virtual {{v6}}, L{farg};->CalledInterfaceName()Ljava/lang/String;
+ move-result-object v4
+ const/4 v0, 1
+ aput-object v4, v1, v0
+
+ invoke-virtual {{v2,v3,v1}}, Ljava/io/PrintStream;->printf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
+ return-void
+ :call_{fname}_try_end
+ .catch Ljava/lang/Error; {{:call_{fname}_try_start .. :call_{fname}_try_end}} :error_{fname}_start
+ :error_{fname}_start
+ move-exception v3
+ sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ invoke-virtual {{v3,v2}}, Ljava/lang/Error;->printStackTrace(Ljava/io/PrintStream;)V
+ return-void
+.end method
+"""
+
+ def __init__(self, farg):
+ """
+ Initialize a test function for the given argument
+ """
+ self.farg = farg
+
+ def get_expected(self):
+ """
+ Get the expected output calling this function.
+ """
+ return "{tree} calls default method on {iface_tree}".format(
+ tree = self.farg.get_tree(), iface_tree = self.farg.get_called().get_tree())
+
+ def get_name(self):
+ """
+ Get the name of this function
+ """
+ return "TEST_FUNC_{}".format(self.farg.get_name())
+
+ def __str__(self):
+ """
+ Print the smali code of this function.
+ """
+ return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(), farg=self.farg.get_name())
+
+class TestClass(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin):
+ """
+ A class that will be instantiated to test default method resolution order.
+ """
+
+ TEST_CLASS_TEMPLATE = """{copyright}
+
+.class public L{class_name};
+.super Ljava/lang/Object;
+.implements L{iface_name};
+
+# public class {class_name} implements {iface_name} {{
+# public String CalledClassName() {{
+# return "{tree}";
+# }}
+# }}
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public CalledClassName()Ljava/lang/String;
+ .locals 1
+ const-string v0, "{tree}"
+ return-object v0
+.end method
+"""
+
+ def __init__(self, iface):
+ """
+ Initialize this test class which implements the given interface
+ """
+ self.iface = iface
+ self.class_name = "CLASS_"+gensym()
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return self.class_name
+
+ def get_tree(self):
+ """
+ Print out a representation of the type tree of this class
+ """
+ return "[{class_name} {iface_tree}]".format(class_name = self.class_name,
+ iface_tree = self.iface.get_tree())
+
+ def __iter__(self):
+ """
+ Step through all interfaces implemented transitively by this class
+ """
+ yield self.iface
+ yield from self.iface
+
+ def get_called(self):
+ """
+ Get the interface whose default method would be called when calling the
+ CalledInterfaceName function.
+ """
+ all_ifaces = set(iface for iface in self if iface.default)
+ for i in all_ifaces:
+ if all(map(lambda j: i not in j.get_super_types(), all_ifaces)):
+ return i
+ raise Exception("UNREACHABLE! Unable to find default method!")
+
+ def __str__(self):
+ """
+ Print the smali code of this class.
+ """
+ return self.TEST_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
+ iface_name = self.iface.get_name(),
+ tree = self.get_tree(),
+ class_name = self.class_name)
+
+class TestInterface(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin):
+ """
+ An interface that will be used to test default method resolution order.
+ """
+
+ TEST_INTERFACE_TEMPLATE = """{copyright}
+.class public abstract interface L{class_name};
+.super Ljava/lang/Object;
+{implements_spec}
+
+# public interface {class_name} {extends} {ifaces} {{
+# public String CalledClassName();
+.method public abstract CalledClassName()Ljava/lang/String;
+.end method
+
+{funcs}
+
+# }}
+"""
+
+ DEFAULT_FUNC_TEMPLATE = """
+# public default String CalledInterfaceName() {{
+# return "{tree}";
+# }}
+.method public CalledInterfaceName()Ljava/lang/String;
+ .locals 1
+ const-string v0, "{tree}"
+ return-object v0
+.end method
+"""
+
+ IMPLEMENTS_TEMPLATE = """
+.implements L{iface_name};
+"""
+
+ def __init__(self, ifaces, default):
+ """
+ Initialize interface with the given super-interfaces
+ """
+ self.ifaces = sorted(ifaces)
+ self.default = default
+ end = "_DEFAULT" if default else ""
+ self.class_name = "INTERFACE_"+gensym()+end
+
+ def get_super_types(self):
+ """
+ Returns a set of all the supertypes of this interface
+ """
+ return set(i2 for i2 in self)
+
+ def get_name(self):
+ """
+ Get the name of this class
+ """
+ return self.class_name
+
+ def get_tree(self):
+ """
+ Print out a representation of the type tree of this class
+ """
+ return "[{class_name} {iftree}]".format(class_name = self.get_name(),
+ iftree = print_tree(self.ifaces))
+
+ def __iter__(self):
+ """
+ Performs depth-first traversal of the interface tree this interface is the
+ root of. Does not filter out repeats.
+ """
+ for i in self.ifaces:
+ yield i
+ yield from i
+
+ def __str__(self):
+ """
+ Print the smali code of this interface.
+ """
+ s_ifaces = " "
+ j_ifaces = " "
+ for i in self.ifaces:
+ s_ifaces += self.IMPLEMENTS_TEMPLATE.format(iface_name = i.get_name())
+ j_ifaces += " {},".format(i.get_name())
+ j_ifaces = j_ifaces[0:-1]
+ if self.default:
+ funcs = self.DEFAULT_FUNC_TEMPLATE.format(ifaces = j_ifaces,
+ tree = self.get_tree(),
+ class_name = self.class_name)
+ else:
+ funcs = ""
+ return self.TEST_INTERFACE_TEMPLATE.format(copyright = get_copyright('smali'),
+ implements_spec = s_ifaces,
+ extends = "extends" if len(self.ifaces) else "",
+ ifaces = j_ifaces,
+ funcs = funcs,
+ tree = self.get_tree(),
+ class_name = self.class_name)
+
+def print_tree(ifaces):
+ """
+ Prints a list of iface trees
+ """
+ return " ".join(i.get_tree() for i in ifaces)
+
+# The deduplicated output of subtree_sizes for each size up to
+# MAX_LEAF_IFACE_PER_OBJECT.
+SUBTREES = [set(tuple(sorted(l)) for l in subtree_sizes(i))
+ for i in range(MAX_IFACE_DEPTH + 1)]
+
+def create_interface_trees():
+ """
+ Return all legal interface trees
+ """
+ def dump_supers(s):
+ """
+ Does depth first traversal of all the interfaces in the list.
+ """
+ for i in s:
+ yield i
+ yield from i
+
+ def create_interface_trees_inner(num, allow_default):
+ for split in SUBTREES[num]:
+ ifaces = []
+ for sub in split:
+ if sub == 1:
+ ifaces.append([TestInterface([], allow_default)])
+ if allow_default:
+ ifaces[-1].append(TestInterface([], False))
+ else:
+ ifaces.append(list(create_interface_trees_inner(sub, allow_default)))
+ for supers in itertools.product(*ifaces):
+ all_supers = sorted(set(dump_supers(supers)) - set(supers))
+ for i in range(len(all_supers) + 1):
+ for combo in itertools.combinations(all_supers, i):
+ yield TestInterface(list(combo) + list(supers), allow_default)
+ if allow_default:
+ for i in range(len(split)):
+ ifaces = []
+ for sub, cs in zip(split, itertools.count()):
+ if sub == 1:
+ ifaces.append([TestInterface([], i == cs)])
+ else:
+ ifaces.append(list(create_interface_trees_inner(sub, i == cs)))
+ for supers in itertools.product(*ifaces):
+ all_supers = sorted(set(dump_supers(supers)) - set(supers))
+ for i in range(len(all_supers) + 1):
+ for combo in itertools.combinations(all_supers, i):
+ yield TestInterface(list(combo) + list(supers), False)
+
+ for num in range(1, MAX_IFACE_DEPTH):
+ yield from create_interface_trees_inner(num, True)
+
+def create_all_test_files():
+ """
+ Creates all the objects representing the files in this test. They just need to
+ be dumped.
+ """
+ mc = MainClass()
+ classes = {mc}
+ for tree in create_interface_trees():
+ classes.add(tree)
+ for i in tree:
+ classes.add(i)
+ test_class = TestClass(tree)
+ mc.add_test(test_class)
+ classes.add(test_class)
+ return mc, classes
+
+def main(argv):
+ smali_dir = Path(argv[1])
+ if not smali_dir.exists() or not smali_dir.is_dir():
+ print("{} is not a valid smali dir".format(smali_dir), file=sys.stderr)
+ sys.exit(1)
+ expected_txt = Path(argv[2])
+ mainclass, all_files = create_all_test_files()
+ with expected_txt.open('w') as out:
+ print(mainclass.get_expected(), file=out)
+ for f in all_files:
+ f.dump(smali_dir)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/test/962-iface-static/build b/test/962-iface-static/build
new file mode 100755
index 0000000000..5ad82f70d1
--- /dev/null
+++ b/test/962-iface-static/build
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+
+# make us exit on a failure
+set -e
+
+if [[ $@ == *"--jvm"* ]]; then
+ # Build the Java files if we are running a --jvm test
+ mkdir -p src
+ mkdir -p classes
+ ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
+ ${JAVAC} -implicit:none -d classes $(find src -name '*.java')
+fi
+
+# Build the smali files and make a dex
+${SMALI} -JXmx512m --experimental --api-level 23 --output classes.dex $(find smali -name '*.smali')
+zip $TEST_NAME.jar classes.dex
diff --git a/test/962-iface-static/expected.txt b/test/962-iface-static/expected.txt
new file mode 100644
index 0000000000..6d98ea1571
--- /dev/null
+++ b/test/962-iface-static/expected.txt
@@ -0,0 +1,3 @@
+init
+constructor
+Hello
diff --git a/test/962-iface-static/info.txt b/test/962-iface-static/info.txt
new file mode 100644
index 0000000000..d4732e533d
--- /dev/null
+++ b/test/962-iface-static/info.txt
@@ -0,0 +1,4 @@
+Smali-based tests for experimental interface static methods.
+
+To run with --jvm you must export JAVA_HOME to a Java 8 Language installation
+and pass the --use-java-home to run-test
diff --git a/test/962-iface-static/run b/test/962-iface-static/run
new file mode 100755
index 0000000000..e713708c18
--- /dev/null
+++ b/test/962-iface-static/run
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Copyright (C) 2015 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.
+
+if echo $@ | grep -q -- "--jvm"; then
+ ${RUN} "$@"
+else
+ ${RUN} "$@" --runtime-option -Xexperimental:default-methods -Xcompiler-option --runtime-arg -Xcompiler-option -Xexperimental:default-methods
+fi
diff --git a/test/962-iface-static/smali/Displayer.smali b/test/962-iface-static/smali/Displayer.smali
new file mode 100644
index 0000000000..06bec16432
--- /dev/null
+++ b/test/962-iface-static/smali/Displayer.smali
@@ -0,0 +1,45 @@
+# /*
+# * Copyright (C) 2015 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.
+# */
+#
+# public class Displayer {
+# static {
+# System.out.println("init");
+# }
+#
+# public Displayer() {
+# System.out.println("constructor");
+# }
+# }
+
+.class public LDisplayer;
+.super Ljava/lang/Object;
+
+.method public static <clinit>()V
+ .locals 3
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ const-string v0, "init"
+ invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ return-void
+.end method
+
+.method public constructor <init>()V
+ .locals 2
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ const-string v0, "constructor"
+ invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ return-void
+.end method
diff --git a/test/962-iface-static/smali/Main.smali b/test/962-iface-static/smali/Main.smali
new file mode 100644
index 0000000000..72fa5e0e6e
--- /dev/null
+++ b/test/962-iface-static/smali/Main.smali
@@ -0,0 +1,40 @@
+# /*
+# * Copyright (C) 2015 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 Main {
+# public static void main(String[] args) {
+# System.out.println(iface.SayHi());
+# }
+# }
+.class public LMain;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public static main([Ljava/lang/String;)V
+ .locals 2
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ invoke-static {}, Liface;->SayHi()Ljava/lang/String;
+ move-result-object v0
+ invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+ return-void
+.end method
diff --git a/test/962-iface-static/smali/iface.smali b/test/962-iface-static/smali/iface.smali
new file mode 100644
index 0000000000..441aae669e
--- /dev/null
+++ b/test/962-iface-static/smali/iface.smali
@@ -0,0 +1,43 @@
+# /*
+# * Copyright (C) 2015 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.
+# */
+#
+# public interface iface {
+# public static final Displayer f = new Displayer();
+#
+# public static String SayHi() {
+# return "Hello";
+# }
+# }
+
+.class public abstract interface Liface;
+.super Ljava/lang/Object;
+
+.field public final static f:LDisplayer;
+
+.method public static <clinit>()V
+ .locals 3
+ new-instance v1, LDisplayer;
+ invoke-direct {v1}, LDisplayer;-><init>()V
+ sput-object v1, Liface;->f:LDisplayer;
+ return-void
+.end method
+
+.method public static SayHi()Ljava/lang/String;
+ .locals 1
+ const-string v0, "Hello"
+ return-object v0
+.end method
+
diff --git a/test/963-default-range-smali/build b/test/963-default-range-smali/build
new file mode 100755
index 0000000000..5ad82f70d1
--- /dev/null
+++ b/test/963-default-range-smali/build
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+
+# make us exit on a failure
+set -e
+
+if [[ $@ == *"--jvm"* ]]; then
+ # Build the Java files if we are running a --jvm test
+ mkdir -p src
+ mkdir -p classes
+ ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
+ ${JAVAC} -implicit:none -d classes $(find src -name '*.java')
+fi
+
+# Build the smali files and make a dex
+${SMALI} -JXmx512m --experimental --api-level 23 --output classes.dex $(find smali -name '*.smali')
+zip $TEST_NAME.jar classes.dex
diff --git a/test/963-default-range-smali/expected.txt b/test/963-default-range-smali/expected.txt
new file mode 100644
index 0000000000..af17d2f873
--- /dev/null
+++ b/test/963-default-range-smali/expected.txt
@@ -0,0 +1,2 @@
+Hello
+Hello
diff --git a/test/963-default-range-smali/info.txt b/test/963-default-range-smali/info.txt
new file mode 100644
index 0000000000..d4732e533d
--- /dev/null
+++ b/test/963-default-range-smali/info.txt
@@ -0,0 +1,4 @@
+Smali-based tests for experimental interface static methods.
+
+To run with --jvm you must export JAVA_HOME to a Java 8 Language installation
+and pass the --use-java-home to run-test
diff --git a/test/963-default-range-smali/run b/test/963-default-range-smali/run
new file mode 100755
index 0000000000..e713708c18
--- /dev/null
+++ b/test/963-default-range-smali/run
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Copyright (C) 2015 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.
+
+if echo $@ | grep -q -- "--jvm"; then
+ ${RUN} "$@"
+else
+ ${RUN} "$@" --runtime-option -Xexperimental:default-methods -Xcompiler-option --runtime-arg -Xcompiler-option -Xexperimental:default-methods
+fi
diff --git a/test/963-default-range-smali/smali/A.smali b/test/963-default-range-smali/smali/A.smali
new file mode 100644
index 0000000000..b3d91dd76b
--- /dev/null
+++ b/test/963-default-range-smali/smali/A.smali
@@ -0,0 +1,29 @@
+# /*
+# * Copyright 2015 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 LA;
+.super Ljava/lang/Object;
+.implements Liface;
+
+# class A implements iface {
+# }
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
diff --git a/test/963-default-range-smali/smali/Main.smali b/test/963-default-range-smali/smali/Main.smali
new file mode 100644
index 0000000000..400fba72d9
--- /dev/null
+++ b/test/963-default-range-smali/smali/Main.smali
@@ -0,0 +1,77 @@
+# /*
+# * Copyright (C) 2015 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 Main {
+# public static void main(String[] args) {
+# A a = new A();
+# System.out.println(a.SayHi("a string 0",
+# "a string 1",
+# "a string 2",
+# "a string 3",
+# "a string 4",
+# "a string 5",
+# "a string 6",
+# "a string 7",
+# "a string 8",
+# "a string 9"));
+# iface b = (iface)a;
+# System.out.println(b.SayHi("a string 0",
+# "a string 1",
+# "a string 2",
+# "a string 3",
+# "a string 4",
+# "a string 5",
+# "a string 6",
+# "a string 7",
+# "a string 8",
+# "a string 9"));
+# }
+# }
+.class public LMain;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+.method public static main([Ljava/lang/String;)V
+ .locals 15
+ sget-object v12, Ljava/lang/System;->out:Ljava/io/PrintStream;
+
+ new-instance v1, LA;
+ invoke-direct {v1}, LA;-><init>()V
+ const-string v2, "a string 0"
+ const-string v3, "a string 1"
+ const-string v4, "a string 2"
+ const-string v5, "a string 3"
+ const-string v6, "a string 4"
+ const-string v7, "a string 5"
+ const-string v8, "a string 6"
+ const-string v9, "a string 7"
+ const-string v10, "a string 8"
+ const-string v11, "a string 9"
+ invoke-virtual/range {v1 .. v11}, LA;->SayHi(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ invoke-virtual {v12,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+ invoke-interface/range {v1 .. v11}, Liface;->SayHi(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ invoke-virtual {v12,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+ return-void
+.end method
diff --git a/test/963-default-range-smali/smali/iface.smali b/test/963-default-range-smali/smali/iface.smali
new file mode 100644
index 0000000000..c2c3ce69a7
--- /dev/null
+++ b/test/963-default-range-smali/smali/iface.smali
@@ -0,0 +1,40 @@
+# /*
+# * Copyright (C) 2015 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.
+# */
+#
+# public interface iface {
+# public default String SayHi(String n1,
+# String n2,
+# String n3,
+# String n4,
+# String n5,
+# String n6,
+# String n7,
+# String n8,
+# String n9,
+# String n0) {
+# return "Hello";
+# }
+# }
+
+.class public abstract interface Liface;
+.super Ljava/lang/Object;
+
+.method public SayHi(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+ .locals 1
+ const-string v0, "Hello"
+ return-object v0
+.end method
+
diff --git a/test/964-default-iface-init-generated/build b/test/964-default-iface-init-generated/build
new file mode 100755
index 0000000000..deef803813
--- /dev/null
+++ b/test/964-default-iface-init-generated/build
@@ -0,0 +1,45 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+
+# make us exit on a failure
+set -e
+
+# We will be making more files than the ulimit is set to allow. Remove it temporarily.
+OLD_ULIMIT=`ulimit -S`
+ulimit -S unlimited
+
+restore_ulimit() {
+ ulimit -S "$OLD_ULIMIT"
+}
+trap 'restore_ulimit' ERR
+
+# Generate the smali files and expected.txt or fail
+./util-src/generate_smali.py ./smali ./expected.txt
+
+if [[ $@ == *"--jvm"* ]]; then
+ # Build the Java files if we are running a --jvm test
+ mkdir -p src
+ mkdir -p classes
+ ${ANDROID_BUILD_TOP}/art/tools/extract-embedded-java ./smali ./src
+ ${JAVAC} -implicit:none -d classes $(find src -name '*.java')
+fi
+
+# Build the smali files and make a dex
+${SMALI} -JXmx512m --experimental --api-level 23 --output classes.dex $(find smali -name '*.smali')
+zip $TEST_NAME.jar classes.dex
+
+# Reset the ulimit back to its initial value
+restore_ulimit
diff --git a/test/964-default-iface-init-generated/expected.txt b/test/964-default-iface-init-generated/expected.txt
new file mode 100644
index 0000000000..1ddd65d177
--- /dev/null
+++ b/test/964-default-iface-init-generated/expected.txt
@@ -0,0 +1 @@
+This file is generated by util-src/generate_smali.py do not directly modify!
diff --git a/test/964-default-iface-init-generated/info.txt b/test/964-default-iface-init-generated/info.txt
new file mode 100644
index 0000000000..5805a86854
--- /dev/null
+++ b/test/964-default-iface-init-generated/info.txt
@@ -0,0 +1,17 @@
+Smali-based tests for interface initialization.
+
+This tests that interface initialization order is correct.
+
+Obviously needs to run under ART or a Java 8 Language runtime and compiler.
+
+When run smali test files are generated by the util-src/generate_smali.py
+script. If we run with --jvm we will use the
+$(ANDROID_BUILD_TOP)/art/tools/extract-embedded-java script to turn the smali
+into equivalent Java using the embedded Java code.
+
+Care should be taken when updating the generate_smali.py script. It should always
+return equivalent output when run multiple times and the expected output should
+be valid.
+
+Do not modify the expected.txt file. It is generated on each run by
+util-src/generate_smali.py.
diff --git a/test/964-default-iface-init-generated/run b/test/964-default-iface-init-generated/run
new file mode 100755
index 0000000000..e378b061d9
--- /dev/null
+++ b/test/964-default-iface-init-generated/run
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# Copyright 2015 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.
+
+if echo $@ | grep -q -- "--jvm"; then
+ ${RUN} "$@"
+else
+ ${RUN} "$@" --runtime-option -Xexperimental:default-methods -Xcompiler-option --runtime-arg -Xcompiler-option -Xexperimental:default-methods
+fi
diff --git a/test/964-default-iface-init-generated/smali/Displayer.smali b/test/964-default-iface-init-generated/smali/Displayer.smali
new file mode 100644
index 0000000000..91280a8a42
--- /dev/null
+++ b/test/964-default-iface-init-generated/smali/Displayer.smali
@@ -0,0 +1,45 @@
+# /*
+# * Copyright (C) 2015 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.
+# */
+#
+# // This class is b/c java does not allow static {} blocks in interfaces.
+# public class Displayer {
+# public Displayer(String type) {
+# System.out.println("initialization of " + type);
+# }
+# public void touch() {
+# return;
+# }
+# }
+
+.class public LDisplayer;
+.super Ljava/lang/Object;
+
+.method public constructor <init>(Ljava/lang/String;)V
+ .locals 2
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ const-string v0, "initialization of "
+ invoke-virtual {v0, p1}, Ljava/lang/String;->concat(Ljava/lang/String;)Ljava/lang/String;
+ move-result-object v0
+ sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ invoke-virtual {v1,v0}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ return-void
+.end method
+
+.method public touch()V
+ .locals 0
+ return-void
+.end method
+
diff --git a/test/964-default-iface-init-generated/util-src/generate_smali.py b/test/964-default-iface-init-generated/util-src/generate_smali.py
new file mode 100755
index 0000000000..be2d3ba563
--- /dev/null
+++ b/test/964-default-iface-init-generated/util-src/generate_smali.py
@@ -0,0 +1,531 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015 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.
+
+"""
+Generate Smali test files for test 964.
+"""
+
+import os
+import sys
+from pathlib import Path
+
+BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+if BUILD_TOP is None:
+ print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
+ sys.exit(1)
+
+# Allow us to import utils and mixins.
+sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))
+
+from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks
+import testgen.mixins as mixins
+
+from functools import total_ordering
+import itertools
+import string
+
+# The max depth the tree can have.
+MAX_IFACE_DEPTH = 3
+
+class MainClass(mixins.DumpMixin, mixins.Named, mixins.SmaliFileMixin):
+ """
+ A Main.smali file containing the Main class and the main function. It will run
+ all the test functions we have.
+ """
+
+ MAIN_CLASS_TEMPLATE = """{copyright}
+
+.class public LMain;
+.super Ljava/lang/Object;
+
+# class Main {{
+
+.method public constructor <init>()V
+ .registers 1
+ invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+{test_groups}
+
+{main_func}
+
+# }}
+"""
+
+ MAIN_FUNCTION_TEMPLATE = """
+# public static void main(String[] args) {{
+.method public static main([Ljava/lang/String;)V
+ .locals 2
+
+ {test_group_invoke}
+
+ return-void
+.end method
+# }}
+"""
+
+ TEST_GROUP_INVOKE_TEMPLATE = """
+# {test_name}();
+ invoke-static {{}}, {test_name}()V
+"""
+
+ def __init__(self):
+ """
+ Initialize this MainClass. We start out with no tests.
+ """
+ self.tests = set()
+
+ def add_test(self, ty):
+ """
+ Add a test for the concrete type 'ty'
+ """
+ self.tests.add(Func(ty))
+
+ def get_expected(self):
+ """
+ Get the expected output of this test.
+ """
+ all_tests = sorted(self.tests)
+ return filter_blanks("\n".join(a.get_expected() for a in all_tests))
+
+ def get_name(self):
+ """
+ Gets the name of this class
+ """
+ return "Main"
+
+ def __str__(self):
+ """
+ Print the smali code for this test.
+ """
+ all_tests = sorted(self.tests)
+ test_invoke = ""
+ test_groups = ""
+ for t in all_tests:
+ test_groups += str(t)
+ for t in all_tests:
+ test_invoke += self.TEST_GROUP_INVOKE_TEMPLATE.format(test_name=t.get_name())
+ main_func = self.MAIN_FUNCTION_TEMPLATE.format(test_group_invoke=test_invoke)
+
+ return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
+ test_groups = test_groups,
+ main_func = main_func)
+
+class Func(mixins.Named, mixins.NameComparableMixin):
+ """
+ A function that tests the functionality of a concrete type. Should only be
+ constructed by MainClass.add_test.
+ """
+
+ TEST_FUNCTION_TEMPLATE = """
+# public static void {fname}() {{
+# try {{
+# System.out.println("About to initialize {tree}");
+# {farg} v = new {farg}();
+# System.out.println("Initialized {tree}");
+# v.touchAll();
+# System.out.println("All of {tree} hierarchy initialized");
+# return;
+# }} catch (Error e) {{
+# e.printStackTrace(System.out);
+# return;
+# }}
+# }}
+.method public static {fname}()V
+ .locals 7
+ :call_{fname}_try_start
+ sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ const-string v3, "About to initialize {tree}"
+ invoke-virtual {{v2, v3}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+ new-instance v6, L{farg};
+ invoke-direct {{v6}}, L{farg};-><init>()V
+
+ const-string v3, "Initialized {tree}"
+ invoke-virtual {{v2, v3}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+ invoke-virtual {{v6}}, L{farg};->touchAll()V
+
+ const-string v3, "All of {tree} hierarchy initialized"
+ invoke-virtual {{v2, v3}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+
+ return-void
+ :call_{fname}_try_end
+ .catch Ljava/lang/Error; {{:call_{fname}_try_start .. :call_{fname}_try_end}} :error_{fname}_start
+ :error_{fname}_start
+ move-exception v3
+ sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ invoke-virtual {{v3,v2}}, Ljava/lang/Error;->printStackTrace(Ljava/io/PrintStream;)V
+ return-void
+.end method
+"""
+
+ OUTPUT_FORMAT = """
+About to initialize {tree}
+{initialize_output}
+Initialized {tree}
+{touch_output}
+All of {tree} hierarchy initialized
+""".strip()
+
+ def __init__(self, farg):
+ """
+ Initialize a test function for the given argument
+ """
+ self.farg = farg
+
+ def __str__(self):
+ """
+ Print the smali code for this test function.
+ """
+ return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name(),
+ farg=self.farg.get_name(),
+ tree = self.farg.get_tree())
+
+ def get_name(self):
+ """
+ Gets the name of this test function
+ """
+ return "TEST_FUNC_{}".format(self.farg.get_name())
+
+ def get_expected(self):
+ """
+ Get the expected output of this function.
+ """
+ return self.OUTPUT_FORMAT.format(
+ tree = self.farg.get_tree(),
+ initialize_output = self.farg.get_initialize_output().strip(),
+ touch_output = self.farg.get_touch_output().strip())
+
+class TestClass(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin):
+ """
+ A class that will be instantiated to test interface initialization order.
+ """
+
+ TEST_CLASS_TEMPLATE = """{copyright}
+
+.class public L{class_name};
+.super Ljava/lang/Object;
+{implements_spec}
+
+# public class {class_name} implements {ifaces} {{
+#
+# public {class_name}() {{
+# }}
+.method public constructor <init>()V
+ .locals 2
+ invoke-direct {{p0}}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
+
+# public void marker() {{
+# return;
+# }}
+.method public marker()V
+ .locals 0
+ return-void
+.end method
+
+# public void touchAll() {{
+.method public touchAll()V
+ .locals 2
+ sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
+ {touch_calls}
+ return-void
+.end method
+# }}
+# }}
+"""
+
+ IMPLEMENTS_TEMPLATE = """
+.implements L{iface_name};
+"""
+
+ TOUCH_CALL_TEMPLATE = """
+# System.out.println("{class_name} touching {iface_name}");
+# {iface_name}.field.touch();
+ const-string v1, "{class_name} touching {iface_name}"
+ invoke-virtual {{v0, v1}}, Ljava/io/PrintStream;->println(Ljava/lang/Object;)V
+ sget-object v1, L{iface_name};->field:LDisplayer;
+ invoke-virtual {{v1}}, LDisplayer;->touch()V
+"""
+
+ TOUCH_OUTPUT_TEMPLATE = """
+{class_name} touching {iface_name}
+{touch_output}
+""".strip()
+
+ def __init__(self, ifaces):
+ """
+ Initialize this test class which implements the given interfaces
+ """
+ self.ifaces = ifaces
+ self.class_name = "CLASS_"+gensym()
+
+ def get_name(self):
+ """
+ Gets the name of this interface
+ """
+ return self.class_name
+
+ def get_tree(self):
+ """
+ Print out a representation of the type tree of this class
+ """
+ return "[{fname} {iftree}]".format(fname = self.get_name(), iftree = print_tree(self.ifaces))
+
+ def get_initialize_output(self):
+ return "\n".join(map(lambda i: i.get_initialize_output().strip(), dump_tree(self.ifaces)))
+
+ def get_touch_output(self):
+ return "\n".join(map(lambda a: self.TOUCH_OUTPUT_TEMPLATE.format(
+ class_name = self.class_name,
+ iface_name = a.get_name(),
+ touch_output = a.get_touch_output()).strip(),
+ self.get_all_interfaces()))
+
+ def get_all_interfaces(self):
+ """
+ Returns a set of all interfaces this class transitively implements
+ """
+ return sorted(set(dump_tree(self.ifaces)))
+
+ def __str__(self):
+ """
+ Print the smali code for this class.
+ """
+ s_ifaces = '\n'.join(map(lambda a: self.IMPLEMENTS_TEMPLATE.format(iface_name = a.get_name()),
+ self.ifaces))
+ j_ifaces = ', '.join(map(lambda a: a.get_name(), self.ifaces))
+ touches = '\n'.join(map(lambda a: self.TOUCH_CALL_TEMPLATE.format(class_name = self.class_name,
+ iface_name = a.get_name()),
+ self.get_all_interfaces()))
+ return self.TEST_CLASS_TEMPLATE.format(copyright = get_copyright('smali'),
+ implements_spec = s_ifaces,
+ ifaces = j_ifaces,
+ class_name = self.class_name,
+ touch_calls = touches)
+
+class TestInterface(mixins.DumpMixin, mixins.Named, mixins.NameComparableMixin, mixins.SmaliFileMixin):
+ """
+ An interface that will be used to test default method resolution order.
+ """
+
+ TEST_INTERFACE_TEMPLATE = """{copyright}
+.class public abstract interface L{class_name};
+.super Ljava/lang/Object;
+{implements_spec}
+
+# public interface {class_name} {extends} {ifaces} {{
+# public static final Displayer field = new Displayer("{tree}");
+.field public final static field:LDisplayer;
+
+.method public static constructor <clinit>()V
+ .locals 3
+ const-string v2, "{tree}"
+ new-instance v1, LDisplayer;
+ invoke-direct {{v1, v2}}, LDisplayer;-><init>(Ljava/lang/String;)V
+ sput-object v1, L{class_name};->field:LDisplayer;
+ return-void
+.end method
+
+# public void marker();
+.method public abstract marker()V
+.end method
+
+{funcs}
+
+# }}
+"""
+
+ DEFAULT_FUNC_TEMPLATE = """
+# public default void {class_name}_DEFAULT_FUNC() {{
+# return;
+# }}
+.method public {class_name}_DEFAULT_FUNC()V
+ .locals 0
+ return-void
+.end method
+"""
+ IMPLEMENTS_TEMPLATE = """
+.implements L{iface_name};
+"""
+
+ OUTPUT_TEMPLATE = "initialization of {tree}"
+
+ def __init__(self, ifaces, default):
+ """
+ Initialize interface with the given super-interfaces
+ """
+ self.ifaces = ifaces
+ self.default = default
+ end = "_DEFAULT" if default else ""
+ self.class_name = "INTERFACE_"+gensym()+end
+ self.cloned = False
+ self.initialized = False
+
+ def clone(self):
+ """
+ Clones this interface, returning a new one with the same structure but
+ different name.
+ """
+ return TestInterface(tuple(map(lambda a: a.clone(), self.ifaces)), self.default)
+
+ def get_name(self):
+ """
+ Gets the name of this interface
+ """
+ return self.class_name
+
+ def __iter__(self):
+ """
+ Performs depth-first traversal of the interface tree this interface is the
+ root of. Does not filter out repeats.
+ """
+ for i in self.ifaces:
+ yield i
+ yield from i
+
+ def get_tree(self):
+ """
+ Print out a representation of the type tree of this class
+ """
+ return "[{class_name} {iftree}]".format(class_name = self.get_name(),
+ iftree = print_tree(self.ifaces))
+
+ def get_initialize_output(self):
+ """
+ Returns the expected output upon the class that implements this interface being initialized.
+ """
+ if self.default and not self.initialized:
+ self.initialized = True
+ return self.OUTPUT_TEMPLATE.format(tree = self.get_tree())
+ else:
+ return ""
+
+ def get_touch_output(self):
+ """
+ Returns the expected output upon this interface being touched.
+ """
+ if not self.default and not self.initialized:
+ self.initialized = True
+ return self.OUTPUT_TEMPLATE.format(tree = self.get_tree())
+ else:
+ return ""
+
+ def __str__(self):
+ """
+ Print the smali code for this interface.
+ """
+ s_ifaces = '\n'.join(map(lambda a: self.IMPLEMENTS_TEMPLATE.format(iface_name = a.get_name()),
+ self.ifaces))
+ j_ifaces = ', '.join(map(lambda a: a.get_name(), self.ifaces))
+ if self.default:
+ funcs = self.DEFAULT_FUNC_TEMPLATE.format(class_name = self.class_name)
+ else:
+ funcs = ""
+ return self.TEST_INTERFACE_TEMPLATE.format(copyright = get_copyright('smali'),
+ implements_spec = s_ifaces,
+ extends = "extends" if len(self.ifaces) else "",
+ ifaces = j_ifaces,
+ funcs = funcs,
+ tree = self.get_tree(),
+ class_name = self.class_name)
+
+def dump_tree(ifaces):
+ """
+ Yields all the interfaces transitively implemented by the set in
+ reverse-depth-first order
+ """
+ for i in ifaces:
+ yield from dump_tree(i.ifaces)
+ yield i
+
+def print_tree(ifaces):
+ """
+ Prints the tree for the given ifaces.
+ """
+ return " ".join(i.get_tree() for i in ifaces)
+
+def clone_all(l):
+ return tuple(a.clone() for a in l)
+
+# Cached output of subtree_sizes for speed of access.
+SUBTREES = [set(tuple(l) for l in subtree_sizes(i))
+ for i in range(MAX_IFACE_DEPTH + 1)]
+
+def create_test_classes():
+ """
+ Yield all the test classes with the different interface trees
+ """
+ for num in range(1, MAX_IFACE_DEPTH + 1):
+ for split in SUBTREES[num]:
+ ifaces = []
+ for sub in split:
+ ifaces.append(list(create_interface_trees(sub)))
+ for supers in itertools.product(*ifaces):
+ yield TestClass(clone_all(supers))
+ for i in range(len(set(dump_tree(supers)) - set(supers))):
+ ns = clone_all(supers)
+ selected = sorted(set(dump_tree(ns)) - set(ns))[i]
+ yield TestClass(tuple([selected] + list(ns)))
+
+def create_interface_trees(num):
+ """
+ Yield all the interface trees up to 'num' depth.
+ """
+ if num == 0:
+ yield TestInterface(tuple(), False)
+ yield TestInterface(tuple(), True)
+ return
+ for split in SUBTREES[num]:
+ ifaces = []
+ for sub in split:
+ ifaces.append(list(create_interface_trees(sub)))
+ for supers in itertools.product(*ifaces):
+ yield TestInterface(clone_all(supers), False)
+ yield TestInterface(clone_all(supers), True)
+ # TODO Should add on some from higher up the tree.
+
+def create_all_test_files():
+ """
+ Creates all the objects representing the files in this test. They just need to
+ be dumped.
+ """
+ mc = MainClass()
+ classes = {mc}
+ for clazz in create_test_classes():
+ classes.add(clazz)
+ for i in dump_tree(clazz.ifaces):
+ classes.add(i)
+ mc.add_test(clazz)
+ return mc, classes
+
+def main(argv):
+ smali_dir = Path(argv[1])
+ if not smali_dir.exists() or not smali_dir.is_dir():
+ print("{} is not a valid smali dir".format(smali_dir), file=sys.stderr)
+ sys.exit(1)
+ expected_txt = Path(argv[2])
+ mainclass, all_files = create_all_test_files()
+ with expected_txt.open('w') as out:
+ print(mainclass.get_expected(), file=out)
+ for f in all_files:
+ f.dump(smali_dir)
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index db16b97ea6..e114a2e9f3 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -214,13 +214,29 @@ TEST_ART_TIMING_SENSITIVE_RUN_TESTS := \
055-enum-performance \
133-static-invoke-super
- # disable timing sensitive tests on "dist" builds.
+# disable timing sensitive tests on "dist" builds.
ifdef dist_goal
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
$(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), $(TEST_ART_TIMING_SENSITIVE_RUN_TESTS), $(ALL_ADDRESS_SIZES))
endif
+# Tests that require python3.
+TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS := \
+ 960-default-smali \
+ 961-default-iface-resolution-generated \
+ 964-default-iface-init-generated \
+
+# Check if we have python3 to run our tests.
+ifeq ($(wildcard /usr/bin/python3),)
+ $(warning "No python3 found. Disabling tests: $(TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS)")
+
+ # Currently disable tests requiring python3 when it is not installed.
+ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+ $(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \
+ $(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), $(TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS), $(ALL_ADDRESS_SIZES))
+endif
+
TEST_ART_TIMING_SENSITIVE_RUN_TESTS :=
# Note 116-nodex2oat is not broken per-se it just doesn't (and isn't meant to) work with --prebuild.
@@ -313,13 +329,15 @@ ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,target,$(RUN_TYPES),$(PREBUIL
$(PICTEST_TYPES),$(DEBUGGABLE_TYPES),130-hprof,$(ALL_ADDRESS_SIZES))
# 131 is an old test. The functionality has been implemented at an earlier stage and is checked
-# in tests 138.
-ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+# in tests 138. Blacklisted for debug builds since these builds have duplicate classes checks which
+# punt to interpreter.
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),debug,$(PREBUILD_TYPES), \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \
$(PICTEST_TYPES),$(DEBUGGABLE_TYPES),131-structural-change,$(ALL_ADDRESS_SIZES))
-# 138-duplicate-classes-check. Turned off temporarily, b/21333911.
-ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
+# 138-duplicate-classes-check. Turned on for debug builds since debug builds have duplicate classes
+# checks enabled, b/2133391.
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),ndebug,$(PREBUILD_TYPES), \
$(COMPILER_TYPES),$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES),$(IMAGE_TYPES), \
$(PICTEST_TYPES),$(DEBUGGABLE_TYPES),138-duplicate-classes-check,$(ALL_ADDRESS_SIZES))
@@ -469,6 +487,8 @@ TEST_ART_BROKEN_OPTIMIZING_MIPS_RUN_TESTS := \
530-checker-regression-reftype-final \
532-checker-nonnull-arrayset \
534-checker-bce-deoptimization \
+ 536-checker-intrinsic-optimization \
+ 537-checker-debuggable \
ifeq (mips,$(TARGET_ARCH))
ifneq (,$(filter optimizing,$(COMPILER_TYPES)))
@@ -519,8 +539,10 @@ TEST_ART_BROKEN_OPTIMIZING_DEBUGGABLE_RUN_TESTS :=
# Tests that should fail in the read barrier configuration.
# 137: Read barrier forces interpreter. Cannot run this with the interpreter.
+# 141: Class unloading test is flaky with CC since CC seems to occasionally keep class loaders live.
TEST_ART_BROKEN_READ_BARRIER_RUN_TESTS := \
- 137-cfi
+ 137-cfi \
+ 141-class-unload
ifeq ($(ART_USE_READ_BARRIER),true)
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
diff --git a/test/etc/default-build b/test/etc/default-build
index c281bca3f5..c92402b529 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -26,6 +26,8 @@ while true; do
option="$1"
DX_FLAGS="${DX_FLAGS} $option"
shift
+ elif [ "x$1" = "x--jvm" ]; then
+ shift
elif expr "x$1" : "x--" >/dev/null 2>&1; then
echo "unknown $0 option: $1" 1>&2
exit 1
diff --git a/test/run-all-tests b/test/run-all-tests
index 13490c46e4..76283b7a8d 100755
--- a/test/run-all-tests
+++ b/test/run-all-tests
@@ -41,6 +41,9 @@ while true; do
if [ "x$1" = "x--host" ]; then
run_args="${run_args} --host"
shift
+ elif [ "x$1" = "x--use-java-home" ]; then
+ run_args="${run_args} --use-java-home"
+ shift
elif [ "x$1" = "x--jvm" ]; then
run_args="${run_args} --jvm"
shift
@@ -133,7 +136,7 @@ if [ "$usage" = "yes" ]; then
echo " --debug --dev --host --interpreter --jit --jvm --no-optimize"
echo " --no-verify -O --update --valgrind --zygote --64 --relocate"
echo " --prebuild --always-clean --gcstress --gcverify --trace"
- echo " --no-patchoat --no-dex2oat"
+ echo " --no-patchoat --no-dex2oat --use-java-home"
echo " Specific Runtime Options:"
echo " --seq Run tests one-by-one, avoiding failures caused by busy CPU"
) 1>&2
diff --git a/test/run-test b/test/run-test
index a5b6e92869..1b71f33209 100755
--- a/test/run-test
+++ b/test/run-test
@@ -40,7 +40,6 @@ else
tmp_dir="${TMPDIR}/$USER/${test_dir}"
fi
checker="${progdir}/../tools/checker/checker.py"
-
export JAVA="java"
export JAVAC="javac -g"
export RUN="${progdir}/etc/run-test-jar"
@@ -155,6 +154,15 @@ while true; do
DEX_LOCATION=$tmp_dir
run_args="${run_args} --host"
shift
+ elif [ "x$1" = "x--use-java-home" ]; then
+ if [ -n "${JAVA_HOME}" ]; then
+ export JAVA="${JAVA_HOME}/bin/java"
+ export JAVAC="${JAVA_HOME}/bin/javac -g"
+ else
+ echo "Passed --use-java-home without JAVA_HOME variable set!"
+ usage="yes"
+ fi
+ shift
elif [ "x$1" = "x--jvm" ]; then
target_mode="no"
runtime="jvm"
@@ -162,6 +170,7 @@ while true; do
NEED_DEX="false"
USE_JACK="false"
run_args="${run_args} --jvm"
+ build_args="${build_args} --jvm"
shift
elif [ "x$1" = "x-O" ]; then
lib="libart.so"
@@ -560,6 +569,9 @@ if [ "$usage" = "yes" ]; then
echo " --invoke-with Pass --invoke-with option to runtime."
echo " --dalvik Use Dalvik (off by default)."
echo " --jvm Use a host-local RI virtual machine."
+ echo " --use-java-home Use the JAVA_HOME environment variable"
+ echo " to find the java compiler and runtime"
+ echo " (if applicable) to run the test with."
echo " --output-path [path] Location where to store the build" \
"files."
echo " --64 Run the test in 64-bit mode"
@@ -637,18 +649,24 @@ if [[ "$TEST_NAME" =~ ^[0-9]+-checker- ]]; then
# on a particular DEX output, keep building them with dx for now (b/19467889).
USE_JACK="false"
- if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" -a "$debuggable" = "no" ]; then
+ if [ "$runtime" = "art" -a "$image_suffix" = "-optimizing" ]; then
# In no-prebuild mode, the compiler is only invoked if both dex2oat and
# patchoat are available. Disable Checker otherwise (b/22552692).
if [ "$prebuild_mode" = "yes" ] || [ "$have_patchoat" = "yes" -a "$have_dex2oat" = "yes" ]; then
run_checker="yes"
+
if [ "$target_mode" = "no" ]; then
cfg_output_dir="$tmp_dir"
- checker_arch_option="--arch=${host_arch_name^^}"
+ checker_args="--arch=${host_arch_name^^}"
else
cfg_output_dir="$DEX_LOCATION"
- checker_arch_option="--arch=${target_arch_name^^}"
+ checker_args="--arch=${target_arch_name^^}"
+ fi
+
+ if [ "$debuggable" = "yes" ]; then
+ checker_args="$checker_args --debuggable"
fi
+
run_args="${run_args} -Xcompiler-option --dump-cfg=$cfg_output_dir/$cfg_output \
-Xcompiler-option -j1"
fi
@@ -702,7 +720,7 @@ if [ "$dev_mode" = "yes" ]; then
if [ "$target_mode" = "yes" ]; then
adb pull $cfg_output_dir/$cfg_output &> /dev/null
fi
- "$checker" $checker_arch_option "$cfg_output" "$tmp_dir" 2>&1
+ "$checker" $checker_args "$cfg_output" "$tmp_dir" 2>&1
checker_exit="$?"
if [ "$checker_exit" = "0" ]; then
good="yes"
@@ -727,7 +745,7 @@ elif [ "$update_mode" = "yes" ]; then
if [ "$target_mode" = "yes" ]; then
adb pull $cfg_output_dir/$cfg_output &> /dev/null
fi
- "$checker" -q $checker_arch_option "$cfg_output" "$tmp_dir" >> "$output" 2>&1
+ "$checker" -q $checker_args "$cfg_output" "$tmp_dir" >> "$output" 2>&1
fi
sed -e 's/[[:cntrl:]]$//g' < "$output" >"${td_expected}"
good="yes"
@@ -768,7 +786,7 @@ else
if [ "$target_mode" = "yes" ]; then
adb pull $cfg_output_dir/$cfg_output &> /dev/null
fi
- "$checker" -q $checker_arch_option "$cfg_output" "$tmp_dir" >> "$output" 2>&1
+ "$checker" -q $checker_args "$cfg_output" "$tmp_dir" >> "$output" 2>&1
checker_exit="$?"
if [ "$checker_exit" != "0" ]; then
echo "checker exit status: $checker_exit" 1>&2
diff --git a/test/utils/python/testgen/mixins.py b/test/utils/python/testgen/mixins.py
new file mode 100644
index 0000000000..085e51def2
--- /dev/null
+++ b/test/utils/python/testgen/mixins.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015 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.
+
+"""
+Common mixins and abstract base classes (ABCs) useful for writing test generators in python
+"""
+
+import abc
+import collections.abc
+import functools
+
+class Named(metaclass=abc.ABCMeta):
+ """
+ An abc that defines a get_name method.
+ """
+
+ @abc.abstractmethod
+ def get_name(self):
+ """
+ Returns a unique name to use as the identity for implementing comparisons.
+ """
+ pass
+
+class FileLike(metaclass=abc.ABCMeta):
+ """
+ An abc that defines get_file_name and get_file_extension methods.
+ """
+
+ @abc.abstractmethod
+ def get_file_name(self):
+ """Returns the filename this object represents"""
+ pass
+
+ @abc.abstractmethod
+ def get_file_extension(self):
+ """Returns the file extension of the file this object represents"""
+ pass
+
+@functools.lru_cache(maxsize=None)
+def get_file_extension_mixin(ext):
+ """
+ Gets a mixin that defines get_file_name(self) in terms of get_name(self) with the
+ given file extension.
+ """
+
+ class FExt(object):
+ """
+ A mixin defining get_file_name(self) in terms of get_name(self)
+ """
+
+ def get_file_name(self):
+ return self.get_name() + ext
+
+ def get_file_extension(self):
+ return ext
+
+ # Register the ABCs
+ Named.register(FExt)
+ FileLike.register(FExt)
+
+ return FExt
+
+class SmaliFileMixin(get_file_extension_mixin(".smali")):
+ """
+ A mixin that defines that the file this class belongs to is get_name() + ".smali".
+ """
+ pass
+
+class NameComparableMixin(object):
+ """
+ A mixin that defines the object comparison and related functionality in terms
+ of a get_name(self) function.
+ """
+
+ def __lt__(self, other):
+ return self.get_name() < other.get_name()
+
+ def __gt__(self, other):
+ return self.get_name() > other.get_name()
+
+ def __eq__(self, other):
+ return self.get_name() == other.get_name()
+
+ def __le__(self, other):
+ return self.get_name() <= other.get_name()
+
+ def __ge__(self, other):
+ return self.get_name() >= other.get_name()
+
+ def __ne__(self, other):
+ return self.get_name() != other.get_name()
+
+ def __hash__(self):
+ return hash(self.get_name())
+
+Named.register(NameComparableMixin)
+collections.abc.Hashable.register(NameComparableMixin)
+
+class DumpMixin(metaclass=abc.ABCMeta):
+ """
+ A mixin to add support for dumping the string representation of an object to a
+ file. Requires the get_file_name(self) method be defined.
+ """
+
+ @abc.abstractmethod
+ def __str__(self):
+ """
+ Returns the data to be printed to a file by dump.
+ """
+ pass
+
+ def dump(self, directory):
+ """
+ Dump this object to a file in the given directory
+ """
+ out_file = directory / self.get_file_name()
+ if out_file.exists():
+ out_file.unlink()
+ with out_file.open('w') as out:
+ print(str(self), file=out)
+
+FileLike.register(DumpMixin)
diff --git a/test/utils/python/testgen/utils.py b/test/utils/python/testgen/utils.py
new file mode 100644
index 0000000000..769ad16ebe
--- /dev/null
+++ b/test/utils/python/testgen/utils.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2015 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.
+
+"""
+Common functions useful for writing test generators in python
+"""
+
+import itertools
+import os
+import string
+from pathlib import Path
+
+BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
+if BUILD_TOP is None:
+ print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
+ sys.exit(1)
+
+# An iterator which yields strings made from lowercase letters. First yields
+# all 1 length strings, then all 2 and so on. It does this alphabetically.
+NAME_GEN = itertools.chain.from_iterable(
+ map(lambda n: itertools.product(string.ascii_lowercase, repeat=n),
+ itertools.count(1)))
+
+def gensym():
+ """
+ Returns a new, globally unique, identifier name that is a valid Java symbol
+ on each call.
+ """
+ return ''.join(next(NAME_GEN))
+
+def filter_blanks(s):
+ """
+ Takes a string returns the same string sans empty lines
+ """
+ return "\n".join(a for a in s.split("\n") if a.strip() != "")
+
+def get_copyright(filetype = "java"):
+ """
+ Returns the standard copyright header for the given filetype
+ """
+ if filetype == "smali":
+ return "\n".join(map(lambda a: "# " + a, get_copyright("java").split("\n")))
+ else:
+ fname = filetype + ".txt"
+ with (Path(BUILD_TOP)/"development"/"docs"/"copyright-templates"/fname).open() as template:
+ return "".join(template.readlines())
+
+def subtree_sizes(n):
+ """
+ A generator that yields a tuple containing a possible arrangement of subtree
+ nodes for a tree with a total of 'n' leaf nodes.
+ """
+ if n == 0:
+ return
+ elif n == 1:
+ yield (0,)
+ elif n == 2:
+ yield (1, 1)
+ else:
+ for prevt in subtree_sizes(n - 1):
+ prev = list(prevt)
+ yield tuple([1] + prev)
+ for i in range(len(prev)):
+ prev[i] += 1
+ yield tuple(prev)
+ prev[i] -= 1
+