Add initial default method support to Art

This commit starts the process of adding default methods and their
associated pieces to ART.

This adds full support for calling default methods using
invoke-interface and invoke-virtual on objects implementing the
interfaces. Verifier is changed to allow this when the runtime is
started with -Xexperimental:default-methods.

This also adds support for defining and calling static methods on
interface classes with invoke-static.

Directly calling overridden default methods using invoke-super is not
yet supported.

This adds 5 new run-tests for this functionality.

Bug: 24618811

Change-Id: I35ca800d99d3329348b277789b70ceeeba6e7f03
diff --git a/test/960-default-smali/build b/test/960-default-smali/build
new file mode 100755
index 0000000..c786687
--- /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 0000000..7671eed
--- /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 0000000..eb596e2
--- /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 0000000..e378b06
--- /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 0000000..e755612
--- /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 0000000..ab63aee
--- /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 0000000..d847dd1
--- /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 0000000..08a8508
--- /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 0000000..32f3b7e
--- /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 0000000..bae6250
--- /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 0000000..60ffa26
--- /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 0000000..3eaa089
--- /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 0000000..446f2a4
--- /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 0000000..28530ff
--- /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 0000000..ace1798
--- /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 0000000..31fc2e7
--- /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 0000000..82065ea
--- /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 0000000..72fb58a
--- /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 0000000..93f3d62
--- /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 0000000..0aa41f7
--- /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 0000000..b2bf1f0
--- /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)