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 {