Version 2.0.68
Cherry pick: Don't inline catch-handlers with potentially unknown exception guards.
CL: https://r8-review.googlesource.com/c/r8/+/50380
Bug: 153514654
Cherry pick: Update status for Regress131349148.
CL: https://r8-review.googlesource.com/c/r8/+/50403
Change-Id: I8e48d042437834310d8212ea7ffa703ea5a884c1
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index bbc8638..d386137 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "2.0.67";
+ public static final String LABEL = "2.0.68";
private Version() {
}
diff --git a/src/main/java/com/android/tools/r8/androidapi/AvailableApiExceptions.java b/src/main/java/com/android/tools/r8/androidapi/AvailableApiExceptions.java
new file mode 100644
index 0000000..c44f1f4
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/androidapi/AvailableApiExceptions.java
@@ -0,0 +1,405 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.androidapi;
+
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.SetUtils;
+import java.util.Set;
+
+/**
+ * Provides a mapping of API levels to exceptions introduced at that API level.
+ *
+ * <p>The mapping is only provided up to excluding the API level 21 (Android L) at which point the
+ * verification issue for unresolved exception types was fixed.
+ *
+ * <p>See b/153514654 and b/131349148.
+ *
+ * <p>See GenerateAvailableApiExceptions.main in tests module for generating the buildMap function.
+ */
+public class AvailableApiExceptions {
+
+ private final Set<DexType> exceptions;
+
+ public AvailableApiExceptions(InternalOptions options) {
+ assert options.minApiLevel < AndroidApiLevel.L.getLevel();
+ exceptions = build(options.itemFactory, options.minApiLevel);
+ }
+
+ public boolean canCauseVerificationError(DexType type) {
+ return !exceptions.contains(type);
+ }
+
+ /** The content of this method can be regenerated with GenerateAvailableExceptions.main. */
+ public static Set<DexType> build(DexItemFactory factory, int minApiLevel) {
+ Set<DexType> types = SetUtils.newIdentityHashSet(333);
+ if (minApiLevel >= 1) {
+ types.add(factory.createType("Landroid/app/PendingIntent$CanceledException;"));
+ types.add(factory.createType("Landroid/content/ActivityNotFoundException;"));
+ types.add(factory.createType("Landroid/content/IntentFilter$MalformedMimeTypeException;"));
+ types.add(factory.createType("Landroid/content/ReceiverCallNotAllowedException;"));
+ types.add(factory.createType("Landroid/content/pm/PackageManager$NameNotFoundException;"));
+ types.add(factory.createType("Landroid/content/res/Resources$NotFoundException;"));
+ types.add(factory.createType("Landroid/database/CursorIndexOutOfBoundsException;"));
+ types.add(factory.createType("Landroid/database/SQLException;"));
+ types.add(factory.createType("Landroid/database/StaleDataException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteAbortException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteConstraintException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteDatabaseCorruptException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteDiskIOException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteDoneException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteFullException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteMisuseException;"));
+ types.add(factory.createType("Landroid/net/ParseException;"));
+ types.add(factory.createType("Landroid/opengl/GLException;"));
+ types.add(factory.createType("Landroid/os/BadParcelableException;"));
+ types.add(factory.createType("Landroid/os/DeadObjectException;"));
+ types.add(factory.createType("Landroid/os/ParcelFormatException;"));
+ types.add(factory.createType("Landroid/os/RemoteException;"));
+ types.add(factory.createType("Landroid/provider/Settings$SettingNotFoundException;"));
+ types.add(factory.createType("Landroid/test/AssertionFailedError;"));
+ types.add(factory.createType("Landroid/test/ComparisonFailure;"));
+ types.add(factory.createType("Landroid/util/AndroidException;"));
+ types.add(factory.createType("Landroid/util/AndroidRuntimeException;"));
+ types.add(factory.createType("Landroid/util/TimeFormatException;"));
+ types.add(factory.createType("Landroid/view/InflateException;"));
+ types.add(factory.createType("Landroid/view/Surface$OutOfResourcesException;"));
+ types.add(factory.createType("Landroid/view/SurfaceHolder$BadSurfaceTypeException;"));
+ types.add(factory.createType("Landroid/view/WindowManager$BadTokenException;"));
+ types.add(factory.createType("Landroid/widget/RemoteViews$ActionException;"));
+ types.add(factory.createType("Ljava/io/CharConversionException;"));
+ types.add(factory.createType("Ljava/io/EOFException;"));
+ types.add(factory.createType("Ljava/io/FileNotFoundException;"));
+ types.add(factory.createType("Ljava/io/IOException;"));
+ types.add(factory.createType("Ljava/io/InterruptedIOException;"));
+ types.add(factory.createType("Ljava/io/InvalidClassException;"));
+ types.add(factory.createType("Ljava/io/InvalidObjectException;"));
+ types.add(factory.createType("Ljava/io/NotActiveException;"));
+ types.add(factory.createType("Ljava/io/NotSerializableException;"));
+ types.add(factory.createType("Ljava/io/ObjectStreamException;"));
+ types.add(factory.createType("Ljava/io/OptionalDataException;"));
+ types.add(factory.createType("Ljava/io/StreamCorruptedException;"));
+ types.add(factory.createType("Ljava/io/SyncFailedException;"));
+ types.add(factory.createType("Ljava/io/UTFDataFormatException;"));
+ types.add(factory.createType("Ljava/io/UnsupportedEncodingException;"));
+ types.add(factory.createType("Ljava/io/WriteAbortedException;"));
+ types.add(factory.createType("Ljava/lang/AbstractMethodError;"));
+ types.add(factory.createType("Ljava/lang/ArithmeticException;"));
+ types.add(factory.createType("Ljava/lang/ArrayIndexOutOfBoundsException;"));
+ types.add(factory.createType("Ljava/lang/ArrayStoreException;"));
+ types.add(factory.createType("Ljava/lang/AssertionError;"));
+ types.add(factory.createType("Ljava/lang/ClassCastException;"));
+ types.add(factory.createType("Ljava/lang/ClassCircularityError;"));
+ types.add(factory.createType("Ljava/lang/ClassFormatError;"));
+ types.add(factory.createType("Ljava/lang/ClassNotFoundException;"));
+ types.add(factory.createType("Ljava/lang/CloneNotSupportedException;"));
+ types.add(factory.createType("Ljava/lang/EnumConstantNotPresentException;"));
+ types.add(factory.createType("Ljava/lang/Error;"));
+ types.add(factory.createType("Ljava/lang/Exception;"));
+ types.add(factory.createType("Ljava/lang/ExceptionInInitializerError;"));
+ types.add(factory.createType("Ljava/lang/IllegalAccessError;"));
+ types.add(factory.createType("Ljava/lang/IllegalAccessException;"));
+ types.add(factory.createType("Ljava/lang/IllegalArgumentException;"));
+ types.add(factory.createType("Ljava/lang/IllegalMonitorStateException;"));
+ types.add(factory.createType("Ljava/lang/IllegalStateException;"));
+ types.add(factory.createType("Ljava/lang/IllegalThreadStateException;"));
+ types.add(factory.createType("Ljava/lang/IncompatibleClassChangeError;"));
+ types.add(factory.createType("Ljava/lang/IndexOutOfBoundsException;"));
+ types.add(factory.createType("Ljava/lang/InstantiationError;"));
+ types.add(factory.createType("Ljava/lang/InstantiationException;"));
+ types.add(factory.createType("Ljava/lang/InternalError;"));
+ types.add(factory.createType("Ljava/lang/InterruptedException;"));
+ types.add(factory.createType("Ljava/lang/LinkageError;"));
+ types.add(factory.createType("Ljava/lang/NegativeArraySizeException;"));
+ types.add(factory.createType("Ljava/lang/NoClassDefFoundError;"));
+ types.add(factory.createType("Ljava/lang/NoSuchFieldError;"));
+ types.add(factory.createType("Ljava/lang/NoSuchFieldException;"));
+ types.add(factory.createType("Ljava/lang/NoSuchMethodError;"));
+ types.add(factory.createType("Ljava/lang/NoSuchMethodException;"));
+ types.add(factory.createType("Ljava/lang/NullPointerException;"));
+ types.add(factory.createType("Ljava/lang/NumberFormatException;"));
+ types.add(factory.createType("Ljava/lang/OutOfMemoryError;"));
+ types.add(factory.createType("Ljava/lang/RuntimeException;"));
+ types.add(factory.createType("Ljava/lang/SecurityException;"));
+ types.add(factory.createType("Ljava/lang/StackOverflowError;"));
+ types.add(factory.createType("Ljava/lang/StringIndexOutOfBoundsException;"));
+ types.add(factory.createType("Ljava/lang/ThreadDeath;"));
+ types.add(factory.createType("Ljava/lang/Throwable;"));
+ types.add(factory.createType("Ljava/lang/TypeNotPresentException;"));
+ types.add(factory.createType("Ljava/lang/UnknownError;"));
+ types.add(factory.createType("Ljava/lang/UnsatisfiedLinkError;"));
+ types.add(factory.createType("Ljava/lang/UnsupportedClassVersionError;"));
+ types.add(factory.createType("Ljava/lang/UnsupportedOperationException;"));
+ types.add(factory.createType("Ljava/lang/VerifyError;"));
+ types.add(factory.createType("Ljava/lang/VirtualMachineError;"));
+ types.add(factory.createType("Ljava/lang/annotation/AnnotationFormatError;"));
+ types.add(factory.createType("Ljava/lang/annotation/AnnotationTypeMismatchException;"));
+ types.add(factory.createType("Ljava/lang/annotation/IncompleteAnnotationException;"));
+ types.add(factory.createType("Ljava/lang/reflect/GenericSignatureFormatError;"));
+ types.add(factory.createType("Ljava/lang/reflect/InvocationTargetException;"));
+ types.add(factory.createType("Ljava/lang/reflect/MalformedParameterizedTypeException;"));
+ types.add(factory.createType("Ljava/lang/reflect/UndeclaredThrowableException;"));
+ types.add(factory.createType("Ljava/net/BindException;"));
+ types.add(factory.createType("Ljava/net/ConnectException;"));
+ types.add(factory.createType("Ljava/net/HttpRetryException;"));
+ types.add(factory.createType("Ljava/net/MalformedURLException;"));
+ types.add(factory.createType("Ljava/net/NoRouteToHostException;"));
+ types.add(factory.createType("Ljava/net/PortUnreachableException;"));
+ types.add(factory.createType("Ljava/net/ProtocolException;"));
+ types.add(factory.createType("Ljava/net/SocketException;"));
+ types.add(factory.createType("Ljava/net/SocketTimeoutException;"));
+ types.add(factory.createType("Ljava/net/URISyntaxException;"));
+ types.add(factory.createType("Ljava/net/UnknownHostException;"));
+ types.add(factory.createType("Ljava/net/UnknownServiceException;"));
+ types.add(factory.createType("Ljava/nio/BufferOverflowException;"));
+ types.add(factory.createType("Ljava/nio/BufferUnderflowException;"));
+ types.add(factory.createType("Ljava/nio/InvalidMarkException;"));
+ types.add(factory.createType("Ljava/nio/ReadOnlyBufferException;"));
+ types.add(factory.createType("Ljava/nio/channels/AlreadyConnectedException;"));
+ types.add(factory.createType("Ljava/nio/channels/AsynchronousCloseException;"));
+ types.add(factory.createType("Ljava/nio/channels/CancelledKeyException;"));
+ types.add(factory.createType("Ljava/nio/channels/ClosedByInterruptException;"));
+ types.add(factory.createType("Ljava/nio/channels/ClosedChannelException;"));
+ types.add(factory.createType("Ljava/nio/channels/ClosedSelectorException;"));
+ types.add(factory.createType("Ljava/nio/channels/ConnectionPendingException;"));
+ types.add(factory.createType("Ljava/nio/channels/FileLockInterruptionException;"));
+ types.add(factory.createType("Ljava/nio/channels/IllegalBlockingModeException;"));
+ types.add(factory.createType("Ljava/nio/channels/IllegalSelectorException;"));
+ types.add(factory.createType("Ljava/nio/channels/NoConnectionPendingException;"));
+ types.add(factory.createType("Ljava/nio/channels/NonReadableChannelException;"));
+ types.add(factory.createType("Ljava/nio/channels/NonWritableChannelException;"));
+ types.add(factory.createType("Ljava/nio/channels/NotYetBoundException;"));
+ types.add(factory.createType("Ljava/nio/channels/NotYetConnectedException;"));
+ types.add(factory.createType("Ljava/nio/channels/OverlappingFileLockException;"));
+ types.add(factory.createType("Ljava/nio/channels/UnresolvedAddressException;"));
+ types.add(factory.createType("Ljava/nio/channels/UnsupportedAddressTypeException;"));
+ types.add(factory.createType("Ljava/nio/charset/CharacterCodingException;"));
+ types.add(factory.createType("Ljava/nio/charset/CoderMalfunctionError;"));
+ types.add(factory.createType("Ljava/nio/charset/IllegalCharsetNameException;"));
+ types.add(factory.createType("Ljava/nio/charset/MalformedInputException;"));
+ types.add(factory.createType("Ljava/nio/charset/UnmappableCharacterException;"));
+ types.add(factory.createType("Ljava/nio/charset/UnsupportedCharsetException;"));
+ types.add(factory.createType("Ljava/security/AccessControlException;"));
+ types.add(factory.createType("Ljava/security/DigestException;"));
+ types.add(factory.createType("Ljava/security/GeneralSecurityException;"));
+ types.add(factory.createType("Ljava/security/InvalidAlgorithmParameterException;"));
+ types.add(factory.createType("Ljava/security/InvalidKeyException;"));
+ types.add(factory.createType("Ljava/security/InvalidParameterException;"));
+ types.add(factory.createType("Ljava/security/KeyException;"));
+ types.add(factory.createType("Ljava/security/KeyManagementException;"));
+ types.add(factory.createType("Ljava/security/KeyStoreException;"));
+ types.add(factory.createType("Ljava/security/NoSuchAlgorithmException;"));
+ types.add(factory.createType("Ljava/security/NoSuchProviderException;"));
+ types.add(factory.createType("Ljava/security/PrivilegedActionException;"));
+ types.add(factory.createType("Ljava/security/ProviderException;"));
+ types.add(factory.createType("Ljava/security/SignatureException;"));
+ types.add(factory.createType("Ljava/security/UnrecoverableEntryException;"));
+ types.add(factory.createType("Ljava/security/UnrecoverableKeyException;"));
+ types.add(factory.createType("Ljava/security/acl/AclNotFoundException;"));
+ types.add(factory.createType("Ljava/security/acl/LastOwnerException;"));
+ types.add(factory.createType("Ljava/security/acl/NotOwnerException;"));
+ types.add(factory.createType("Ljava/security/cert/CRLException;"));
+ types.add(factory.createType("Ljava/security/cert/CertPathBuilderException;"));
+ types.add(factory.createType("Ljava/security/cert/CertPathValidatorException;"));
+ types.add(factory.createType("Ljava/security/cert/CertStoreException;"));
+ types.add(factory.createType("Ljava/security/cert/CertificateEncodingException;"));
+ types.add(factory.createType("Ljava/security/cert/CertificateException;"));
+ types.add(factory.createType("Ljava/security/cert/CertificateExpiredException;"));
+ types.add(factory.createType("Ljava/security/cert/CertificateNotYetValidException;"));
+ types.add(factory.createType("Ljava/security/cert/CertificateParsingException;"));
+ types.add(factory.createType("Ljava/security/spec/InvalidKeySpecException;"));
+ types.add(factory.createType("Ljava/security/spec/InvalidParameterSpecException;"));
+ types.add(factory.createType("Ljava/sql/BatchUpdateException;"));
+ types.add(factory.createType("Ljava/sql/DataTruncation;"));
+ types.add(factory.createType("Ljava/sql/SQLException;"));
+ types.add(factory.createType("Ljava/sql/SQLWarning;"));
+ types.add(factory.createType("Ljava/text/ParseException;"));
+ types.add(factory.createType("Ljava/util/ConcurrentModificationException;"));
+ types.add(factory.createType("Ljava/util/DuplicateFormatFlagsException;"));
+ types.add(factory.createType("Ljava/util/EmptyStackException;"));
+ types.add(factory.createType("Ljava/util/FormatFlagsConversionMismatchException;"));
+ types.add(factory.createType("Ljava/util/FormatterClosedException;"));
+ types.add(factory.createType("Ljava/util/IllegalFormatCodePointException;"));
+ types.add(factory.createType("Ljava/util/IllegalFormatConversionException;"));
+ types.add(factory.createType("Ljava/util/IllegalFormatException;"));
+ types.add(factory.createType("Ljava/util/IllegalFormatFlagsException;"));
+ types.add(factory.createType("Ljava/util/IllegalFormatPrecisionException;"));
+ types.add(factory.createType("Ljava/util/IllegalFormatWidthException;"));
+ types.add(factory.createType("Ljava/util/InputMismatchException;"));
+ types.add(factory.createType("Ljava/util/InvalidPropertiesFormatException;"));
+ types.add(factory.createType("Ljava/util/MissingFormatArgumentException;"));
+ types.add(factory.createType("Ljava/util/MissingFormatWidthException;"));
+ types.add(factory.createType("Ljava/util/MissingResourceException;"));
+ types.add(factory.createType("Ljava/util/NoSuchElementException;"));
+ types.add(factory.createType("Ljava/util/TooManyListenersException;"));
+ types.add(factory.createType("Ljava/util/UnknownFormatConversionException;"));
+ types.add(factory.createType("Ljava/util/UnknownFormatFlagsException;"));
+ types.add(factory.createType("Ljava/util/concurrent/BrokenBarrierException;"));
+ types.add(factory.createType("Ljava/util/concurrent/CancellationException;"));
+ types.add(factory.createType("Ljava/util/concurrent/ExecutionException;"));
+ types.add(factory.createType("Ljava/util/concurrent/RejectedExecutionException;"));
+ types.add(factory.createType("Ljava/util/concurrent/TimeoutException;"));
+ types.add(factory.createType("Ljava/util/jar/JarException;"));
+ types.add(factory.createType("Ljava/util/prefs/BackingStoreException;"));
+ types.add(factory.createType("Ljava/util/prefs/InvalidPreferencesFormatException;"));
+ types.add(factory.createType("Ljava/util/regex/PatternSyntaxException;"));
+ types.add(factory.createType("Ljava/util/zip/DataFormatException;"));
+ types.add(factory.createType("Ljava/util/zip/ZipException;"));
+ types.add(factory.createType("Ljavax/crypto/BadPaddingException;"));
+ types.add(factory.createType("Ljavax/crypto/ExemptionMechanismException;"));
+ types.add(factory.createType("Ljavax/crypto/IllegalBlockSizeException;"));
+ types.add(factory.createType("Ljavax/crypto/NoSuchPaddingException;"));
+ types.add(factory.createType("Ljavax/crypto/ShortBufferException;"));
+ types.add(factory.createType("Ljavax/net/ssl/SSLException;"));
+ types.add(factory.createType("Ljavax/net/ssl/SSLHandshakeException;"));
+ types.add(factory.createType("Ljavax/net/ssl/SSLKeyException;"));
+ types.add(factory.createType("Ljavax/net/ssl/SSLPeerUnverifiedException;"));
+ types.add(factory.createType("Ljavax/net/ssl/SSLProtocolException;"));
+ types.add(factory.createType("Ljavax/security/auth/DestroyFailedException;"));
+ types.add(factory.createType("Ljavax/security/auth/callback/UnsupportedCallbackException;"));
+ types.add(factory.createType("Ljavax/security/auth/login/LoginException;"));
+ types.add(factory.createType("Ljavax/security/cert/CertificateEncodingException;"));
+ types.add(factory.createType("Ljavax/security/cert/CertificateException;"));
+ types.add(factory.createType("Ljavax/security/cert/CertificateExpiredException;"));
+ types.add(factory.createType("Ljavax/security/cert/CertificateNotYetValidException;"));
+ types.add(factory.createType("Ljavax/security/cert/CertificateParsingException;"));
+ types.add(factory.createType("Ljavax/xml/parsers/FactoryConfigurationError;"));
+ types.add(factory.createType("Ljavax/xml/parsers/ParserConfigurationException;"));
+ types.add(factory.createType("Ljunit/framework/AssertionFailedError;"));
+ types.add(factory.createType("Ljunit/framework/ComparisonFailure;"));
+ types.add(factory.createType("Lorg/apache/http/ConnectionClosedException;"));
+ types.add(factory.createType("Lorg/apache/http/HttpException;"));
+ types.add(factory.createType("Lorg/apache/http/MalformedChunkCodingException;"));
+ types.add(factory.createType("Lorg/apache/http/MethodNotSupportedException;"));
+ types.add(factory.createType("Lorg/apache/http/NoHttpResponseException;"));
+ types.add(factory.createType("Lorg/apache/http/ParseException;"));
+ types.add(factory.createType("Lorg/apache/http/ProtocolException;"));
+ types.add(factory.createType("Lorg/apache/http/UnsupportedHttpVersionException;"));
+ types.add(factory.createType("Lorg/apache/http/auth/AuthenticationException;"));
+ types.add(factory.createType("Lorg/apache/http/auth/InvalidCredentialsException;"));
+ types.add(factory.createType("Lorg/apache/http/auth/MalformedChallengeException;"));
+ types.add(factory.createType("Lorg/apache/http/client/CircularRedirectException;"));
+ types.add(factory.createType("Lorg/apache/http/client/ClientProtocolException;"));
+ types.add(factory.createType("Lorg/apache/http/client/HttpResponseException;"));
+ types.add(factory.createType("Lorg/apache/http/client/NonRepeatableRequestException;"));
+ types.add(factory.createType("Lorg/apache/http/client/RedirectException;"));
+ types.add(factory.createType("Lorg/apache/http/conn/ConnectTimeoutException;"));
+ types.add(factory.createType("Lorg/apache/http/conn/ConnectionPoolTimeoutException;"));
+ types.add(factory.createType("Lorg/apache/http/conn/HttpHostConnectException;"));
+ types.add(factory.createType("Lorg/apache/http/cookie/MalformedCookieException;"));
+ types.add(factory.createType("Lorg/apache/http/impl/auth/NTLMEngineException;"));
+ types.add(
+ factory.createType("Lorg/apache/http/impl/auth/UnsupportedDigestAlgorithmException;"));
+ types.add(factory.createType("Lorg/apache/http/impl/client/TunnelRefusedException;"));
+ types.add(factory.createType("Lorg/apache/http/impl/cookie/DateParseException;"));
+ types.add(factory.createType("Lorg/json/JSONException;"));
+ types.add(factory.createType("Lorg/w3c/dom/DOMException;"));
+ types.add(factory.createType("Lorg/xml/sax/SAXException;"));
+ types.add(factory.createType("Lorg/xml/sax/SAXNotRecognizedException;"));
+ types.add(factory.createType("Lorg/xml/sax/SAXNotSupportedException;"));
+ types.add(factory.createType("Lorg/xml/sax/SAXParseException;"));
+ types.add(factory.createType("Lorg/xmlpull/v1/XmlPullParserException;"));
+ }
+ if (minApiLevel >= 4) {
+ types.add(factory.createType("Landroid/content/IntentSender$SendIntentException;"));
+ }
+ if (minApiLevel >= 5) {
+ types.add(factory.createType("Landroid/accounts/AccountsException;"));
+ types.add(factory.createType("Landroid/accounts/AuthenticatorException;"));
+ types.add(factory.createType("Landroid/accounts/NetworkErrorException;"));
+ types.add(factory.createType("Landroid/accounts/OperationCanceledException;"));
+ types.add(factory.createType("Landroid/content/OperationApplicationException;"));
+ }
+ if (minApiLevel >= 8) {
+ types.add(factory.createType("Ljavax/xml/datatype/DatatypeConfigurationException;"));
+ types.add(factory.createType("Ljavax/xml/transform/TransformerConfigurationException;"));
+ types.add(factory.createType("Ljavax/xml/transform/TransformerException;"));
+ types.add(factory.createType("Ljavax/xml/transform/TransformerFactoryConfigurationError;"));
+ types.add(factory.createType("Ljavax/xml/xpath/XPathException;"));
+ types.add(factory.createType("Ljavax/xml/xpath/XPathExpressionException;"));
+ types.add(factory.createType("Ljavax/xml/xpath/XPathFactoryConfigurationException;"));
+ types.add(factory.createType("Ljavax/xml/xpath/XPathFunctionException;"));
+ types.add(factory.createType("Lorg/w3c/dom/ls/LSException;"));
+ }
+ if (minApiLevel >= 9) {
+ types.add(factory.createType("Landroid/net/sip/SipException;"));
+ types.add(factory.createType("Landroid/nfc/FormatException;"));
+ types.add(factory.createType("Ljava/io/IOError;"));
+ types.add(factory.createType("Ljava/sql/SQLClientInfoException;"));
+ types.add(factory.createType("Ljava/sql/SQLDataException;"));
+ types.add(factory.createType("Ljava/sql/SQLFeatureNotSupportedException;"));
+ types.add(factory.createType("Ljava/sql/SQLIntegrityConstraintViolationException;"));
+ types.add(factory.createType("Ljava/sql/SQLInvalidAuthorizationSpecException;"));
+ types.add(factory.createType("Ljava/sql/SQLNonTransientConnectionException;"));
+ types.add(factory.createType("Ljava/sql/SQLNonTransientException;"));
+ types.add(factory.createType("Ljava/sql/SQLRecoverableException;"));
+ types.add(factory.createType("Ljava/sql/SQLSyntaxErrorException;"));
+ types.add(factory.createType("Ljava/sql/SQLTimeoutException;"));
+ types.add(factory.createType("Ljava/sql/SQLTransactionRollbackException;"));
+ types.add(factory.createType("Ljava/sql/SQLTransientConnectionException;"));
+ types.add(factory.createType("Ljava/sql/SQLTransientException;"));
+ types.add(factory.createType("Ljava/util/ServiceConfigurationError;"));
+ types.add(factory.createType("Ljava/util/zip/ZipError;"));
+ }
+ if (minApiLevel >= 10) {
+ types.add(factory.createType("Landroid/nfc/TagLostException;"));
+ }
+ if (minApiLevel >= 11) {
+ types.add(factory.createType("Landroid/app/Fragment$InstantiationException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteAccessPermException;"));
+ types.add(
+ factory.createType(
+ "Landroid/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteBlobTooBigException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteCantOpenDatabaseException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteDatabaseLockedException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteDatatypeMismatchException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteOutOfMemoryException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteReadOnlyDatabaseException;"));
+ types.add(factory.createType("Landroid/database/sqlite/SQLiteTableLockedException;"));
+ types.add(factory.createType("Landroid/graphics/SurfaceTexture$OutOfResourcesException;"));
+ types.add(factory.createType("Landroid/os/NetworkOnMainThreadException;"));
+ types.add(factory.createType("Landroid/renderscript/RSDriverException;"));
+ types.add(factory.createType("Landroid/renderscript/RSIllegalArgumentException;"));
+ types.add(factory.createType("Landroid/renderscript/RSInvalidStateException;"));
+ types.add(factory.createType("Landroid/renderscript/RSRuntimeException;"));
+ types.add(factory.createType("Landroid/util/Base64DataException;"));
+ types.add(factory.createType("Landroid/util/MalformedJsonException;"));
+ types.add(factory.createType("Landroid/view/KeyCharacterMap$UnavailableException;"));
+ }
+ if (minApiLevel >= 14) {
+ types.add(factory.createType("Landroid/security/KeyChainException;"));
+ types.add(factory.createType("Landroid/util/NoSuchPropertyException;"));
+ }
+ if (minApiLevel >= 15) {
+ types.add(factory.createType("Landroid/os/TransactionTooLargeException;"));
+ }
+ if (minApiLevel >= 16) {
+ types.add(factory.createType("Landroid/media/MediaCodec$CryptoException;"));
+ types.add(factory.createType("Landroid/media/MediaCryptoException;"));
+ types.add(factory.createType("Landroid/os/OperationCanceledException;"));
+ }
+ if (minApiLevel >= 17) {
+ types.add(factory.createType("Landroid/view/WindowManager$InvalidDisplayException;"));
+ }
+ if (minApiLevel >= 18) {
+ types.add(factory.createType("Landroid/media/DeniedByServerException;"));
+ types.add(factory.createType("Landroid/media/MediaDrmException;"));
+ types.add(factory.createType("Landroid/media/NotProvisionedException;"));
+ types.add(factory.createType("Landroid/media/UnsupportedSchemeException;"));
+ }
+ if (minApiLevel >= 19) {
+ types.add(factory.createType("Landroid/media/ResourceBusyException;"));
+ types.add(
+ factory.createType("Landroid/os/ParcelFileDescriptor$FileDescriptorDetachedException;"));
+ types.add(factory.createType("Ljava/lang/ReflectiveOperationException;"));
+ types.add(factory.createType("Ljavax/crypto/AEADBadTagException;"));
+ }
+ return types;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 9876ae8..4bec07e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -6,6 +6,7 @@
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.google.common.base.Predicates.not;
+import com.android.tools.r8.androidapi.AvailableApiExceptions;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AccessFlags;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
@@ -80,6 +81,8 @@
private final Set<DexEncodedMethod> doubleInlineSelectedTargets = Sets.newIdentityHashSet();
private final Map<DexEncodedMethod, DexEncodedMethod> doubleInlineeCandidates = new HashMap<>();
+ private final AvailableApiExceptions availableApiExceptions;
+
public Inliner(
AppView<AppInfoWithLiveness> appView,
MainDexClasses mainDexClasses,
@@ -94,6 +97,10 @@
this.lambdaMerger = lambdaMerger;
this.lensCodeRewriter = lensCodeRewriter;
this.mainDexClasses = mainDexClasses;
+ availableApiExceptions =
+ appView.options().canHaveDalvikCatchHandlerVerificationBug()
+ ? new AvailableApiExceptions(appView.options())
+ : null;
}
boolean isBlacklisted(
@@ -138,8 +145,7 @@
}
public ConstraintWithTarget computeInliningConstraint(IRCode code, DexEncodedMethod method) {
- if (appView.options().canHaveDalvikCatchHandlerVerificationBug()
- && useReflectiveOperationExceptionOrUnknownClassInCatch(code)) {
+ if (containsPotentialCatchHandlerVerificationError(code)) {
return ConstraintWithTarget.NEVER;
}
@@ -1008,13 +1014,16 @@
assert code.isConsistentSSA();
}
- private boolean useReflectiveOperationExceptionOrUnknownClassInCatch(IRCode code) {
+ private boolean containsPotentialCatchHandlerVerificationError(IRCode code) {
+ if (availableApiExceptions == null) {
+ assert !appView.options().canHaveDalvikCatchHandlerVerificationBug();
+ return false;
+ }
for (BasicBlock block : code.blocks) {
for (CatchHandler<BasicBlock> catchHandler : block.getCatchHandlers()) {
- if (catchHandler.guard == appView.dexItemFactory().reflectiveOperationExceptionType) {
- return true;
- }
- if (appView.definitionFor(catchHandler.guard) == null) {
+ DexClass clazz = appView.definitionFor(catchHandler.guard);
+ if ((clazz == null || clazz.isLibraryClass())
+ && availableApiExceptions.canCauseVerificationError(catchHandler.guard)) {
return true;
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java
new file mode 100644
index 0000000..15e37c1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java
@@ -0,0 +1,171 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.inliner;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Streams;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/** This test extends that of Regress131349148 for other API-introduced exceptions. */
+@RunWith(Parameterized.class)
+public class InlineCatchHandlerWithLibraryTypeTest extends TestBase {
+
+ private static final String TEMPLATE_CODE_EXCEPTION_BINARY_NAME = "java/lang/RuntimeException";
+
+ // A subset of exception types introduced in API levels between 16 to 24.
+ private static final Map<String, Integer> EXCEPTIONS =
+ ImmutableMap.<String, Integer>builder()
+ // VM 4.0.4 (api 15) is the first VM we have so no need to go prior to that.
+ .put("android.media.MediaCryptoException", 16)
+ .put("android.view.WindowManager$InvalidDisplayException", 17)
+ .put("android.media.DeniedByServerException", 18)
+ .put("android.media.ResourceBusyException", 19)
+ .put("java.lang.ReflectiveOperationException", 19)
+ .put("javax.crypto.AEADBadTagException", 19)
+ .put("android.system.ErrnoException", 21)
+ .put("android.media.MediaDrmResetException", 23)
+ .put("java.io.UncheckedIOException", 24)
+ .put("java.util.concurrent.CompletionException", 24)
+ // Verify error was fixed in 21 so up to 24 should catch post-fix issues.
+ .build();
+
+ private static final String EXPECTED = StringUtils.lines("Done...");
+
+ private final TestParameters parameters;
+ private final String exception;
+
+ @Parameters(name = "{0}, {1}")
+ public static List<Object[]> params() {
+ return buildParameters(
+ getTestParameters().withAllRuntimesAndApiLevels().build(),
+ new TreeSet<>(EXCEPTIONS.keySet()));
+ }
+
+ public InlineCatchHandlerWithLibraryTypeTest(TestParameters parameters, String exception) {
+ this.parameters = parameters;
+ this.exception = exception;
+ }
+
+ private String getExceptionBinaryName() {
+ return DescriptorUtils.getBinaryNameFromJavaType(exception);
+ }
+
+ private byte[] getClassWithCatchHandler() throws IOException {
+ return transformer(ClassWithCatchHandler.class)
+ .transformTryCatchBlock(
+ "methodWithCatch",
+ (start, end, handler, type, continuation) -> {
+ String newType =
+ type.equals(TEMPLATE_CODE_EXCEPTION_BINARY_NAME)
+ ? getExceptionBinaryName()
+ : type;
+ continuation.apply(start, end, handler, newType);
+ })
+ .transform();
+ }
+
+ private boolean compilationTargetIsMissingExceptionType() {
+ // A CF target could target any API in the end.
+ return parameters.isCfRuntime()
+ || parameters.getApiLevel().getLevel() < EXCEPTIONS.get(exception);
+ }
+
+ private boolean compileTargetHasVerificationBug() {
+ // A CF target could target any API in the end.
+ return parameters.isCfRuntime() || parameters.getApiLevel().isLessThan(AndroidApiLevel.L);
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .enableInliningAnnotations()
+ .addProgramClasses(TestClass.class)
+ .addProgramClassFileData(getClassWithCatchHandler())
+ .addKeepMainRule(TestClass.class)
+ .setMinApi(parameters.getApiLevel())
+ // Use the latest library so that all of the exceptions are defined.
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.LATEST))
+ .compile()
+ .inspect(this::checkInlined)
+ .run(parameters.getRuntime(), TestClass.class)
+ .apply(this::checkResult);
+ }
+
+ private void checkResult(R8TestRunResult runResult) {
+ // The bootclasspath for our build of 4.4.4 does not contain various bits. Allow verify error.
+ if (!compilationTargetIsMissingExceptionType()
+ && parameters.getRuntime().asDex().getVm().getVersion().equals(Version.V4_4_4)
+ && (exception.startsWith("android.media") || exception.startsWith("android.view"))) {
+ runResult.assertFailureWithErrorThatThrows(VerifyError.class);
+ return;
+ }
+ // Correct compilation should ensure that all programs run without error.
+ runResult.assertSuccessWithOutput(EXPECTED);
+ }
+
+ private void checkInlined(CodeInspector inspector) {
+ ClassSubject classSubject = inspector.clazz(TestClass.class);
+ boolean mainHasInlinedCatchHandler =
+ Streams.stream(classSubject.mainMethod().iterateTryCatches())
+ .anyMatch(tryCatch -> tryCatch.isCatching(exception));
+ if (compileTargetHasVerificationBug() && compilationTargetIsMissingExceptionType()) {
+ assertFalse(mainHasInlinedCatchHandler);
+ } else {
+ assertTrue(mainHasInlinedCatchHandler);
+ }
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ if (args.length == 200) {
+ // Never called
+ ClassWithCatchHandler.methodWithCatch();
+ }
+ System.out.println("Done...");
+ }
+ }
+
+ static class ClassWithCatchHandler {
+
+ @NeverInline
+ public static void maybeThrow() {
+ if (System.nanoTime() > 0) {
+ throw new RuntimeException();
+ }
+ }
+
+ public static void methodWithCatch() {
+ try {
+ maybeThrow();
+ } catch (RuntimeException e) {
+ // We must use the exception, otherwise there is no move-exception that triggers the
+ // verification error.
+ System.out.println(e.getClass().getName());
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithProgramTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithProgramTypeTest.java
new file mode 100644
index 0000000..bcb4b9b
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithProgramTypeTest.java
@@ -0,0 +1,85 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.ir.optimize.inliner;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.google.common.collect.Streams;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/** Simple test to ensure that we do inline program defined types used in catch handler guards. */
+@RunWith(Parameterized.class)
+public class InlineCatchHandlerWithProgramTypeTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public InlineCatchHandlerWithProgramTypeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(InlineCatchHandlerWithProgramTypeTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Done...")
+ .inspect(this::checkInlined);
+ }
+
+ private void checkInlined(CodeInspector inspector) {
+ ClassSubject classSubject = inspector.clazz(TestClass.class);
+ ClassSubject exceptionSubject = inspector.clazz(MyException.class);
+ boolean mainHasInlinedCatchHandler =
+ Streams.stream(classSubject.mainMethod().iterateTryCatches())
+ .anyMatch(tryCatch -> tryCatch.isCatching(exceptionSubject.getFinalName()));
+ assertTrue(mainHasInlinedCatchHandler);
+ }
+
+ static class MyException extends RuntimeException {}
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ if (args.length == 200) {
+ // Never called
+ ClassWithCatchHandler.methodWithCatch();
+ }
+ System.out.println("Done...");
+ }
+ }
+
+ static class ClassWithCatchHandler {
+
+ @NeverInline
+ public static void maybeThrow() {
+ if (System.nanoTime() > 0) {
+ throw new MyException();
+ }
+ }
+
+ public static void methodWithCatch() {
+ try {
+ maybeThrow();
+ } catch (MyException e) {
+ System.out.println(e.getClass().getName());
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/Regress131349148.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/Regress131349148.java
index 08d4f85..28e40ac 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/Regress131349148.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/Regress131349148.java
@@ -53,7 +53,7 @@
.anyMatch(
tryCatch -> tryCatch.isCatching("java.lang.ReflectiveOperationException"));
int runtimeLevel = parameters.getApiLevel().getLevel();
- assertEquals(runtimeLevel >= AndroidApiLevel.L.getLevel(), mainHasReflectiveOperationException);
+ assertEquals(runtimeLevel >= AndroidApiLevel.K.getLevel(), mainHasReflectiveOperationException);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index 8486892..ebe9ab2 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -27,6 +27,7 @@
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
public class ClassFileTransformer {
@@ -385,6 +386,21 @@
void apply(int opcode, String type);
}
+ @FunctionalInterface
+ public interface TryCatchBlockTransform {
+ void visitTryCatchBlock(
+ Label start,
+ Label end,
+ Label handler,
+ String type,
+ TryCatchBlockTransformContinuation continuation);
+ }
+
+ @FunctionalInterface
+ public interface TryCatchBlockTransformContinuation {
+ void apply(Label start, Label end, Label handler, String type);
+ }
+
public ClassFileTransformer transformMethodInsnInMethod(
String methodName, MethodInsnTransform transform) {
return addMethodTransformer(
@@ -417,6 +433,21 @@
});
}
+ public ClassFileTransformer transformTryCatchBlock(
+ String methodName, TryCatchBlockTransform transform) {
+ return addMethodTransformer(
+ new MethodTransformer() {
+ @Override
+ public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ if (getContext().method.getMethodName().equals(methodName)) {
+ transform.visitTryCatchBlock(start, end, handler, type, super::visitTryCatchBlock);
+ } else {
+ super.visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+ });
+ }
+
/** Abstraction of the MethodVisitor.visitLdcInsn method with its continuation. */
@FunctionalInterface
public interface LdcInsnTransform {