From 4c0df5c72751044137f093e63c10c2da4a175368 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Thu, 30 May 2019 14:38:43 -0700 Subject: [PATCH] Frameworks: Slightly refactor Parcel code Decrease the amount of code covered by a lock in Parcel. This allows fetching multiple classes in parallel, with the slight downside that these classes might be the same. Reduces contention samples for this method in profiling by two thirds. Test: m Test: manual profiling Change-Id: I96415659f6625df25800c60dd3bee1094255fcc3 --- core/java/android/os/Parcel.java | 104 ++++++++++++++++--------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index ae743fbda482d..fe2fbb1f4d471 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -2797,65 +2797,67 @@ public final class Parcel { return null; } Parcelable.Creator creator; + HashMap> map; synchronized (mCreators) { - HashMap> map = mCreators.get(loader); + map = mCreators.get(loader); if (map == null) { map = new HashMap<>(); mCreators.put(loader, map); } creator = map.get(name); - if (creator == null) { - try { - // If loader == null, explicitly emulate Class.forName(String) "caller - // classloader" behavior. - ClassLoader parcelableClassLoader = - (loader == null ? getClass().getClassLoader() : loader); - // Avoid initializing the Parcelable class until we know it implements - // Parcelable and has the necessary CREATOR field. http://b/1171613. - Class parcelableClass = Class.forName(name, false /* initialize */, - parcelableClassLoader); - if (!Parcelable.class.isAssignableFrom(parcelableClass)) { - throw new BadParcelableException("Parcelable protocol requires subclassing " - + "from Parcelable on class " + name); - } - Field f = parcelableClass.getField("CREATOR"); - if ((f.getModifiers() & Modifier.STATIC) == 0) { - throw new BadParcelableException("Parcelable protocol requires " - + "the CREATOR object to be static on class " + name); - } - Class creatorType = f.getType(); - if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) { - // Fail before calling Field.get(), not after, to avoid initializing - // parcelableClass unnecessarily. - throw new BadParcelableException("Parcelable protocol requires a " - + "Parcelable.Creator object called " - + "CREATOR on class " + name); - } - creator = (Parcelable.Creator) f.get(null); - } - catch (IllegalAccessException e) { - Log.e(TAG, "Illegal access when unmarshalling: " + name, e); - throw new BadParcelableException( - "IllegalAccessException when unmarshalling: " + name); - } - catch (ClassNotFoundException e) { - Log.e(TAG, "Class not found when unmarshalling: " + name, e); - throw new BadParcelableException( - "ClassNotFoundException when unmarshalling: " + name); - } - catch (NoSuchFieldException e) { - throw new BadParcelableException("Parcelable protocol requires a " - + "Parcelable.Creator object called " - + "CREATOR on class " + name); - } - if (creator == null) { - throw new BadParcelableException("Parcelable protocol requires a " - + "non-null Parcelable.Creator object called " - + "CREATOR on class " + name); - } + } + if (creator != null) { + return creator; + } - map.put(name, creator); + try { + // If loader == null, explicitly emulate Class.forName(String) "caller + // classloader" behavior. + ClassLoader parcelableClassLoader = + (loader == null ? getClass().getClassLoader() : loader); + // Avoid initializing the Parcelable class until we know it implements + // Parcelable and has the necessary CREATOR field. http://b/1171613. + Class parcelableClass = Class.forName(name, false /* initialize */, + parcelableClassLoader); + if (!Parcelable.class.isAssignableFrom(parcelableClass)) { + throw new BadParcelableException("Parcelable protocol requires subclassing " + + "from Parcelable on class " + name); } + Field f = parcelableClass.getField("CREATOR"); + if ((f.getModifiers() & Modifier.STATIC) == 0) { + throw new BadParcelableException("Parcelable protocol requires " + + "the CREATOR object to be static on class " + name); + } + Class creatorType = f.getType(); + if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) { + // Fail before calling Field.get(), not after, to avoid initializing + // parcelableClass unnecessarily. + throw new BadParcelableException("Parcelable protocol requires a " + + "Parcelable.Creator object called " + + "CREATOR on class " + name); + } + creator = (Parcelable.Creator) f.get(null); + } catch (IllegalAccessException e) { + Log.e(TAG, "Illegal access when unmarshalling: " + name, e); + throw new BadParcelableException( + "IllegalAccessException when unmarshalling: " + name); + } catch (ClassNotFoundException e) { + Log.e(TAG, "Class not found when unmarshalling: " + name, e); + throw new BadParcelableException( + "ClassNotFoundException when unmarshalling: " + name); + } catch (NoSuchFieldException e) { + throw new BadParcelableException("Parcelable protocol requires a " + + "Parcelable.Creator object called " + + "CREATOR on class " + name); + } + if (creator == null) { + throw new BadParcelableException("Parcelable protocol requires a " + + "non-null Parcelable.Creator object called " + + "CREATOR on class " + name); + } + + synchronized (mCreators) { + map.put(name, creator); } return creator;