Bug 1382335 - 1. Record the type of null native pointers; r=esawin
authorJim Chen <nchen@mozilla.com>
Mon, 31 Jul 2017 12:30:13 -0400
changeset 420791 3a434c64cc3b9548ae5a4ba8a526c16594061940
parent 420790 1221530577aa51b65999ea225fdd1cab8f70567c
child 420792 81735bcac861e602c6b335060bdb33d1255afdb0
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersesawin
bugs1382335
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1382335 - 1. Record the type of null native pointers; r=esawin Right now we throw NullPointerException with the message "Null native pointer", but we can save the type of the native pointer in the message to make it easier to categorize and analyze crashes. This patch uses the __func__ feature to get the name of a particular template parameter type. MozReview-Commit-ID: GNWzIy91OD6
widget/android/jni/Natives.h
--- a/widget/android/jni/Natives.h
+++ b/widget/android/jni/Natives.h
@@ -13,16 +13,32 @@
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WeakPtr.h"
 #include "mozilla/Unused.h"
 #include "mozilla/jni/Accessors.h"
 #include "mozilla/jni/Refs.h"
 #include "mozilla/jni/Types.h"
 #include "mozilla/jni/Utils.h"
 
+struct NativeException {
+    const char* str;
+};
+
+template<class T> static
+NativeException NullHandle()
+{
+    return { __func__ };
+}
+
+template<class T> static
+NativeException NullWeakPtr()
+{
+    return { __func__ };
+}
+
 namespace mozilla {
 namespace jni {
 
 /**
  * C++ classes implementing instance (non-static) native methods can choose
  * from one of two ownership models, when associating a C++ object with a Java
  * instance.
  *
@@ -121,36 +137,38 @@ class NativePtrPicker
             static char (&Test(int))[NativePtrType::REFPTR];
 
     template<class> static char (&Test(...))[NativePtrType::OWNING];
 
 public:
     static const int value = sizeof(Test<Impl>('\0')) / sizeof(char);
 };
 
+template<class Impl>
 inline uintptr_t CheckNativeHandle(JNIEnv* env, uintptr_t handle)
 {
     if (!handle) {
         if (!env->ExceptionCheck()) {
-            ThrowException(env, "java/lang/NullPointerException",
-                           "Null native pointer");
+            ThrowException(env,
+                           "java/lang/NullPointerException",
+                           NullHandle<Impl>().str);
         }
         return 0;
     }
     return handle;
 }
 
 template<class Impl, int Type = NativePtrPicker<Impl>::value> struct NativePtr;
 
 template<class Impl>
 struct NativePtr<Impl, /* Type = */ NativePtrType::OWNING>
 {
     static Impl* Get(JNIEnv* env, jobject instance)
     {
-        return reinterpret_cast<Impl*>(CheckNativeHandle(
+        return reinterpret_cast<Impl*>(CheckNativeHandle<Impl>(
                 env, GetNativeHandle(env, instance)));
     }
 
     template<class LocalRef>
     static Impl* Get(const LocalRef& instance)
     {
         return Get(instance.Env(), instance.Get());
     }
@@ -179,25 +197,26 @@ struct NativePtr<Impl, /* Type = */ Nati
 };
 
 template<class Impl>
 struct NativePtr<Impl, /* Type = */ NativePtrType::WEAK>
 {
     static Impl* Get(JNIEnv* env, jobject instance)
     {
         const auto ptr = reinterpret_cast<WeakPtr<Impl>*>(
-                CheckNativeHandle(env, GetNativeHandle(env, instance)));
+                CheckNativeHandle<Impl>(env, GetNativeHandle(env, instance)));
         if (!ptr) {
             return nullptr;
         }
 
         Impl* const impl = *ptr;
         if (!impl) {
-            ThrowException(env, "java/lang/NullPointerException",
-                           "Native weak object already released");
+            ThrowException(env,
+                           "java/lang/NullPointerException",
+                           NullWeakPtr<Impl>().str);
         }
         return impl;
     }
 
     template<class LocalRef>
     static Impl* Get(const LocalRef& instance)
     {
         return Get(instance.Env(), instance.Get());
@@ -228,17 +247,17 @@ struct NativePtr<Impl, /* Type = */ Nati
 };
 
 template<class Impl>
 struct NativePtr<Impl, /* Type = */ NativePtrType::REFPTR>
 {
     static Impl* Get(JNIEnv* env, jobject instance)
     {
         const auto ptr = reinterpret_cast<RefPtr<Impl>*>(
-                CheckNativeHandle(env, GetNativeHandle(env, instance)));
+                CheckNativeHandle<Impl>(env, GetNativeHandle(env, instance)));
         if (!ptr) {
             return nullptr;
         }
 
         MOZ_ASSERT(*ptr);
         return *ptr;
     }