StrictMode: avoid an allocation in common case

Make the initialValue() of the ThreadLocal be null, so checking it doesn't
cause one to be created in the case of an RPC call not using StrictMode.

Change-Id: I3ea19ce444a1b3c39a6e53c5cb5d4faf4b07a6c8
This commit is contained in:
Brad Fitzpatrick
2010-07-15 13:16:41 -07:00
parent 0c36c96f2a
commit 703e5d3c7f
2 changed files with 31 additions and 9 deletions

View File

@@ -1202,6 +1202,7 @@ public final class Parcel {
code = EX_ILLEGAL_STATE;
}
writeInt(code);
StrictMode.clearGatheredViolations();
if (code == 0) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;

View File

@@ -80,6 +80,8 @@ public final class StrictMode {
* our offending stack traces to the caller to ultimately handle
* in the originating process.
*
* This must be kept in sync with the constant in libs/binder/Parcel.cpp
*
* @hide
*/
public static final int PENALTY_GATHER = 0x100;
@@ -98,7 +100,10 @@ public final class StrictMode {
private static ThreadLocal<ArrayList<ApplicationErrorReport.CrashInfo>> gatheredViolations =
new ThreadLocal<ArrayList<ApplicationErrorReport.CrashInfo>>() {
@Override protected ArrayList<ApplicationErrorReport.CrashInfo> initialValue() {
return new ArrayList<ApplicationErrorReport.CrashInfo>(1);
// Starts null to avoid unnecessary allocations when
// checking whether there are any violations or not in
// hasGatheredViolations() below.
return null;
}
};
@@ -308,7 +313,10 @@ public final class StrictMode {
if ((policy & PENALTY_GATHER) != 0) {
ArrayList<ApplicationErrorReport.CrashInfo> violations = gatheredViolations.get();
if (violations.size() >= 5) {
if (violations == null) {
violations = new ArrayList<ApplicationErrorReport.CrashInfo>(1);
gatheredViolations.set(violations);
} else if (violations.size() >= 5) {
// Too many. In a loop or something? Don't gather them all.
return;
}
@@ -393,7 +401,16 @@ public final class StrictMode {
* Called from Parcel.writeNoException()
*/
/* package */ static boolean hasGatheredViolations() {
return !gatheredViolations.get().isEmpty();
return gatheredViolations.get() != null;
}
/**
* Called from Parcel.writeException(), so we drop this memory and
* don't incorrectly attribute it to the wrong caller on the next
* Binder call on this thread.
*/
/* package */ static void clearGatheredViolations() {
gatheredViolations.set(null);
}
/**
@@ -401,13 +418,17 @@ public final class StrictMode {
*/
/* package */ static void writeGatheredViolationsToParcel(Parcel p) {
ArrayList<ApplicationErrorReport.CrashInfo> violations = gatheredViolations.get();
p.writeInt(violations.size());
for (int i = 0; i < violations.size(); ++i) {
violations.get(i).writeToParcel(p, 0 /* unused flags? */);
if (violations == null) {
p.writeInt(0);
} else {
p.writeInt(violations.size());
for (int i = 0; i < violations.size(); ++i) {
violations.get(i).writeToParcel(p, 0 /* unused flags? */);
}
if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
violations.clear(); // somewhat redundant, as we're about to null the threadlocal
}
if (LOG_V) Log.d(TAG, "wrote violations to response parcel; num=" + violations.size());
violations.clear();
gatheredViolations.set(null);
}
private static class LogStackTrace extends Exception {}