diff options
| -rw-r--r-- | runtime/art_method-inl.h | 5 | ||||
| -rwxr-xr-x | test/978-virtual-interface/build | 20 | ||||
| -rw-r--r-- | test/978-virtual-interface/expected.txt | 1 | ||||
| -rw-r--r-- | test/978-virtual-interface/info.txt | 7 | ||||
| -rw-r--r-- | test/978-virtual-interface/smali/Iface.smali | 110 | ||||
| -rw-r--r-- | test/978-virtual-interface/smali/Main.smali | 50 | ||||
| -rw-r--r-- | test/978-virtual-interface/smali/Subtype.smali | 40 | ||||
| -rw-r--r-- | test/978-virtual-interface/smali/Target.smali | 40 |
8 files changed, 271 insertions, 2 deletions
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index 73c6cf16d4..1aa6a00495 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -227,9 +227,10 @@ inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) { case kDirect: return !IsDirect() || IsStatic(); case kVirtual: { - // We have an error if we are direct or a non-default, non-miranda interface method. + // We have an error if we are direct or a non-copied (i.e. not part of a real class) interface + // method. mirror::Class* methods_class = GetDeclaringClass(); - return IsDirect() || (methods_class->IsInterface() && !IsDefault() && !IsMiranda()); + return IsDirect() || (methods_class->IsInterface() && !IsCopied()); } case kSuper: // Constructors and static methods are called with invoke-direct. diff --git a/test/978-virtual-interface/build b/test/978-virtual-interface/build new file mode 100755 index 0000000000..14230c2e1d --- /dev/null +++ b/test/978-virtual-interface/build @@ -0,0 +1,20 @@ +#!/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 + +./default-build "$@" --experimental default-methods diff --git a/test/978-virtual-interface/expected.txt b/test/978-virtual-interface/expected.txt new file mode 100644 index 0000000000..99071b1d4e --- /dev/null +++ b/test/978-virtual-interface/expected.txt @@ -0,0 +1 @@ +Recieved expected ICCE error! diff --git a/test/978-virtual-interface/info.txt b/test/978-virtual-interface/info.txt new file mode 100644 index 0000000000..0b8a39f550 --- /dev/null +++ b/test/978-virtual-interface/info.txt @@ -0,0 +1,7 @@ +Smali-based regression test for b/32201623 + +This test cannot be run with --jvm. + +This test checks that we correctly detect when one attempts to invoke an +interface method via the invoke-virtual opcode and that correct exceptions are +sent. diff --git a/test/978-virtual-interface/smali/Iface.smali b/test/978-virtual-interface/smali/Iface.smali new file mode 100644 index 0000000000..9c3ef7a0b4 --- /dev/null +++ b/test/978-virtual-interface/smali/Iface.smali @@ -0,0 +1,110 @@ +# /* +# * 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. +# */ +# +# // Methods are sorted in alphabetical order in dex file. We need 10 padding +# // methods to ensure the 11'th target lines up to the same vtable slot as the +# // first Subtype virtual method (the other 10 are the java/lang/Object; +# // methods). +# interface Iface { +# public default void fakeMethod_A() {} +# public default void fakeMethod_B() {} +# public default void fakeMethod_C() {} +# public default void fakeMethod_D() {} +# public default void fakeMethod_E() {} +# public default void fakeMethod_F() {} +# public default void fakeMethod_G() {} +# public default void fakeMethod_H() {} +# public default void fakeMethod_I() {} +# public default void fakeMethod_J() {} +# public default void fakeMethod_K() {} +# public default void fakeMethod_Target() {} +# } + +.class public abstract interface LIface; + +.super Ljava/lang/Object; + +# // 1 +.method public fakeMethod_A()V + .locals 0 + return-void +.end method + +# // 2 +.method public fakeMethod_B()V + .locals 0 + return-void +.end method + +# // 3 +.method public fakeMethod_C()V + .locals 0 + return-void +.end method + +# // 4 +.method public fakeMethod_D()V + .locals 0 + return-void +.end method + +# // 5 +.method public fakeMethod_E()V + .locals 0 + return-void +.end method + +# // 5 +.method public fakeMethod_F()V + .locals 0 + return-void +.end method + +# // 6 +.method public fakeMethod_G()V + .locals 0 + return-void +.end method + +# // 7 +.method public fakeMethod_H()V + .locals 0 + return-void +.end method + +# // 8 +.method public fakeMethod_I()V + .locals 0 + return-void +.end method + +# // 9 +.method public fakeMethod_J()V + .locals 0 + return-void +.end method + +# // 10 +.method public fakeMethod_K()V + .locals 0 + return-void +.end method + +# // 11 +.method public fakeMethod_Target()V + .locals 0 + return-void +.end method diff --git a/test/978-virtual-interface/smali/Main.smali b/test/978-virtual-interface/smali/Main.smali new file mode 100644 index 0000000000..61b82f3f7b --- /dev/null +++ b/test/978-virtual-interface/smali/Main.smali @@ -0,0 +1,50 @@ +# /* +# * 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[] s) { +# Subtype s = new Subtype(); +# try { +# s.callPackage(); +# System.out.println("No error thrown!"); +# } catch (IncompatibleClassChangeError e) { +# System.out.println("Recieved expected ICCE error!"); +# } +# } +# } + +.class public LMain; + +.super Ljava/lang/Object; + +.method public static main([Ljava/lang/String;)V + .locals 3 + + new-instance v0, LSubtype; + invoke-direct {v0}, LSubtype;-><init>()V + sget-object v2, Ljava/lang/System;->out:Ljava/io/PrintStream; + :try_start + invoke-virtual {v0}, LSubtype;->callPackage()V + const-string v1, "No error thrown!" + invoke-virtual {v2, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V + return-void + :try_end + .catch Ljava/lang/IncompatibleClassChangeError; {:try_start .. :try_end} :error_start + :error_start + const-string v1, "Recieved expected ICCE error!" + invoke-virtual {v2, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V + return-void +.end method diff --git a/test/978-virtual-interface/smali/Subtype.smali b/test/978-virtual-interface/smali/Subtype.smali new file mode 100644 index 0000000000..f876cf961b --- /dev/null +++ b/test/978-virtual-interface/smali/Subtype.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 class Subtype extends pkg.Target implements Iface{ +# public void callPackage() { +# // Fake into a virtual call. +# // ((Iface)this).fakeMethod_Target(); +# } +# } + +.class public LSubtype; + +.super Lpkg/Target; + +.implements LIface; + +.method public constructor <init>()V + .locals 0 + invoke-direct {p0}, Lpkg/Target;-><init>()V + return-void +.end method + +.method public callPackage()V + .locals 0 + invoke-virtual {p0}, LIface;->fakeMethod_Target()V + return-void +.end method diff --git a/test/978-virtual-interface/smali/Target.smali b/test/978-virtual-interface/smali/Target.smali new file mode 100644 index 0000000000..70108fb6bf --- /dev/null +++ b/test/978-virtual-interface/smali/Target.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. +# */ +# +# package pkg; +# public class Target { +# public void packageMethod() { +# System.out.println("Package method called!"); +# } +# } + +.class public Lpkg/Target; + +.super Ljava/lang/Object; + +.method public constructor <init>()V + .locals 0 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V + return-void +.end method + +.method packageMethod()V + .locals 2 + const-string v1, "Package method called!" + sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; + invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V + return-void +.end method |