Move native accesses of array into one access instead of per-element
Differential Revision: D6578349 fbshipit-source-id: 84ebd66ed791a845e9cc0fbc7e12a377534aa903
This commit is contained in:
parent
24e521c063
commit
5649aed6d3
|
@ -13,6 +13,9 @@ import com.facebook.jni.HybridData;
|
||||||
import com.facebook.proguard.annotations.DoNotStrip;
|
import com.facebook.proguard.annotations.DoNotStrip;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import com.facebook.infer.annotation.Assertions;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of a NativeArray that allows read-only access to its members. This will generally
|
* Implementation of a NativeArray that allows read-only access to its members. This will generally
|
||||||
|
@ -28,24 +31,142 @@ public class ReadableNativeArray extends NativeArray implements ReadableArray {
|
||||||
super(hybridData);
|
super(hybridData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//WriteOnce but not in the constructor fields
|
||||||
|
private @Nullable Object[] mLocalArray;
|
||||||
|
private @Nullable ReadableType[] mLocalTypeArray;
|
||||||
|
|
||||||
|
private static int jniPassCounter = 0;
|
||||||
|
private static boolean mUseNativeAccessor = false;
|
||||||
|
public static void setUseNativeAccessor(boolean useNativeAccessor) {
|
||||||
|
mUseNativeAccessor = useNativeAccessor;
|
||||||
|
}
|
||||||
|
public static int getJNIPassCounter() {
|
||||||
|
return jniPassCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object[] getLocalArray() {
|
||||||
|
// Fast, non blocking check for the common case
|
||||||
|
if (mLocalArray != null) {
|
||||||
|
return mLocalArray;
|
||||||
|
}
|
||||||
|
synchronized (this) {
|
||||||
|
// Make sure no concurrent call already updated
|
||||||
|
if (mLocalArray == null) {
|
||||||
|
jniPassCounter++;
|
||||||
|
mLocalArray = Assertions.assertNotNull(importArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mLocalArray;
|
||||||
|
}
|
||||||
|
private native Object[] importArray();
|
||||||
|
|
||||||
|
private ReadableType[] getLocalTypeArray() {
|
||||||
|
// Fast, non-blocking check for the common case
|
||||||
|
if (mLocalTypeArray != null) {
|
||||||
|
return mLocalTypeArray;
|
||||||
|
}
|
||||||
|
synchronized (this) {
|
||||||
|
// Make sure no concurrent call already updated
|
||||||
|
if (mLocalTypeArray == null) {
|
||||||
|
jniPassCounter++;
|
||||||
|
Object[] tempArray = Assertions.assertNotNull(importTypeArray());
|
||||||
|
mLocalTypeArray = Arrays.copyOf(tempArray, tempArray.length, ReadableType[].class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mLocalTypeArray;
|
||||||
|
}
|
||||||
|
private native Object[] importTypeArray();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native int size();
|
public int size() {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return sizeNative();
|
||||||
|
}
|
||||||
|
return getLocalArray().length;
|
||||||
|
}
|
||||||
|
private native int sizeNative();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native boolean isNull(int index);
|
public boolean isNull(int index) {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return isNullNative(index);
|
||||||
|
}
|
||||||
|
return getLocalArray()[index] == null;
|
||||||
|
}
|
||||||
|
private native boolean isNullNative(int index);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native boolean getBoolean(int index);
|
public boolean getBoolean(int index) {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return getBooleanNative(index);
|
||||||
|
}
|
||||||
|
return ((Boolean) getLocalArray()[index]).booleanValue();
|
||||||
|
}
|
||||||
|
private native boolean getBooleanNative(int index);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native double getDouble(int index);
|
public double getDouble(int index) {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return getDoubleNative(index);
|
||||||
|
}
|
||||||
|
return ((Double) getLocalArray()[index]).doubleValue();
|
||||||
|
}
|
||||||
|
private native double getDoubleNative(int index);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native int getInt(int index);
|
public int getInt(int index) {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return getIntNative(index);
|
||||||
|
}
|
||||||
|
return ((Double) getLocalArray()[index]).intValue();
|
||||||
|
}
|
||||||
|
private native int getIntNative(int index);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native String getString(int index);
|
public String getString(int index) {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return getStringNative(index);
|
||||||
|
}
|
||||||
|
return (String) getLocalArray()[index];
|
||||||
|
}
|
||||||
|
private native String getStringNative(int index);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native ReadableNativeArray getArray(int index);
|
public ReadableNativeArray getArray(int index) {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return getArrayNative(index);
|
||||||
|
}
|
||||||
|
return (ReadableNativeArray) getLocalArray()[index];
|
||||||
|
}
|
||||||
|
private native ReadableNativeArray getArrayNative(int index);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native ReadableNativeMap getMap(int index);
|
public ReadableNativeMap getMap(int index) {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return getMapNative(index);
|
||||||
|
}
|
||||||
|
return (ReadableNativeMap) getLocalArray()[index];
|
||||||
|
}
|
||||||
|
private native ReadableNativeMap getMapNative(int index);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public native ReadableType getType(int index);
|
public ReadableType getType(int index) {
|
||||||
|
if (mUseNativeAccessor) {
|
||||||
|
jniPassCounter++;
|
||||||
|
return getTypeNative(index);
|
||||||
|
}
|
||||||
|
return getLocalTypeArray()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
private native ReadableType getTypeNative(int index);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dynamic getDynamic(int index) {
|
public Dynamic getDynamic(int index) {
|
||||||
|
|
|
@ -56,6 +56,48 @@ const char* ReadableNativeArray::getString(jint index) {
|
||||||
return dyn.getString().c_str();
|
return dyn.getString().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_ref<JArrayClass<jobject>> ReadableNativeArray::importArray() {
|
||||||
|
jint size = array_.size();
|
||||||
|
auto jarray = JArrayClass<jobject>::newArray(size);
|
||||||
|
for (jint i = 0; i < size; i++) {
|
||||||
|
switch(array_.at(i).type()) {
|
||||||
|
case folly::dynamic::Type::NULLT: {
|
||||||
|
jarray->setElement(i, nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case folly::dynamic::Type::BOOL: {
|
||||||
|
jarray->
|
||||||
|
setElement(i,
|
||||||
|
JBoolean::valueOf(ReadableNativeArray::getBoolean(i)).release());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case folly::dynamic::Type::INT64:
|
||||||
|
case folly::dynamic::Type::DOUBLE: {
|
||||||
|
jarray->setElement(i,
|
||||||
|
JDouble::valueOf(ReadableNativeArray::getDouble(i)).release());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case folly::dynamic::Type::STRING: {
|
||||||
|
jarray->
|
||||||
|
setElement(i,
|
||||||
|
make_jstring(ReadableNativeArray::getString(i)).release());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case folly::dynamic::Type::OBJECT: {
|
||||||
|
jarray->setElement(i,ReadableNativeArray::getMap(i).release());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case folly::dynamic::Type::ARRAY: {
|
||||||
|
jarray->setElement(i,ReadableNativeArray::getArray(i).release());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return jarray;
|
||||||
|
}
|
||||||
|
|
||||||
local_ref<ReadableNativeArray::jhybridobject> ReadableNativeArray::getArray(jint index) {
|
local_ref<ReadableNativeArray::jhybridobject> ReadableNativeArray::getArray(jint index) {
|
||||||
auto& elem = array_.at(index);
|
auto& elem = array_.at(index);
|
||||||
if (elem.isNull()) {
|
if (elem.isNull()) {
|
||||||
|
@ -69,6 +111,15 @@ local_ref<ReadableType> ReadableNativeArray::getType(jint index) {
|
||||||
return ReadableType::getType(array_.at(index).type());
|
return ReadableType::getType(array_.at(index).type());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local_ref<JArrayClass<jobject>> ReadableNativeArray::importTypeArray() {
|
||||||
|
jint size = array_.size();
|
||||||
|
auto jarray = JArrayClass<jobject>::newArray(size);
|
||||||
|
for (jint i = 0; i < size; i++) {
|
||||||
|
jarray->setElement(i, ReadableNativeArray::getType(i).release());
|
||||||
|
}
|
||||||
|
return jarray;
|
||||||
|
}
|
||||||
|
|
||||||
local_ref<NativeMap::jhybridobject> ReadableNativeArray::getMap(jint index) {
|
local_ref<NativeMap::jhybridobject> ReadableNativeArray::getMap(jint index) {
|
||||||
auto& elem = array_.at(index);
|
auto& elem = array_.at(index);
|
||||||
return ReadableNativeMap::createWithContents(folly::dynamic(elem));
|
return ReadableNativeMap::createWithContents(folly::dynamic(elem));
|
||||||
|
@ -83,15 +134,17 @@ local_ref<ReadableNativeMap::jhybridobject> getMapFixed(alias_ref<ReadableNative
|
||||||
|
|
||||||
void ReadableNativeArray::registerNatives() {
|
void ReadableNativeArray::registerNatives() {
|
||||||
registerHybrid({
|
registerHybrid({
|
||||||
makeNativeMethod("size", ReadableNativeArray::getSize),
|
makeNativeMethod("importArray", ReadableNativeArray::importArray),
|
||||||
makeNativeMethod("isNull", ReadableNativeArray::isNull),
|
makeNativeMethod("importTypeArray", ReadableNativeArray::importTypeArray),
|
||||||
makeNativeMethod("getBoolean", ReadableNativeArray::getBoolean),
|
makeNativeMethod("sizeNative", ReadableNativeArray::getSize),
|
||||||
makeNativeMethod("getDouble", ReadableNativeArray::getDouble),
|
makeNativeMethod("isNullNative", ReadableNativeArray::isNull),
|
||||||
makeNativeMethod("getInt", ReadableNativeArray::getInt),
|
makeNativeMethod("getBooleanNative", ReadableNativeArray::getBoolean),
|
||||||
makeNativeMethod("getString", ReadableNativeArray::getString),
|
makeNativeMethod("getDoubleNative", ReadableNativeArray::getDouble),
|
||||||
makeNativeMethod("getArray", ReadableNativeArray::getArray),
|
makeNativeMethod("getIntNative", ReadableNativeArray::getInt),
|
||||||
makeNativeMethod("getMap", getMapFixed),
|
makeNativeMethod("getStringNative", ReadableNativeArray::getString),
|
||||||
makeNativeMethod("getType", ReadableNativeArray::getType),
|
makeNativeMethod("getArrayNative", ReadableNativeArray::getArray),
|
||||||
|
makeNativeMethod("getMapNative", getMapFixed),
|
||||||
|
makeNativeMethod("getTypeNative", ReadableNativeArray::getType),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ class ReadableNativeArray : public jni::HybridClass<ReadableNativeArray, NativeA
|
||||||
static constexpr const char* kJavaDescriptor = "Lcom/facebook/react/bridge/ReadableNativeArray;";
|
static constexpr const char* kJavaDescriptor = "Lcom/facebook/react/bridge/ReadableNativeArray;";
|
||||||
|
|
||||||
static void mapException(const std::exception& ex);
|
static void mapException(const std::exception& ex);
|
||||||
|
jni::local_ref<jni::JArrayClass<jobject>> importArray();
|
||||||
|
jni::local_ref<jni::JArrayClass<jobject>> importTypeArray();
|
||||||
jint getSize();
|
jint getSize();
|
||||||
jboolean isNull(jint index);
|
jboolean isNull(jint index);
|
||||||
jboolean getBoolean(jint index);
|
jboolean getBoolean(jint index);
|
||||||
|
|
Loading…
Reference in New Issue