Skip to content

Commit

Permalink
Add PhantomRef based YogaNode subclass
Browse files Browse the repository at this point in the history
Summary: Adds a subclass of `YogaNodeJNIBase` that uses `PhantomReference` for deallocating native memory rather than `Object#finalize()`. This should help making garbage collection more efficient.

Reviewed By: amir-shalem

Differential Revision: D16182667

fbshipit-source-id: d310fdb6af184168c43462b24f5e18ab5d0d7ad0
  • Loading branch information
davidaurelio authored and facebook-github-bot committed Jul 20, 2019
1 parent 2b9f7ba commit 5ebc0ab
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 27 deletions.
4 changes: 2 additions & 2 deletions ReactAndroid/src/main/java/com/facebook/yoga/YogaNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

public abstract class YogaNode {
public static YogaNode create() {
return new YogaNodeJNIBase();
return new YogaNodeJNIFinalizer();
}

public static YogaNode create(YogaConfig config) {
return new YogaNodeJNIBase(config);
return new YogaNodeJNIFinalizer(config);
}

public abstract void reset();
Expand Down
34 changes: 9 additions & 25 deletions ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import javax.annotation.Nullable;

@DoNotStrip
public class YogaNodeJNIBase extends YogaNode implements Cloneable {
public abstract class YogaNodeJNIBase extends YogaNode implements Cloneable {

/* Those flags needs be in sync with YGJNI.cpp */
private static final byte MARGIN = 1;
Expand All @@ -35,7 +35,7 @@ public class YogaNodeJNIBase extends YogaNode implements Cloneable {
@Nullable private List<YogaNodeJNIBase> mChildren;
@Nullable private YogaMeasureFunction mMeasureFunction;
@Nullable private YogaBaselineFunction mBaselineFunction;
private long mNativePointer;
protected long mNativePointer;
@Nullable private Object mData;

@DoNotStrip
Expand All @@ -46,37 +46,21 @@ public class YogaNodeJNIBase extends YogaNode implements Cloneable {

private boolean mHasNewLayout = true;

public YogaNodeJNIBase() {
mNativePointer = YogaNative.jni_YGNodeNew();
if (mNativePointer == 0) {
private YogaNodeJNIBase(long nativePointer) {
if (nativePointer == 0) {
throw new IllegalStateException("Failed to allocate native memory");
}
mNativePointer = nativePointer;
}

public YogaNodeJNIBase(YogaConfig config) {
mNativePointer = YogaNative.jni_YGNodeNewWithConfig(config.mNativePointer);
if (mNativePointer == 0) {
throw new IllegalStateException("Failed to allocate native memory");
}
YogaNodeJNIBase() {
this(YogaNative.jni_YGNodeNew());
}

@Override
protected void finalize() throws Throwable {
try {
freeNatives();
} finally {
super.finalize();
}
YogaNodeJNIBase(YogaConfig config) {
this(YogaNative.jni_YGNodeNewWithConfig(config.mNativePointer));
}

/* frees the native underlying YGNode. Useful for testing. */
public void freeNatives() {
if (mNativePointer > 0) {
long nativePointer = mNativePointer;
mNativePointer = 0;
YogaNative.jni_YGNodeFree(nativePointer);
}
}
public void reset() {
mMeasureFunction = null;
mBaselineFunction = null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
package com.facebook.yoga;

public class YogaNodeJNIFinalizer extends YogaNodeJNIBase {
public YogaNodeJNIFinalizer() {
super();
}

public YogaNodeJNIFinalizer(YogaConfig config) {
super(config);
}

@Override
protected void finalize() throws Throwable {
try {
freeNatives();
} finally {
super.finalize();
}
}

public void freeNatives() {
if (mNativePointer != 0) {
long nativePointer = mNativePointer;
mNativePointer = 0;
YogaNative.jni_YGNodeFree(nativePointer);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
package com.facebook.yoga;

import com.facebook.jni.DestructorThread;

public class YogaNodeJNIPhantomRefs extends YogaNodeJNIBase {
public YogaNodeJNIPhantomRefs() {
super();
registerPhantomRef(this, mNativePointer);
}

public YogaNodeJNIPhantomRefs(YogaConfig config) {
super(config);
registerPhantomRef(this, mNativePointer);
}

@Override
public YogaNodeJNIPhantomRefs cloneWithoutChildren() {
YogaNodeJNIPhantomRefs clone = (YogaNodeJNIPhantomRefs) super.cloneWithoutChildren();
registerPhantomRef(clone, clone.mNativePointer);
return clone;
}

private static final void registerPhantomRef(YogaNode node, final long nativePointer) {
new DestructorThread.Destructor(node) {
private long mNativePointer = nativePointer;
@Override
protected void destruct() {
if (mNativePointer != 0) {
YogaNative.jni_YGNodeFree(mNativePointer);
mNativePointer = 0;
}
}
};
}
}

0 comments on commit 5ebc0ab

Please sign in to comment.