No more weak JNI refs!

Summary:
@public

Completely removes the usage of weak JNI refs.

This is great, because node allocation and deallocation no longer go through a VM-global lock to access the weak reference table.
This is also great, because we can no longer overflow that ref table.
Performance is comparable to weak refs.

Reviewed By: marco-cova

Differential Revision: D14423068

fbshipit-source-id: 62003d2d6fd971e91460a26fb3477046f26e2ba5
This commit is contained in:
David Aurelio
2019-03-12 12:59:58 -07:00
committed by Facebook Github Bot
parent 7890672ecc
commit 3331a9e480
2 changed files with 21 additions and 42 deletions

View File

@@ -36,8 +36,6 @@ public class YogaNodeJNI extends YogaNode {
private static final int PADDING = 2; private static final int PADDING = 2;
private static final int BORDER = 4; private static final int BORDER = 4;
private final boolean mAvoidGlobalJNIRefs;
@DoNotStrip @DoNotStrip
private float mWidth = YogaConstants.UNDEFINED; private float mWidth = YogaConstants.UNDEFINED;
@DoNotStrip @DoNotStrip
@@ -78,17 +76,15 @@ public class YogaNodeJNI extends YogaNode {
private native long jni_YGNodeNew(); private native long jni_YGNodeNew();
public YogaNodeJNI() { public YogaNodeJNI() {
mAvoidGlobalJNIRefs = false;
mNativePointer = jni_YGNodeNew(); mNativePointer = jni_YGNodeNew();
if (mNativePointer == 0) { if (mNativePointer == 0) {
throw new IllegalStateException("Failed to allocate native memory"); throw new IllegalStateException("Failed to allocate native memory");
} }
} }
private native long jni_YGNodeNewWithConfig(long configPointer, boolean avoidGlobalJNIRefs); private native long jni_YGNodeNewWithConfig(long configPointer);
public YogaNodeJNI(YogaConfig config) { public YogaNodeJNI(YogaConfig config) {
mAvoidGlobalJNIRefs = config.avoidGlobalJNIRefs; mNativePointer = jni_YGNodeNewWithConfig(config.mNativePointer);
mNativePointer = jni_YGNodeNewWithConfig(config.mNativePointer, mAvoidGlobalJNIRefs);
if (mNativePointer == 0) { if (mNativePointer == 0) {
throw new IllegalStateException("Failed to allocate native memory"); throw new IllegalStateException("Failed to allocate native memory");
} }
@@ -231,21 +227,19 @@ public class YogaNodeJNI extends YogaNode {
long[] nativePointers = null; long[] nativePointers = null;
YogaNodeJNI[] nodes = null; YogaNodeJNI[] nodes = null;
if (mAvoidGlobalJNIRefs) { ArrayList<YogaNodeJNI> n = new ArrayList<>();
ArrayList<YogaNodeJNI> n = new ArrayList<>(); n.add(this);
n.add(this); for (int i = 0; i < n.size(); ++i) {
for (int i = 0; i < n.size(); ++i) { List<YogaNodeJNI> children = n.get(i).mChildren;
List<YogaNodeJNI> children = n.get(i).mChildren; if (children != null) {
if (children != null) { n.addAll(children);
n.addAll(children);
}
} }
}
nodes = n.toArray(new YogaNodeJNI[n.size()]); nodes = n.toArray(new YogaNodeJNI[n.size()]);
nativePointers = new long[nodes.length]; nativePointers = new long[nodes.length];
for (int i = 0; i < nodes.length; ++i) { for (int i = 0; i < nodes.length; ++i) {
nativePointers[i] = nodes[i].mNativePointer; nativePointers[i] = nodes[i].mNativePointer;
}
} }
jni_YGNodeCalculateLayout(mNativePointer, width, height, nativePointers, nodes); jni_YGNodeCalculateLayout(mNativePointer, width, height, nativePointers, nodes);

View File

@@ -89,11 +89,7 @@ public:
}; };
struct YGNodeContext { struct YGNodeContext {
weak_ref<jobject>* ygNodeJObjectRef{nullptr};
int edgeSetFlag = 0; int edgeSetFlag = 0;
~YGNodeContext() {
delete ygNodeJObjectRef;
}
}; };
const int MARGIN = 1; const int MARGIN = 1;
@@ -107,13 +103,7 @@ static inline YGNodeContext* ygNodeRefToYGNodeContext(YGNodeRef node) {
static inline local_ref<JYogaNode> YGNodeJobject( static inline local_ref<JYogaNode> YGNodeJobject(
YGNodeRef node, YGNodeRef node,
void* layoutContext) { void* layoutContext) {
if (layoutContext == nullptr) { return reinterpret_cast<PtrJNodeMap*>(layoutContext)->ref(node);
return (reinterpret_cast<weak_ref<JYogaNode>*>(
ygNodeRefToYGNodeContext(node)->ygNodeJObjectRef))
->lockLocal();
} else {
return reinterpret_cast<PtrJNodeMap*>(layoutContext)->ref(node);
}
} }
static void YGTransferLayoutDirection( static void YGTransferLayoutDirection(
@@ -320,25 +310,20 @@ static int YGJNILogFunc(
return result; return result;
} }
YGNodeContext* createYGNodeContext(alias_ref<jobject> thiz) { YGNodeContext* createYGNodeContext() {
YGNodeContext* ygNodeContext = new YGNodeContext(); return new YGNodeContext();
ygNodeContext->ygNodeJObjectRef = new weak_ref<jobject>(make_weak(thiz));
return ygNodeContext;
} }
jlong jni_YGNodeNew(alias_ref<jobject> thiz) { jlong jni_YGNodeNew(alias_ref<jobject>) {
const YGNodeRef node = YGNodeNew(); const YGNodeRef node = YGNodeNew();
node->setContext(createYGNodeContext(thiz)); node->setContext(createYGNodeContext());
node->setPrintFunc(YGPrint); node->setPrintFunc(YGPrint);
return reinterpret_cast<jlong>(node); return reinterpret_cast<jlong>(node);
} }
jlong jni_YGNodeNewWithConfig( jlong jni_YGNodeNewWithConfig(alias_ref<jobject>, jlong configPointer) {
alias_ref<jobject> thiz,
jlong configPointer,
jboolean avoidGlobalJNIRefs) {
const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer)); const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer));
node->setContext(createYGNodeContext(avoidGlobalJNIRefs ? nullptr : thiz)); node->setContext(createYGNodeContext());
return reinterpret_cast<jlong>(node); return reinterpret_cast<jlong>(node);
} }
@@ -817,7 +802,7 @@ static void YGNodeSetStyleInputs(
} }
void jni_YGNodeSetStyleInputs( void jni_YGNodeSetStyleInputs(
alias_ref<jobject> thiz, alias_ref<jobject>,
jlong nativePointer, jlong nativePointer,
alias_ref<JArrayFloat> styleInputs, alias_ref<JArrayFloat> styleInputs,
jint size) { jint size) {