Skip to content

Commit ca46c67

Browse files
davidaureliofacebook-github-bot
authored andcommitted
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
1 parent 5bb2265 commit ca46c67

File tree

6 files changed

+67
-48
lines changed

6 files changed

+67
-48
lines changed

java/com/facebook/yoga/YogaNative.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,40 +69,40 @@ public class YogaNative {
6969
static native void jni_YGNodeStyleSetFlexGrow(long nativePointer, float flexGrow);
7070
static native float jni_YGNodeStyleGetFlexShrink(long nativePointer);
7171
static native void jni_YGNodeStyleSetFlexShrink(long nativePointer, float flexShrink);
72-
static native Object jni_YGNodeStyleGetFlexBasis(long nativePointer);
72+
static native long jni_YGNodeStyleGetFlexBasis(long nativePointer);
7373
static native void jni_YGNodeStyleSetFlexBasis(long nativePointer, float flexBasis);
7474
static native void jni_YGNodeStyleSetFlexBasisPercent(long nativePointer, float percent);
7575
static native void jni_YGNodeStyleSetFlexBasisAuto(long nativePointer);
76-
static native Object jni_YGNodeStyleGetMargin(long nativePointer, int edge);
76+
static native long jni_YGNodeStyleGetMargin(long nativePointer, int edge);
7777
static native void jni_YGNodeStyleSetMargin(long nativePointer, int edge, float margin);
7878
static native void jni_YGNodeStyleSetMarginPercent(long nativePointer, int edge, float percent);
7979
static native void jni_YGNodeStyleSetMarginAuto(long nativePointer, int edge);
80-
static native Object jni_YGNodeStyleGetPadding(long nativePointer, int edge);
80+
static native long jni_YGNodeStyleGetPadding(long nativePointer, int edge);
8181
static native void jni_YGNodeStyleSetPadding(long nativePointer, int edge, float padding);
8282
static native void jni_YGNodeStyleSetPaddingPercent(long nativePointer, int edge, float percent);
8383
static native float jni_YGNodeStyleGetBorder(long nativePointer, int edge);
8484
static native void jni_YGNodeStyleSetBorder(long nativePointer, int edge, float border);
85-
static native Object jni_YGNodeStyleGetPosition(long nativePointer, int edge);
85+
static native long jni_YGNodeStyleGetPosition(long nativePointer, int edge);
8686
static native void jni_YGNodeStyleSetPosition(long nativePointer, int edge, float position);
8787
static native void jni_YGNodeStyleSetPositionPercent(long nativePointer, int edge, float percent);
88-
static native Object jni_YGNodeStyleGetWidth(long nativePointer);
88+
static native long jni_YGNodeStyleGetWidth(long nativePointer);
8989
static native void jni_YGNodeStyleSetWidth(long nativePointer, float width);
9090
static native void jni_YGNodeStyleSetWidthPercent(long nativePointer, float percent);
9191
static native void jni_YGNodeStyleSetWidthAuto(long nativePointer);
92-
static native Object jni_YGNodeStyleGetHeight(long nativePointer);
92+
static native long jni_YGNodeStyleGetHeight(long nativePointer);
9393
static native void jni_YGNodeStyleSetHeight(long nativePointer, float height);
9494
static native void jni_YGNodeStyleSetHeightPercent(long nativePointer, float percent);
9595
static native void jni_YGNodeStyleSetHeightAuto(long nativePointer);
96-
static native Object jni_YGNodeStyleGetMinWidth(long nativePointer);
96+
static native long jni_YGNodeStyleGetMinWidth(long nativePointer);
9797
static native void jni_YGNodeStyleSetMinWidth(long nativePointer, float minWidth);
9898
static native void jni_YGNodeStyleSetMinWidthPercent(long nativePointer, float percent);
99-
static native Object jni_YGNodeStyleGetMinHeight(long nativePointer);
99+
static native long jni_YGNodeStyleGetMinHeight(long nativePointer);
100100
static native void jni_YGNodeStyleSetMinHeight(long nativePointer, float minHeight);
101101
static native void jni_YGNodeStyleSetMinHeightPercent(long nativePointer, float percent);
102-
static native Object jni_YGNodeStyleGetMaxWidth(long nativePointer);
102+
static native long jni_YGNodeStyleGetMaxWidth(long nativePointer);
103103
static native void jni_YGNodeStyleSetMaxWidth(long nativePointer, float maxWidth);
104104
static native void jni_YGNodeStyleSetMaxWidthPercent(long nativePointer, float percent);
105-
static native Object jni_YGNodeStyleGetMaxHeight(long nativePointer);
105+
static native long jni_YGNodeStyleGetMaxHeight(long nativePointer);
106106
static native void jni_YGNodeStyleSetMaxHeight(long nativePointer, float maxheight);
107107
static native void jni_YGNodeStyleSetMaxHeightPercent(long nativePointer, float percent);
108108
static native float jni_YGNodeStyleGetAspectRatio(long nativePointer);

java/com/facebook/yoga/YogaNodeJNIBase.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ public void setFlexShrink(float flexShrink) {
349349
}
350350

351351
public YogaValue getFlexBasis() {
352-
return (YogaValue) YogaNative.jni_YGNodeStyleGetFlexBasis(mNativePointer);
352+
return valueFromLong(YogaNative.jni_YGNodeStyleGetFlexBasis(mNativePointer));
353353
}
354354

355355
public void setFlexBasis(float flexBasis) {
@@ -365,7 +365,7 @@ public void setFlexBasisAuto() {
365365
}
366366

367367
public YogaValue getMargin(YogaEdge edge) {
368-
return (YogaValue) YogaNative.jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue());
368+
return valueFromLong(YogaNative.jni_YGNodeStyleGetMargin(mNativePointer, edge.intValue()));
369369
}
370370

371371
public void setMargin(YogaEdge edge, float margin) {
@@ -381,7 +381,7 @@ public void setMarginAuto(YogaEdge edge) {
381381
}
382382

383383
public YogaValue getPadding(YogaEdge edge) {
384-
return (YogaValue) YogaNative.jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue());
384+
return valueFromLong(YogaNative.jni_YGNodeStyleGetPadding(mNativePointer, edge.intValue()));
385385
}
386386

387387
public void setPadding(YogaEdge edge, float padding) {
@@ -401,7 +401,7 @@ public void setBorder(YogaEdge edge, float border) {
401401
}
402402

403403
public YogaValue getPosition(YogaEdge edge) {
404-
return (YogaValue) YogaNative.jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue());
404+
return valueFromLong(YogaNative.jni_YGNodeStyleGetPosition(mNativePointer, edge.intValue()));
405405
}
406406

407407
public void setPosition(YogaEdge edge, float position) {
@@ -413,7 +413,7 @@ public void setPositionPercent(YogaEdge edge, float percent) {
413413
}
414414

415415
public YogaValue getWidth() {
416-
return (YogaValue) YogaNative.jni_YGNodeStyleGetWidth(mNativePointer);
416+
return valueFromLong(YogaNative.jni_YGNodeStyleGetWidth(mNativePointer));
417417
}
418418

419419
public void setWidth(float width) {
@@ -429,7 +429,7 @@ public void setWidthAuto() {
429429
}
430430

431431
public YogaValue getHeight() {
432-
return (YogaValue) YogaNative.jni_YGNodeStyleGetHeight(mNativePointer);
432+
return valueFromLong(YogaNative.jni_YGNodeStyleGetHeight(mNativePointer));
433433
}
434434

435435
public void setHeight(float height) {
@@ -445,7 +445,7 @@ public void setHeightAuto() {
445445
}
446446

447447
public YogaValue getMinWidth() {
448-
return (YogaValue) YogaNative.jni_YGNodeStyleGetMinWidth(mNativePointer);
448+
return valueFromLong(YogaNative.jni_YGNodeStyleGetMinWidth(mNativePointer));
449449
}
450450

451451
public void setMinWidth(float minWidth) {
@@ -457,7 +457,7 @@ public void setMinWidthPercent(float percent) {
457457
}
458458

459459
public YogaValue getMinHeight() {
460-
return (YogaValue) YogaNative.jni_YGNodeStyleGetMinHeight(mNativePointer);
460+
return valueFromLong(YogaNative.jni_YGNodeStyleGetMinHeight(mNativePointer));
461461
}
462462

463463
public void setMinHeight(float minHeight) {
@@ -469,7 +469,7 @@ public void setMinHeightPercent(float percent) {
469469
}
470470

471471
public YogaValue getMaxWidth() {
472-
return (YogaValue) YogaNative.jni_YGNodeStyleGetMaxWidth(mNativePointer);
472+
return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxWidth(mNativePointer));
473473
}
474474

475475
public void setMaxWidth(float maxWidth) {
@@ -481,7 +481,7 @@ public void setMaxWidthPercent(float percent) {
481481
}
482482

483483
public YogaValue getMaxHeight() {
484-
return (YogaValue) YogaNative.jni_YGNodeStyleGetMaxHeight(mNativePointer);
484+
return valueFromLong(YogaNative.jni_YGNodeStyleGetMaxHeight(mNativePointer));
485485
}
486486

487487
public void setMaxHeight(float maxheight) {
@@ -656,4 +656,8 @@ private final long replaceChild(YogaNodeJNIBase newNode, int childIndex) {
656656
newNode.mOwner = this;
657657
return newNode.mNativePointer;
658658
}
659+
660+
private static YogaValue valueFromLong(long raw) {
661+
return new YogaValue(Float.intBitsToFloat((int) raw), (int) (raw >> 32));
662+
}
659663
}

java/com/facebook/yoga/YogaValue.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
*/
77
package com.facebook.yoga;
88

9-
import com.facebook.proguard.annotations.DoNotStrip;
10-
11-
@DoNotStrip
129
public class YogaValue {
1310
static final YogaValue UNDEFINED = new YogaValue(YogaConstants.UNDEFINED, YogaUnit.UNDEFINED);
1411
static final YogaValue ZERO = new YogaValue(0, YogaUnit.POINT);
@@ -22,7 +19,6 @@ public YogaValue(float value, YogaUnit unit) {
2219
this.unit = unit;
2320
}
2421

25-
@DoNotStrip
2622
YogaValue(float value, int unit) {
2723
this(value, YogaUnit.fromInt(unit));
2824
}

java/jni/YGJNI.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <yoga/Yoga.h>
1010
#include <yoga/log.h>
1111
#include <cstdint>
12+
#include <cstring>
1213
#include <iostream>
1314
#include <map>
1415

@@ -128,6 +129,19 @@ class YGNodeEdges {
128129
}
129130
};
130131

132+
struct YogaValue {
133+
static constexpr jint NAN_BYTES = 0x7fc00000;
134+
135+
static jlong asJavaLong(const YGValue& value) {
136+
uint32_t valueBytes = 0;
137+
memcpy(&valueBytes, &value.value, sizeof valueBytes);
138+
return ((jlong) value.unit) << 32 | valueBytes;
139+
}
140+
constexpr static jlong undefinedAsJavaLong() {
141+
return ((jlong) YGUnitUndefined) << 32 | NAN_BYTES;
142+
}
143+
};
144+
131145
} // namespace
132146

133147
static inline local_ref<JYogaNode> YGNodeJobject(
@@ -472,9 +486,8 @@ void jni_YGNodeCopyStyle(jlong dstNativePointer, jlong srcNativePointer) {
472486
}
473487

474488
#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \
475-
local_ref<jobject> jni_YGNodeStyleGet##name( \
476-
alias_ref<jclass>, jlong nativePointer) { \
477-
return JYogaValue::create( \
489+
jlong jni_YGNodeStyleGet##name(alias_ref<jclass>, jlong nativePointer) { \
490+
return YogaValue::asJavaLong( \
478491
YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \
479492
} \
480493
\
@@ -509,9 +522,9 @@ void jni_YGNodeCopyStyle(jlong dstNativePointer, jlong srcNativePointer) {
509522
}
510523

511524
#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \
512-
local_ref<jobject> jni_YGNodeStyleGet##name( \
525+
jlong jni_YGNodeStyleGet##name( \
513526
alias_ref<jclass>, jlong nativePointer, jint edge) { \
514-
return JYogaValue::create(YGNodeStyleGet##name( \
527+
return YogaValue::asJavaLong(YGNodeStyleGet##name( \
515528
_jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge))); \
516529
} \
517530
\
@@ -841,15 +854,15 @@ jint jni_YGNodeGetInstanceCount() {
841854
return YGNodeGetInstanceCount();
842855
}
843856

844-
local_ref<jobject> jni_YGNodeStyleGetMargin(
857+
jlong jni_YGNodeStyleGetMargin(
845858
alias_ref<jclass>,
846859
jlong nativePointer,
847860
jint edge) {
848861
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
849862
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::MARGIN)) {
850-
return JYogaValue::create(YGValueUndefined);
863+
return YogaValue::undefinedAsJavaLong();
851864
}
852-
return JYogaValue::create(
865+
return YogaValue::asJavaLong(
853866
YGNodeStyleGetMargin(yogaNodeRef, static_cast<YGEdge>(edge)));
854867
}
855868

@@ -876,15 +889,15 @@ void jni_YGNodeStyleSetMarginAuto(jlong nativePointer, jint edge) {
876889
YGNodeStyleSetMarginAuto(yogaNodeRef, static_cast<YGEdge>(edge));
877890
}
878891

879-
local_ref<jobject> jni_YGNodeStyleGetPadding(
892+
jlong jni_YGNodeStyleGetPadding(
880893
alias_ref<jclass>,
881894
jlong nativePointer,
882895
jint edge) {
883896
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
884897
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::PADDING)) {
885-
return JYogaValue::create(YGValueUndefined);
898+
return YogaValue::undefinedAsJavaLong();
886899
}
887-
return JYogaValue::create(
900+
return YogaValue::asJavaLong(
888901
YGNodeStyleGetPadding(yogaNodeRef, static_cast<YGEdge>(edge)));
889902
}
890903

java/jni/YGJTypes.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,3 @@ struct JYogaLogger : public facebook::jni::JavaClass<JYogaLogger> {
2828
facebook::jni::alias_ref<JYogaLogLevel>,
2929
jstring);
3030
};
31-
32-
struct JYogaValue : public facebook::jni::JavaClass<JYogaValue> {
33-
constexpr static auto kJavaDescriptor = "Lcom/facebook/yoga/YogaValue;";
34-
35-
static facebook::jni::local_ref<javaobject> create(YGValue value) {
36-
return newInstance(value.value, static_cast<int>(value.unit));
37-
}
38-
};

java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
/*
2-
* Copyright (c) Facebook, Inc. and its affiliates.
3-
*
4-
* This source code is licensed under the MIT license found in the LICENSE
5-
* file in the root directory of this source tree.
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
63
*
4+
* This source code is licensed under the MIT license found in the LICENSE
5+
* file in the root directory of this source tree.
76
*/
87
package com.facebook.yoga;
98

@@ -401,6 +400,21 @@ public void testMarginAssignment() {
401400
}
402401
}
403402

403+
@Test
404+
public void testNegativeMarginAssignment() {
405+
final YogaNode node = createNode();
406+
for (YogaEdge edge : YogaEdge.values()) {
407+
node.setMargin(edge, -25);
408+
assertEquals(new YogaValue(-25, YogaUnit.POINT), node.getMargin(edge));
409+
410+
node.setMarginPercent(edge, -5);
411+
assertEquals(new YogaValue(-5, YogaUnit.PERCENT), node.getMargin(edge));
412+
413+
node.setMarginAuto(edge);
414+
assertEquals(YogaValue.AUTO, node.getMargin(edge));
415+
}
416+
}
417+
404418
@Test
405419
public void testMarginPointAffectsLayout() {
406420
final YogaNode node = style().margin(YogaEdge.TOP, 42).node();

0 commit comments

Comments
 (0)