Bug 1192043 - Add more JNIEnv support and null-check refs in JNI ref classs; r=snorp

Add more constructors in LocalRef and GlobalRef to accommodate use cases
where a JNIEnv is already available for performance reasons. Also add
more null-checks when creating references for performance reasons.
This commit is contained in:
Jim Chen 2015-08-25 14:52:16 -04:00
Родитель 4149622c41
Коммит 4403af4250
1 изменённых файлов: 33 добавлений и 20 удалений

Просмотреть файл

@ -214,8 +214,6 @@ template<class Cls>
class Ref : public RefBase<Cls, jobject> class Ref : public RefBase<Cls, jobject>
{ {
template<class C, typename T> friend class RefBase; template<class C, typename T> friend class RefBase;
friend class jni::LocalRef<Cls>;
friend class jni::GlobalRef<Cls>;
friend struct detail::TypeAdapter<Ref<Cls>>; friend struct detail::TypeAdapter<Ref<Cls>>;
typedef RefBase<Cls, jobject> Base; typedef RefBase<Cls, jobject> Base;
@ -248,8 +246,6 @@ class Ref<TypedObject<T>>
: public RefBase<TypedObject<T>, T> : public RefBase<TypedObject<T>, T>
{ {
friend class RefBase<TypedObject<T>, T>; friend class RefBase<TypedObject<T>, T>;
friend class jni::LocalRef<TypedObject<T>>;
friend class jni::GlobalRef<TypedObject<T>>;
friend struct detail::TypeAdapter<Ref<TypedObject<T>>>; friend struct detail::TypeAdapter<Ref<TypedObject<T>>>;
typedef RefBase<TypedObject<T>, T> Base; typedef RefBase<TypedObject<T>, T> Base;
@ -300,6 +296,14 @@ private:
template<class C> using GenericLocalRef template<class C> using GenericLocalRef
= typename GenericLocalRef<Cls>::template Type<C>; = typename GenericLocalRef<Cls>::template Type<C>;
static jobject NewLocalRef(JNIEnv* env, jobject obj)
{
if (!obj) {
return nullptr;
}
return env->NewLocalRef(obj);
}
JNIEnv* const mEnv; JNIEnv* const mEnv;
LocalRef(JNIEnv* env, jobject instance) LocalRef(JNIEnv* env, jobject instance)
@ -331,7 +335,7 @@ public:
// Copy constructor. // Copy constructor.
LocalRef(const LocalRef<Cls>& ref) LocalRef(const LocalRef<Cls>& ref)
: Ref<Cls>(ref.mEnv->NewLocalRef(ref.mInstance)) : Ref<Cls>(NewLocalRef(ref.mEnv, ref.mInstance))
, mEnv(ref.mEnv) , mEnv(ref.mEnv)
{} {}
@ -354,9 +358,14 @@ public:
: Ref<Cls>(nullptr) : Ref<Cls>(nullptr)
, mEnv(GetEnvForThread()) , mEnv(GetEnvForThread())
{ {
Ref<Cls>::mInstance = mEnv->NewLocalRef(ref.mInstance); Ref<Cls>::mInstance = NewLocalRef(mEnv, ref.Get());
} }
LocalRef(JNIEnv* env, const Ref<Cls>& ref)
: Ref<Cls>(NewLocalRef(env, ref.Get()))
, mEnv(env)
{}
// Move a LocalRef<Object> into a LocalRef<Cls> without // Move a LocalRef<Object> into a LocalRef<Cls> without
// creating/deleting local references. // creating/deleting local references.
MOZ_IMPLICIT LocalRef(LocalRef<GenericObject>&& ref) MOZ_IMPLICIT LocalRef(LocalRef<GenericObject>&& ref)
@ -410,7 +419,7 @@ public:
LocalRef<Cls>& operator=(const Ref<Cls>& ref) LocalRef<Cls>& operator=(const Ref<Cls>& ref)
{ {
LocalRef<Cls> newRef(mEnv, mEnv->NewLocalRef(ref.mInstance)); LocalRef<Cls> newRef(mEnv, ref);
return swap(newRef); return swap(newRef);
} }
@ -444,9 +453,6 @@ private:
if (!instance) { if (!instance) {
return nullptr; return nullptr;
} }
if (!env) {
env = GetEnvForThread();
}
return env->NewGlobalRef(instance); return env->NewGlobalRef(instance);
} }
@ -465,7 +471,7 @@ public:
// Copy constructor // Copy constructor
GlobalRef(const GlobalRef& ref) GlobalRef(const GlobalRef& ref)
: Ref<Cls>(NewGlobalRef(nullptr, ref.mInstance)) : Ref<Cls>(NewGlobalRef(GetEnvForThread(), ref.mInstance))
{} {}
// Move constructor // Move constructor
@ -476,11 +482,15 @@ public:
} }
MOZ_IMPLICIT GlobalRef(const Ref<Cls>& ref) MOZ_IMPLICIT GlobalRef(const Ref<Cls>& ref)
: Ref<Cls>(NewGlobalRef(nullptr, ref.mInstance)) : Ref<Cls>(NewGlobalRef(GetEnvForThread(), ref.Get()))
{} {}
GlobalRef(JNIEnv* env, const Ref<Cls>& ref) GlobalRef(JNIEnv* env, const Ref<Cls>& ref)
: Ref<Cls>(NewGlobalRef(env, ref.mInstance)) : Ref<Cls>(NewGlobalRef(env, ref.Get()))
{}
MOZ_IMPLICIT GlobalRef(const LocalRef<Cls>& ref)
: Ref<Cls>(NewGlobalRef(ref.Env(), ref.Get()))
{} {}
// Implicitly converts nullptr to GlobalRef. // Implicitly converts nullptr to GlobalRef.
@ -491,9 +501,7 @@ public:
~GlobalRef() ~GlobalRef()
{ {
if (Ref<Cls>::mInstance) { if (Ref<Cls>::mInstance) {
JNIEnv* const env = GetEnvForThread(); Clear(GetEnvForThread());
env->DeleteGlobalRef(Ref<Cls>::mInstance);
Ref<Cls>::mInstance = nullptr;
} }
} }
@ -506,6 +514,14 @@ public:
return obj; return obj;
} }
void Clear(JNIEnv* env)
{
if (Ref<Cls>::mInstance) {
env->DeleteGlobalRef(Ref<Cls>::mInstance);
Ref<Cls>::mInstance = nullptr;
}
}
GlobalRef<Cls>& operator=(GlobalRef<Cls> ref) GlobalRef<Cls>& operator=(GlobalRef<Cls> ref)
{ {
return swap(ref); return swap(ref);
@ -530,8 +546,6 @@ template<>
class Ref<String> : public RefBase<String, jstring> class Ref<String> : public RefBase<String, jstring>
{ {
friend class RefBase<String, jstring>; friend class RefBase<String, jstring>;
friend class jni::LocalRef<String>;
friend class jni::GlobalRef<String>;
friend struct detail::TypeAdapter<Ref<String>>; friend struct detail::TypeAdapter<Ref<String>>;
typedef RefBase<TypedObject<jstring>, jstring> Base; typedef RefBase<TypedObject<jstring>, jstring> Base;
@ -625,10 +639,9 @@ public:
operator String::LocalRef() const operator String::LocalRef() const
{ {
JNIEnv* const env = mEnv ? mEnv : GetEnvForThread();
// We can't return our existing ref because the returned // We can't return our existing ref because the returned
// LocalRef could be freed first, so we need a new local ref. // LocalRef could be freed first, so we need a new local ref.
return String::LocalRef::Adopt(env, env->NewLocalRef(Get())); return String::LocalRef(mEnv ? mEnv : GetEnvForThread(), *this);
} }
}; };