зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1459297 - Use SDK JNI calls for boxing/unboxing GeckoBundle values; r=snorp
Instead of the helper methods in GeckoBundle, add SDK JNI calls for the boxing/unboxing operations, and use those calls directly. Moreover, for unboxing Boolean/Double/Integer, use their internal "value" field value directly if possible, to avoid making a JNI method call. MozReview-Commit-ID: Azvov1gCeje --HG-- extra : rebase_source : 34cd4a821d2b47e48957f241bbf165439635be59
This commit is contained in:
Родитель
a2a7ef293f
Коммит
8f6ba7ef0c
|
@ -40,21 +40,6 @@ public final class GeckoBundle implements Parcelable {
|
|||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
private static final GeckoBundle[] EMPTY_BUNDLE_ARRAY = new GeckoBundle[0];
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static Object box(boolean b) { return b; }
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static Object box(int i) { return i; }
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static Object box(double d) { return d; }
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static boolean unboxBoolean(Boolean b) { return b; }
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static int unboxInteger(Number i) { return i.intValue(); }
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static double unboxDouble(Number d) { return d.doubleValue(); }
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static String unboxString(Object s) { return s.toString(); }
|
||||
|
||||
private SimpleArrayMap<String, Object> mMap;
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "EventDispatcher.h"
|
||||
|
||||
#include "JavaBuiltins.h"
|
||||
#include "nsAppShell.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
@ -272,11 +273,12 @@ BoxValue(JSContext* aCx, JS::HandleValue aData, jni::Object::LocalRef& aOut)
|
|||
if (aData.isNullOrUndefined()) {
|
||||
aOut = nullptr;
|
||||
} else if (aData.isBoolean()) {
|
||||
aOut = java::GeckoBundle::Box(aData.toBoolean());
|
||||
aOut = aData.toBoolean() ? java::sdk::Boolean::TRUE()
|
||||
: java::sdk::Boolean::FALSE();
|
||||
} else if (aData.isInt32()) {
|
||||
aOut = java::GeckoBundle::Box(aData.toInt32());
|
||||
aOut = java::sdk::Integer::ValueOf(aData.toInt32());
|
||||
} else if (aData.isNumber()) {
|
||||
aOut = java::GeckoBundle::Box(aData.toNumber());
|
||||
aOut = java::sdk::Double::New(aData.toNumber());
|
||||
} else if (aData.isString()) {
|
||||
return BoxString(aCx, aData, aOut);
|
||||
} else if (aData.isObject()) {
|
||||
|
@ -480,26 +482,61 @@ UnboxArrayObject(JSContext* aCx, const jni::Object::LocalRef& aData,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
template<class T> jfieldID
|
||||
GetValueFieldID(const char* aType)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
JNIEnv* const env = jni::GetGeckoThreadEnv();
|
||||
const jfieldID id = env->GetFieldID(
|
||||
typename T::Context(env, nullptr).ClassRef(), "value", aType);
|
||||
env->ExceptionClear();
|
||||
return id;
|
||||
}
|
||||
|
||||
nsresult
|
||||
UnboxValue(JSContext* aCx, const jni::Object::LocalRef& aData,
|
||||
JS::MutableHandleValue aOut)
|
||||
{
|
||||
static jfieldID booleanValueField =
|
||||
GetValueFieldID<java::sdk::Boolean>("Z");
|
||||
static jfieldID intValueField = GetValueFieldID<java::sdk::Integer>("I");
|
||||
static jfieldID doubleValueField = GetValueFieldID<java::sdk::Double>("D");
|
||||
|
||||
if (!aData) {
|
||||
aOut.setNull();
|
||||
} else if (aData.IsInstanceOf<jni::Boolean>()) {
|
||||
aOut.setBoolean(java::GeckoBundle::UnboxBoolean(aData));
|
||||
} else if (aData.IsInstanceOf<jni::Integer>() ||
|
||||
aData.IsInstanceOf<jni::Byte>() ||
|
||||
if (booleanValueField) {
|
||||
aOut.setBoolean(aData.Env()->GetBooleanField(
|
||||
aData.Get(), booleanValueField) != JNI_FALSE);
|
||||
MOZ_CATCH_JNI_EXCEPTION(aData.Env());
|
||||
} else {
|
||||
aOut.setBoolean(
|
||||
java::sdk::Boolean::Ref::From(aData)->BooleanValue());
|
||||
}
|
||||
} else if (aData.IsInstanceOf<jni::Integer>()) {
|
||||
if (intValueField) {
|
||||
aOut.setInt32(aData.Env()->GetIntField(aData.Get(), intValueField));
|
||||
MOZ_CATCH_JNI_EXCEPTION(aData.Env());
|
||||
} else {
|
||||
aOut.setInt32(java::sdk::Number::Ref::From(aData)->IntValue());
|
||||
}
|
||||
} else if (aData.IsInstanceOf<jni::Byte>() ||
|
||||
aData.IsInstanceOf<jni::Short>()) {
|
||||
aOut.setInt32(java::GeckoBundle::UnboxInteger(aData));
|
||||
} else if (aData.IsInstanceOf<jni::Double>() ||
|
||||
aData.IsInstanceOf<jni::Float>() ||
|
||||
aOut.setInt32(java::sdk::Number::Ref::From(aData)->IntValue());
|
||||
} else if (aData.IsInstanceOf<jni::Double>()) {
|
||||
if (doubleValueField) {
|
||||
aOut.setNumber(aData.Env()->GetDoubleField(
|
||||
aData.Get(), doubleValueField));
|
||||
} else {
|
||||
aOut.setNumber(java::sdk::Number::Ref::From(aData)->DoubleValue());
|
||||
}
|
||||
} else if (aData.IsInstanceOf<jni::Float>() ||
|
||||
aData.IsInstanceOf<jni::Long>()) {
|
||||
aOut.setNumber(java::GeckoBundle::UnboxDouble(aData));
|
||||
aOut.setNumber(java::sdk::Number::Ref::From(aData)->DoubleValue());
|
||||
} else if (aData.IsInstanceOf<jni::String>()) {
|
||||
return UnboxString(aCx, aData, aOut);
|
||||
} else if (aData.IsInstanceOf<jni::Character>()) {
|
||||
return UnboxString(aCx, java::GeckoBundle::UnboxString(aData), aOut);
|
||||
return UnboxString(aCx, java::sdk::String::ValueOf(aData), aOut);
|
||||
} else if (aData.IsInstanceOf<java::GeckoBundle>()) {
|
||||
return UnboxBundle(aCx, aData, aOut);
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
[java.lang.Boolean = skip:true]
|
||||
# Use static fields for boxing boolean.
|
||||
TRUE =
|
||||
FALSE =
|
||||
booleanValue =
|
||||
|
||||
[java.lang.Double = skip:true]
|
||||
<init>(D)V =
|
||||
|
||||
[java.lang.Integer = skip:true]
|
||||
# Use valueOf() for boxing int; don't use constructor
|
||||
# because some Integer values are cached.
|
||||
valueOf(I)Ljava/lang/Integer; =
|
||||
|
||||
[java.lang.Number = skip:true]
|
||||
# Use doubleValue() for unboxing Double/Float/Long.
|
||||
doubleValue =
|
||||
# Use intValue() for unboxing Byte/Int/Short.
|
||||
intValue =
|
||||
|
||||
[java.lang.String = skip:true]
|
||||
valueOf(Ljava/lang/Object;)Ljava/lang/String; =
|
|
@ -12,6 +12,7 @@ with Files("**"):
|
|||
generated = [
|
||||
'AndroidBuild',
|
||||
'AndroidRect',
|
||||
'JavaBuiltins',
|
||||
'KeyEvent',
|
||||
'MediaCodec',
|
||||
'MotionEvent',
|
||||
|
|
Загрузка…
Ссылка в новой задаче