Skip to content

Commit 5649aed

Browse files
Kathy Grayfacebook-github-bot
authored andcommitted
Move native accesses of array into one access instead of per-element
Differential Revision: D6578349 fbshipit-source-id: 84ebd66ed791a845e9cc0fbc7e12a377534aa903
1 parent 24e521c commit 5649aed

File tree

3 files changed

+194
-18
lines changed

3 files changed

+194
-18
lines changed

ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java

Lines changed: 130 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import com.facebook.proguard.annotations.DoNotStrip;
1414

1515
import java.util.ArrayList;
16+
import java.util.Arrays;
17+
import com.facebook.infer.annotation.Assertions;
18+
import javax.annotation.Nullable;
1619

1720
/**
1821
* Implementation of a NativeArray that allows read-only access to its members. This will generally
@@ -28,24 +31,142 @@ protected ReadableNativeArray(HybridData hybridData) {
2831
super(hybridData);
2932
}
3033

34+
//WriteOnce but not in the constructor fields
35+
private @Nullable Object[] mLocalArray;
36+
private @Nullable ReadableType[] mLocalTypeArray;
37+
38+
private static int jniPassCounter = 0;
39+
private static boolean mUseNativeAccessor = false;
40+
public static void setUseNativeAccessor(boolean useNativeAccessor) {
41+
mUseNativeAccessor = useNativeAccessor;
42+
}
43+
public static int getJNIPassCounter() {
44+
return jniPassCounter;
45+
}
46+
47+
private Object[] getLocalArray() {
48+
// Fast, non blocking check for the common case
49+
if (mLocalArray != null) {
50+
return mLocalArray;
51+
}
52+
synchronized (this) {
53+
// Make sure no concurrent call already updated
54+
if (mLocalArray == null) {
55+
jniPassCounter++;
56+
mLocalArray = Assertions.assertNotNull(importArray());
57+
}
58+
}
59+
return mLocalArray;
60+
}
61+
private native Object[] importArray();
62+
63+
private ReadableType[] getLocalTypeArray() {
64+
// Fast, non-blocking check for the common case
65+
if (mLocalTypeArray != null) {
66+
return mLocalTypeArray;
67+
}
68+
synchronized (this) {
69+
// Make sure no concurrent call already updated
70+
if (mLocalTypeArray == null) {
71+
jniPassCounter++;
72+
Object[] tempArray = Assertions.assertNotNull(importTypeArray());
73+
mLocalTypeArray = Arrays.copyOf(tempArray, tempArray.length, ReadableType[].class);
74+
}
75+
}
76+
return mLocalTypeArray;
77+
}
78+
private native Object[] importTypeArray();
79+
3180
@Override
32-
public native int size();
81+
public int size() {
82+
if (mUseNativeAccessor) {
83+
jniPassCounter++;
84+
return sizeNative();
85+
}
86+
return getLocalArray().length;
87+
}
88+
private native int sizeNative();
89+
3390
@Override
34-
public native boolean isNull(int index);
91+
public boolean isNull(int index) {
92+
if (mUseNativeAccessor) {
93+
jniPassCounter++;
94+
return isNullNative(index);
95+
}
96+
return getLocalArray()[index] == null;
97+
}
98+
private native boolean isNullNative(int index);
99+
35100
@Override
36-
public native boolean getBoolean(int index);
101+
public boolean getBoolean(int index) {
102+
if (mUseNativeAccessor) {
103+
jniPassCounter++;
104+
return getBooleanNative(index);
105+
}
106+
return ((Boolean) getLocalArray()[index]).booleanValue();
107+
}
108+
private native boolean getBooleanNative(int index);
109+
37110
@Override
38-
public native double getDouble(int index);
111+
public double getDouble(int index) {
112+
if (mUseNativeAccessor) {
113+
jniPassCounter++;
114+
return getDoubleNative(index);
115+
}
116+
return ((Double) getLocalArray()[index]).doubleValue();
117+
}
118+
private native double getDoubleNative(int index);
119+
39120
@Override
40-
public native int getInt(int index);
121+
public int getInt(int index) {
122+
if (mUseNativeAccessor) {
123+
jniPassCounter++;
124+
return getIntNative(index);
125+
}
126+
return ((Double) getLocalArray()[index]).intValue();
127+
}
128+
private native int getIntNative(int index);
129+
41130
@Override
42-
public native String getString(int index);
131+
public String getString(int index) {
132+
if (mUseNativeAccessor) {
133+
jniPassCounter++;
134+
return getStringNative(index);
135+
}
136+
return (String) getLocalArray()[index];
137+
}
138+
private native String getStringNative(int index);
139+
43140
@Override
44-
public native ReadableNativeArray getArray(int index);
141+
public ReadableNativeArray getArray(int index) {
142+
if (mUseNativeAccessor) {
143+
jniPassCounter++;
144+
return getArrayNative(index);
145+
}
146+
return (ReadableNativeArray) getLocalArray()[index];
147+
}
148+
private native ReadableNativeArray getArrayNative(int index);
149+
45150
@Override
46-
public native ReadableNativeMap getMap(int index);
151+
public ReadableNativeMap getMap(int index) {
152+
if (mUseNativeAccessor) {
153+
jniPassCounter++;
154+
return getMapNative(index);
155+
}
156+
return (ReadableNativeMap) getLocalArray()[index];
157+
}
158+
private native ReadableNativeMap getMapNative(int index);
159+
47160
@Override
48-
public native ReadableType getType(int index);
161+
public ReadableType getType(int index) {
162+
if (mUseNativeAccessor) {
163+
jniPassCounter++;
164+
return getTypeNative(index);
165+
}
166+
return getLocalTypeArray()[index];
167+
}
168+
169+
private native ReadableType getTypeNative(int index);
49170

50171
@Override
51172
public Dynamic getDynamic(int index) {

ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.cpp

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,48 @@ const char* ReadableNativeArray::getString(jint index) {
5656
return dyn.getString().c_str();
5757
}
5858

59+
local_ref<JArrayClass<jobject>> ReadableNativeArray::importArray() {
60+
jint size = array_.size();
61+
auto jarray = JArrayClass<jobject>::newArray(size);
62+
for (jint i = 0; i < size; i++) {
63+
switch(array_.at(i).type()) {
64+
case folly::dynamic::Type::NULLT: {
65+
jarray->setElement(i, nullptr);
66+
break;
67+
}
68+
case folly::dynamic::Type::BOOL: {
69+
jarray->
70+
setElement(i,
71+
JBoolean::valueOf(ReadableNativeArray::getBoolean(i)).release());
72+
break;
73+
}
74+
case folly::dynamic::Type::INT64:
75+
case folly::dynamic::Type::DOUBLE: {
76+
jarray->setElement(i,
77+
JDouble::valueOf(ReadableNativeArray::getDouble(i)).release());
78+
break;
79+
}
80+
case folly::dynamic::Type::STRING: {
81+
jarray->
82+
setElement(i,
83+
make_jstring(ReadableNativeArray::getString(i)).release());
84+
break;
85+
}
86+
case folly::dynamic::Type::OBJECT: {
87+
jarray->setElement(i,ReadableNativeArray::getMap(i).release());
88+
break;
89+
}
90+
case folly::dynamic::Type::ARRAY: {
91+
jarray->setElement(i,ReadableNativeArray::getArray(i).release());
92+
break;
93+
}
94+
default:
95+
break;
96+
}
97+
}
98+
return jarray;
99+
}
100+
59101
local_ref<ReadableNativeArray::jhybridobject> ReadableNativeArray::getArray(jint index) {
60102
auto& elem = array_.at(index);
61103
if (elem.isNull()) {
@@ -69,6 +111,15 @@ local_ref<ReadableType> ReadableNativeArray::getType(jint index) {
69111
return ReadableType::getType(array_.at(index).type());
70112
}
71113

114+
local_ref<JArrayClass<jobject>> ReadableNativeArray::importTypeArray() {
115+
jint size = array_.size();
116+
auto jarray = JArrayClass<jobject>::newArray(size);
117+
for (jint i = 0; i < size; i++) {
118+
jarray->setElement(i, ReadableNativeArray::getType(i).release());
119+
}
120+
return jarray;
121+
}
122+
72123
local_ref<NativeMap::jhybridobject> ReadableNativeArray::getMap(jint index) {
73124
auto& elem = array_.at(index);
74125
return ReadableNativeMap::createWithContents(folly::dynamic(elem));
@@ -83,15 +134,17 @@ local_ref<ReadableNativeMap::jhybridobject> getMapFixed(alias_ref<ReadableNative
83134

84135
void ReadableNativeArray::registerNatives() {
85136
registerHybrid({
86-
makeNativeMethod("size", ReadableNativeArray::getSize),
87-
makeNativeMethod("isNull", ReadableNativeArray::isNull),
88-
makeNativeMethod("getBoolean", ReadableNativeArray::getBoolean),
89-
makeNativeMethod("getDouble", ReadableNativeArray::getDouble),
90-
makeNativeMethod("getInt", ReadableNativeArray::getInt),
91-
makeNativeMethod("getString", ReadableNativeArray::getString),
92-
makeNativeMethod("getArray", ReadableNativeArray::getArray),
93-
makeNativeMethod("getMap", getMapFixed),
94-
makeNativeMethod("getType", ReadableNativeArray::getType),
137+
makeNativeMethod("importArray", ReadableNativeArray::importArray),
138+
makeNativeMethod("importTypeArray", ReadableNativeArray::importTypeArray),
139+
makeNativeMethod("sizeNative", ReadableNativeArray::getSize),
140+
makeNativeMethod("isNullNative", ReadableNativeArray::isNull),
141+
makeNativeMethod("getBooleanNative", ReadableNativeArray::getBoolean),
142+
makeNativeMethod("getDoubleNative", ReadableNativeArray::getDouble),
143+
makeNativeMethod("getIntNative", ReadableNativeArray::getInt),
144+
makeNativeMethod("getStringNative", ReadableNativeArray::getString),
145+
makeNativeMethod("getArrayNative", ReadableNativeArray::getArray),
146+
makeNativeMethod("getMapNative", getMapFixed),
147+
makeNativeMethod("getTypeNative", ReadableNativeArray::getType),
95148
});
96149
}
97150

ReactAndroid/src/main/jni/react/jni/ReadableNativeArray.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class ReadableNativeArray : public jni::HybridClass<ReadableNativeArray, NativeA
1919
static constexpr const char* kJavaDescriptor = "Lcom/facebook/react/bridge/ReadableNativeArray;";
2020

2121
static void mapException(const std::exception& ex);
22+
jni::local_ref<jni::JArrayClass<jobject>> importArray();
23+
jni::local_ref<jni::JArrayClass<jobject>> importTypeArray();
2224
jint getSize();
2325
jboolean isNull(jint index);
2426
jboolean getBoolean(jint index);

0 commit comments

Comments
 (0)