Cleanup ReadableMapBuffer

Summary:
Cleans up `ReadableMapBuffer` APIs and migrates to use `std::vector` instead of raw pointer array.

Also uses `fbjni` utility to allocate the bytes instead of making manual JNI calls.

Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D33513027

fbshipit-source-id: afe7d320d12830503de4c9994117d849f0b25245
This commit is contained in:
Andrei Shikov
2022-01-12 08:13:32 -08:00
committed by Facebook GitHub Bot
parent aaff15c2c8
commit f33892081a
4 changed files with 17 additions and 63 deletions
@@ -55,6 +55,7 @@ public class ReadableMapBuffer implements Iterable<ReadableMapBuffer.MapBufferEn
@SuppressWarnings("unused")
private short mCount = 0;
@DoNotStrip
private ReadableMapBuffer(HybridData hybridData) {
mHybridData = hybridData;
}
@@ -64,8 +65,6 @@ public class ReadableMapBuffer implements Iterable<ReadableMapBuffer.MapBufferEn
readHeader();
}
private native ByteBuffer importByteBufferAllocateDirect();
private native ByteBuffer importByteBuffer();
@SuppressWarnings("unused")
@@ -73,14 +72,6 @@ public class ReadableMapBuffer implements Iterable<ReadableMapBuffer.MapBufferEn
@Nullable
private HybridData mHybridData;
@Override
protected void finalize() throws Throwable {
super.finalize();
if (mHybridData != null) {
mHybridData.resetNative();
}
}
private int getKeyOffsetForBucketIndex(int bucketIndex) {
return HEADER_SIZE + BUCKET_SIZE * bucketIndex;
}
@@ -13,36 +13,10 @@ namespace react {
void ReadableMapBuffer::registerNatives() {
registerHybrid({
makeNativeMethod("importByteBuffer", ReadableMapBuffer::importByteBuffer),
makeNativeMethod(
"importByteBufferAllocateDirect",
ReadableMapBuffer::importByteBufferAllocateDirect),
});
}
jni::local_ref<jni::JByteBuffer>
ReadableMapBuffer::importByteBufferAllocateDirect() {
// TODO T83483191: Using this method is safer than "importByteBuffer" because
// ByteBuffer memory will be deallocated once the "Java ByteBuffer" is
// deallocated. Next steps:
// - Validate perf of this method vs importByteBuffer
// - Validate that there's no leaking of memory
react_native_assert(
(serializedData_ != nullptr && serializedDataSize_ != 0) &&
"Error serializedData_ is not initialized");
auto ret = jni::JByteBuffer::allocateDirect(serializedDataSize_);
// TODO T83483191: avoid allocating serializedData_ when using
// JByteBuffer::allocateDirect
std::memcpy(
ret->getDirectBytes(), (void *)serializedData_, serializedDataSize_);
// Deallocate serializedData_ since it's not necessary anymore
delete[] serializedData_;
serializedData_ = nullptr;
serializedDataSize_ = 0;
return ret;
}
jni::JByteBuffer::javaobject ReadableMapBuffer::importByteBuffer() {
jni::local_ref<jni::JByteBuffer> ReadableMapBuffer::importByteBuffer() {
// TODO T83483191: Reevaluate what's the best approach here (allocateDirect vs
// DirectByteBuffer).
//
@@ -55,9 +29,8 @@ jni::JByteBuffer::javaobject ReadableMapBuffer::importByteBuffer() {
// - Add flags to describe if the data was already 'imported'
// - Long-term: Consider creating a big ByteBuffer that can be re-used to
// transfer data of multitple Maps
return static_cast<jni::JByteBuffer::javaobject>(
jni::Environment::current()->NewDirectByteBuffer(
(void *)serializedData_, serializedDataSize_));
return jni::JByteBuffer::wrapBytes(
serializedData_.data(), serializedData_.size());
}
jni::local_ref<ReadableMapBuffer::jhybridobject>
@@ -65,11 +38,10 @@ ReadableMapBuffer::createWithContents(MapBuffer &&map) {
return newObjectCxxArgs(std::move(map));
}
ReadableMapBuffer::~ReadableMapBuffer() {
if (serializedData_ != nullptr) {
delete[] serializedData_;
serializedData_ = nullptr;
}
ReadableMapBuffer::ReadableMapBuffer(MapBuffer &&map)
: serializedData_(std::move(map.bytes_)) {
react_native_assert(
(serializedData_.size() != 0) && "Error no content in map");
}
} // namespace react
@@ -23,28 +23,15 @@ class ReadableMapBuffer : public jni::HybridClass<ReadableMapBuffer> {
static void registerNatives();
static jni::local_ref<jhybridobject> createWithContents(MapBuffer &&map);
static jni::local_ref<ReadableMapBuffer::jhybridobject> createWithContents(
MapBuffer &&map);
jni::local_ref<jni::JByteBuffer> importByteBufferAllocateDirect();
explicit ReadableMapBuffer(MapBuffer &&map);
jni::JByteBuffer::javaobject importByteBuffer();
~ReadableMapBuffer();
jni::local_ref<jni::JByteBuffer> importByteBuffer();
private:
uint8_t *serializedData_ = nullptr;
int32_t serializedDataSize_ = 0;
friend HybridBase;
explicit ReadableMapBuffer(MapBuffer &&map) {
serializedDataSize_ = map.getBufferSize();
react_native_assert(
(serializedDataSize_ != 0) && "Error no content in map");
serializedData_ = new Byte[serializedDataSize_];
map.copy(serializedData_);
}
std::vector<uint8_t> serializedData_;
};
} // namespace react