Create YogaValue instances in Java, not C++

Summary:
@public

Passing primitive data via JNI is more efficient than passing objects.

Here, we avoid creating `YogaValue` (Java) instances via JNI, and rather pass a `long` back to Java. The instance is then created by extracting the necessary bytes on the Java side.

Reviewed By: foghina

Differential Revision: D14576755

fbshipit-source-id: 22d09ad50c3ac6c49b0a797a0dad639ea4829df9
This commit is contained in:
David Aurelio
2019-03-22 10:31:18 -07:00
committed by Facebook Github Bot
parent 5bb2265083
commit ca46c67e9e
6 changed files with 67 additions and 48 deletions

View File

@@ -69,40 +69,40 @@ public class YogaNative {
static native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow); static native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow);
static native float jni_YGNodeStyleGetFlexShrink(long nativePointer); static native float jni_YGNodeStyleGetFlexShrink(long nativePointer);
static native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink); static native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink);
static native Object jni_YGNodeStyleGetFlexBasis(long nativePointer); static native long jni_YGNodeStyleGetFlexBasis(long nativePointer);
static native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis); static native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis);
static native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent); static native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent);
static native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer); static native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer);
static native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge); static native long jni_YGNodeStyleGetMargin(long nativePointer, int edge);
static native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin); static native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin);
static native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent); static native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent);
static native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge); static native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge);
static native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge); static native long jni_YGNodeStyleGetPadding(long nativePointer, int edge);
static native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding); static native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding);
static native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent); static native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent);
static native float jni_YGNodeStyleGetBorder(long nativePointer, int edge); static native float jni_YGNodeStyleGetBorder(long nativePointer, int edge);
static native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border); static native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border);
static native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge); static native long jni_YGNodeStyleGetPosition(long nativePointer, int edge);
static native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position); static native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position);
static native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent); static native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent);
static native Object jni_YGNodeStyleGetWidth(long nativePointer); static native long jni_YGNodeStyleGetWidth(long nativePointer);
static native void jni_YGNodeStyleSetWidth(long nativePointer, float width); static native void jni_YGNodeStyleSetWidth(long nativePointer, float width);
static native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent); static native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent);
static native void jni_YGNodeStyleSetWidthAuto(long nativePointer); static native void jni_YGNodeStyleSetWidthAuto(long nativePointer);
static native Object jni_YGNodeStyleGetHeight(long nativePointer); static native long jni_YGNodeStyleGetHeight(long nativePointer);
static native void jni_YGNodeStyleSetHeight(long nativePointer, float height); static native void jni_YGNodeStyleSetHeight(long nativePointer, float height);
static native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent); static native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent);
static native void jni_YGNodeStyleSetHeightAuto(long nativePointer); static native void jni_YGNodeStyleSetHeightAuto(long nativePointer);
static native Object jni_YGNodeStyleGetMinWidth(long nativePointer); static native long jni_YGNodeStyleGetMinWidth(long nativePointer);
static native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth); static native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth);
static native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent); static native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent);
static native Object jni_YGNodeStyleGetMinHeight(long nativePointer); static native long jni_YGNodeStyleGetMinHeight(long nativePointer);
static native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight); static native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight);
static native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent); static native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent);
static native Object jni_YGNodeStyleGetMaxWidth(long nativePointer); static native long jni_YGNodeStyleGetMaxWidth(long nativePointer);
static native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth); static native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth);
static native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent); static native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent);
static native Object jni_YGNodeStyleGetMaxHeight(long nativePointer); static native long jni_YGNodeStyleGetMaxHeight(long nativePointer);
static native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight); static native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight);
static native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent); static native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent);
static native float jni_YGNodeStyleGetAspectRatio(long nativePointer); static native float jni_YGNodeStyleGetAspectRatio(long nativePointer);

View File

@@ -349,7 +349,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getFlexBasis() { public YogaValue getFlexBasis() {
return (YogaValue) YogaNative.jni_YGNodeStyleGetFlexBasis(mNativePointer); return valueFromLong(YogaNative.jni_YGNodeStyleGetFlexBasis(mNativePointer));
} }
public void setFlexBasis(float flexBasis) { public void setFlexBasis(float flexBasis) {
@@ -365,7 +365,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getMargin(YogaEdge edge) { public YogaValue getMargin(YogaEdge edge) {
return (YogaValue) YogaNative.jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()); return valueFromLong(YogaNative.jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()));
} }
public void setMargin(YogaEdge edge, float margin) { public void setMargin(YogaEdge edge, float margin) {
@@ -381,7 +381,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getPadding(YogaEdge edge) { public YogaValue getPadding(YogaEdge edge) {
return (YogaValue) YogaNative.jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()); return valueFromLong(YogaNative.jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()));
} }
public void setPadding(YogaEdge edge, float padding) { public void setPadding(YogaEdge edge, float padding) {
@@ -401,7 +401,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getPosition(YogaEdge edge) { public YogaValue getPosition(YogaEdge edge) {
return (YogaValue) YogaNative.jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()); return valueFromLong(YogaNative.jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()));
} }
public void setPosition(YogaEdge edge, float position) { public void setPosition(YogaEdge edge, float position) {
@@ -413,7 +413,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getWidth() { public YogaValue getWidth() {
return (YogaValue) YogaNative.jni_YGNodeStyleGetWidth(mNativePointer); return valueFromLong(YogaNative.jni_YGNodeStyleGetWidth(mNativePointer));
} }
public void setWidth(float width) { public void setWidth(float width) {
@@ -429,7 +429,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getHeight() { public YogaValue getHeight() {
return (YogaValue) YogaNative.jni_YGNodeStyleGetHeight(mNativePointer); return valueFromLong(YogaNative.jni_YGNodeStyleGetHeight(mNativePointer));
} }
public void setHeight(float height) { public void setHeight(float height) {
@@ -445,7 +445,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getMinWidth() { public YogaValue getMinWidth() {
return (YogaValue) YogaNative.jni_YGNodeStyleGetMinWidth(mNativePointer); return valueFromLong(YogaNative.jni_YGNodeStyleGetMinWidth(mNativePointer));
} }
public void setMinWidth(float minWidth) { public void setMinWidth(float minWidth) {
@@ -457,7 +457,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getMinHeight() { public YogaValue getMinHeight() {
return (YogaValue) YogaNative.jni_YGNodeStyleGetMinHeight(mNativePointer); return valueFromLong(YogaNative.jni_YGNodeStyleGetMinHeight(mNativePointer));
} }
public void setMinHeight(float minHeight) { public void setMinHeight(float minHeight) {
@@ -469,7 +469,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getMaxWidth() { public YogaValue getMaxWidth() {
return (YogaValue) YogaNative.jni_YGNodeStyleGetMaxWidth(mNativePointer); return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxWidth(mNativePointer));
} }
public void setMaxWidth(float maxWidth) { public void setMaxWidth(float maxWidth) {
@@ -481,7 +481,7 @@ public abstract class YogaNodeJNIBase extends YogaNode {
} }
public YogaValue getMaxHeight() { public YogaValue getMaxHeight() {
return (YogaValue) YogaNative.jni_YGNodeStyleGetMaxHeight(mNativePointer); return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxHeight(mNativePointer));
} }
public void setMaxHeight(float maxheight) { public void setMaxHeight(float maxheight) {
@@ -656,4 +656,8 @@ public abstract class YogaNodeJNIBase extends YogaNode {
newNode.mOwner = this; newNode.mOwner = this;
return newNode.mNativePointer; return newNode.mNativePointer;
} }
private static YogaValue valueFromLong(long raw) {
return new YogaValue(Float.intBitsToFloat((int) raw), (int) (raw >> 32));
}
} }

View File

@@ -6,9 +6,6 @@
*/ */
package com.facebook.yoga; package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip
public class YogaValue { public class YogaValue {
static final YogaValue UNDEFINED = new YogaValue(YogaConstants.UNDEFINED, YogaUnit.UNDEFINED); static final YogaValue UNDEFINED = new YogaValue(YogaConstants.UNDEFINED, YogaUnit.UNDEFINED);
static final YogaValue ZERO = new YogaValue(0, YogaUnit.POINT); static final YogaValue ZERO = new YogaValue(0, YogaUnit.POINT);
@@ -22,7 +19,6 @@ public class YogaValue {
this.unit = unit; this.unit = unit;
} }
@DoNotStrip
YogaValue(float value, int unit) { YogaValue(float value, int unit) {
this(value, YogaUnit.fromInt(unit)); this(value, YogaUnit.fromInt(unit));
} }

View File

@@ -9,6 +9,7 @@
#include <yoga/Yoga.h> #include <yoga/Yoga.h>
#include <yoga/log.h> #include <yoga/log.h>
#include <cstdint> #include <cstdint>
#include <cstring>
#include <iostream> #include <iostream>
#include <map> #include <map>
@@ -128,6 +129,19 @@ public:
} }
}; };
struct YogaValue {
static constexpr jint NAN_BYTES = 0x7fc00000;
static jlong asJavaLong(const YGValue& value) {
uint32_t valueBytes = 0;
memcpy(&valueBytes, &value.value, sizeof valueBytes);
return ((jlong) value.unit) << 32 | valueBytes;
}
constexpr static jlong undefinedAsJavaLong() {
return ((jlong) YGUnitUndefined) << 32 | NAN_BYTES;
}
};
} // namespace } // namespace
static inline local_ref<JYogaNode> YGNodeJobject( static inline local_ref<JYogaNode> YGNodeJobject(
@@ -472,9 +486,8 @@ void jni_YGNodeCopyStyle(jlong dstNativePointer, jlong srcNativePointer) {
} }
#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ #define YG_NODE_JNI_STYLE_UNIT_PROP(name) \
local_ref<jobject> jni_YGNodeStyleGet##name( \ jlong jni_YGNodeStyleGet##name(alias_ref<jclass>, jlong nativePointer) { \
alias_ref<jclass>, jlong nativePointer) { \ return YogaValue::asJavaLong( \
return JYogaValue::create( \
YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \
} \ } \
\ \
@@ -509,9 +522,9 @@ void jni_YGNodeCopyStyle(jlong dstNativePointer, jlong srcNativePointer) {
} }
#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ #define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \
local_ref<jobject> jni_YGNodeStyleGet##name( \ jlong jni_YGNodeStyleGet##name( \
alias_ref<jclass>, jlong nativePointer, jint edge) { \ alias_ref<jclass>, jlong nativePointer, jint edge) { \
return JYogaValue::create(YGNodeStyleGet##name( \ return YogaValue::asJavaLong(YGNodeStyleGet##name( \
_jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge))); \ _jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge))); \
} \ } \
\ \
@@ -841,15 +854,15 @@ jint jni_YGNodeGetInstanceCount() {
return YGNodeGetInstanceCount(); return YGNodeGetInstanceCount();
} }
local_ref<jobject> jni_YGNodeStyleGetMargin( jlong jni_YGNodeStyleGetMargin(
alias_ref<jclass>, alias_ref<jclass>,
jlong nativePointer, jlong nativePointer,
jint edge) { jint edge) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer); YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::MARGIN)) { if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::MARGIN)) {
return JYogaValue::create(YGValueUndefined); return YogaValue::undefinedAsJavaLong();
} }
return JYogaValue::create( return YogaValue::asJavaLong(
YGNodeStyleGetMargin(yogaNodeRef, static_cast<YGEdge>(edge))); YGNodeStyleGetMargin(yogaNodeRef, static_cast<YGEdge>(edge)));
} }
@@ -876,15 +889,15 @@ void jni_YGNodeStyleSetMarginAuto(jlong nativePointer, jint edge) {
YGNodeStyleSetMarginAuto(yogaNodeRef, static_cast<YGEdge>(edge)); YGNodeStyleSetMarginAuto(yogaNodeRef, static_cast<YGEdge>(edge));
} }
local_ref<jobject> jni_YGNodeStyleGetPadding( jlong jni_YGNodeStyleGetPadding(
alias_ref<jclass>, alias_ref<jclass>,
jlong nativePointer, jlong nativePointer,
jint edge) { jint edge) {
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer); YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::PADDING)) { if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::PADDING)) {
return JYogaValue::create(YGValueUndefined); return YogaValue::undefinedAsJavaLong();
} }
return JYogaValue::create( return YogaValue::asJavaLong(
YGNodeStyleGetPadding(yogaNodeRef, static_cast<YGEdge>(edge))); YGNodeStyleGetPadding(yogaNodeRef, static_cast<YGEdge>(edge)));
} }

View File

@@ -28,11 +28,3 @@ struct JYogaLogger : public facebook::jni::JavaClass<JYogaLogger> {
facebook::jni::alias_ref<JYogaLogLevel>, facebook::jni::alias_ref<JYogaLogLevel>,
jstring); jstring);
}; };
struct JYogaValue : public facebook::jni::JavaClass<JYogaValue> {
constexpr static auto kJavaDescriptor = "Lcom/facebook/yoga/YogaValue;";
static facebook::jni::local_ref<javaobject> create(YGValue value) {
return newInstance(value.value, static_cast<int>(value.unit));
}
};

View File

@@ -1,9 +1,8 @@
/* /**
* Copyright (c) Facebook, Inc. and its affiliates. * 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.
* *
* 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; package com.facebook.yoga;
@@ -401,6 +400,21 @@ public class YogaNodeStylePropertiesTest {
} }
} }
@Test
public void testNegativeMarginAssignment() {
final YogaNode node = createNode();
for (YogaEdge edge : YogaEdge.values()) {
node.setMargin(edge, -25);
assertEquals(new YogaValue(-25, YogaUnit.POINT), node.getMargin(edge));
node.setMarginPercent(edge, -5);
assertEquals(new YogaValue(-5, YogaUnit.PERCENT), node.getMargin(edge));
node.setMarginAuto(edge);
assertEquals(YogaValue.AUTO, node.getMargin(edge));
}
}
@Test @Test
public void testMarginPointAffectsLayout() { public void testMarginPointAffectsLayout() {
final YogaNode node = style().margin(YogaEdge.TOP, 42).node(); final YogaNode node = style().margin(YogaEdge.TOP, 42).node();