Unverified Commit f9444dab authored by Oleksandr Karpovich's avatar Oleksandr Karpovich Committed by GitHub

refactor `toInterop` to avoid unnecessary array copies in js when used withing `withResult` (#465)

Co-authored-by: 's avatarOleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
parent e41633e8
...@@ -23,21 +23,36 @@ fun getPtr(n: Native?): NativePointer = n?._ptr ?: Native.NullPointer ...@@ -23,21 +23,36 @@ fun getPtr(n: Native?): NativePointer = n?._ptr ?: Native.NullPointer
expect class InteropScope() { expect class InteropScope() {
fun toInterop(string: String?): InteropPointer fun toInterop(string: String?): InteropPointer
fun toInterop(array: ByteArray?): InteropPointer fun toInterop(array: ByteArray?): InteropPointer
fun toInteropForResult(array: ByteArray?): InteropPointer
fun InteropPointer.fromInterop(result: ByteArray) fun InteropPointer.fromInterop(result: ByteArray)
fun toInterop(array: ShortArray?): InteropPointer fun toInterop(array: ShortArray?): InteropPointer
fun toInteropForResult(array: ShortArray?): InteropPointer
fun InteropPointer.fromInterop(result: ShortArray) fun InteropPointer.fromInterop(result: ShortArray)
fun toInterop(array: IntArray?): InteropPointer fun toInterop(array: IntArray?): InteropPointer
fun toInteropForResult(array: IntArray?): InteropPointer
fun InteropPointer.fromInterop(result: IntArray) fun InteropPointer.fromInterop(result: IntArray)
fun toInterop(array: LongArray?): InteropPointer fun toInterop(array: LongArray?): InteropPointer
fun InteropPointer.fromInterop(result: LongArray) fun InteropPointer.fromInterop(result: LongArray)
fun toInterop(array: FloatArray?): InteropPointer fun toInterop(array: FloatArray?): InteropPointer
fun toInteropForResult(array: FloatArray?): InteropPointer
fun InteropPointer.fromInterop(result: FloatArray) fun InteropPointer.fromInterop(result: FloatArray)
fun toInterop(array: DoubleArray?): InteropPointer fun toInterop(array: DoubleArray?): InteropPointer
fun toInteropForResult(array: DoubleArray?): InteropPointer
fun InteropPointer.fromInterop(result: DoubleArray) fun InteropPointer.fromInterop(result: DoubleArray)
fun toInterop(array: NativePointerArray?): InteropPointer fun toInterop(array: NativePointerArray?): InteropPointer
fun toInteropForResult(array: NativePointerArray?): InteropPointer
fun InteropPointer.fromInterop(result: NativePointerArray) fun InteropPointer.fromInterop(result: NativePointerArray)
fun toInterop(stringArray: Array<String>?): InteropPointer fun toInterop(stringArray: Array<String>?): InteropPointer
fun InteropPointer.fromInteropNativePointerArray(): NativePointerArray fun InteropPointer.fromInteropNativePointerArray(): NativePointerArray
inline fun <reified T> InteropPointer.fromInterop(decoder: ArrayInteropDecoder<T>): Array<T> inline fun <reified T> InteropPointer.fromInterop(decoder: ArrayInteropDecoder<T>): Array<T>
fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer fun toInteropForArraysOfPointers(interopPointers: Array<InteropPointer>): InteropPointer
...@@ -62,14 +77,14 @@ expect class InteropScope() { ...@@ -62,14 +77,14 @@ expect class InteropScope() {
expect inline fun <T> interopScope(block: InteropScope.() -> T): T expect inline fun <T> interopScope(block: InteropScope.() -> T): T
inline fun withResult(result: ByteArray, block: InteropScope.(InteropPointer) -> Unit): ByteArray = interopScope { inline fun withResult(result: ByteArray, block: InteropScope.(InteropPointer) -> Unit): ByteArray = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
block(handle) block(handle)
handle.fromInterop(result) handle.fromInterop(result)
result result
} }
inline fun withNullableResult(result: ByteArray, block: InteropScope.(InteropPointer) -> Boolean): ByteArray? = interopScope { inline fun withNullableResult(result: ByteArray, block: InteropScope.(InteropPointer) -> Boolean): ByteArray? = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
return if (block(handle)) { return if (block(handle)) {
handle.fromInterop(result) handle.fromInterop(result)
result result
...@@ -79,14 +94,14 @@ inline fun withNullableResult(result: ByteArray, block: InteropScope.(InteropPoi ...@@ -79,14 +94,14 @@ inline fun withNullableResult(result: ByteArray, block: InteropScope.(InteropPoi
} }
inline fun withResult(result: FloatArray, block: InteropScope.(InteropPointer) -> Unit): FloatArray = interopScope { inline fun withResult(result: FloatArray, block: InteropScope.(InteropPointer) -> Unit): FloatArray = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
block(handle) block(handle)
handle.fromInterop(result) handle.fromInterop(result)
result result
} }
inline fun withNullableResult(result: FloatArray, block: InteropScope.(InteropPointer) -> Boolean): FloatArray? = interopScope { inline fun withNullableResult(result: FloatArray, block: InteropScope.(InteropPointer) -> Boolean): FloatArray? = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
val blockResult = block(handle) val blockResult = block(handle)
if (blockResult) { if (blockResult) {
handle.fromInterop(result) handle.fromInterop(result)
...@@ -97,14 +112,14 @@ inline fun withNullableResult(result: FloatArray, block: InteropScope.(InteropPo ...@@ -97,14 +112,14 @@ inline fun withNullableResult(result: FloatArray, block: InteropScope.(InteropPo
} }
inline fun withResult(result: IntArray, block: InteropScope.(InteropPointer) -> Unit): IntArray = interopScope { inline fun withResult(result: IntArray, block: InteropScope.(InteropPointer) -> Unit): IntArray = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
block(handle) block(handle)
handle.fromInterop(result) handle.fromInterop(result)
result result
} }
inline fun withNullableResult(result: IntArray, block: InteropScope.(InteropPointer) -> Boolean): IntArray? = interopScope { inline fun withNullableResult(result: IntArray, block: InteropScope.(InteropPointer) -> Boolean): IntArray? = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
return if (block(handle)) { return if (block(handle)) {
handle.fromInterop(result) handle.fromInterop(result)
result result
...@@ -114,21 +129,21 @@ inline fun withNullableResult(result: IntArray, block: InteropScope.(InteropPoin ...@@ -114,21 +129,21 @@ inline fun withNullableResult(result: IntArray, block: InteropScope.(InteropPoin
} }
inline fun withResult(result: ShortArray, block: InteropScope.(InteropPointer) -> Unit): ShortArray = interopScope { inline fun withResult(result: ShortArray, block: InteropScope.(InteropPointer) -> Unit): ShortArray = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
block(handle) block(handle)
handle.fromInterop(result) handle.fromInterop(result)
result result
} }
inline fun withResult(result: DoubleArray, block: InteropScope.(InteropPointer) -> Unit): DoubleArray = interopScope { inline fun withResult(result: DoubleArray, block: InteropScope.(InteropPointer) -> Unit): DoubleArray = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
block(handle) block(handle)
handle.fromInterop(result) handle.fromInterop(result)
result result
} }
inline fun withResult(result: NativePointerArray, block: InteropScope.(InteropPointer) -> Unit): NativePointerArray = interopScope { inline fun withResult(result: NativePointerArray, block: InteropScope.(InteropPointer) -> Unit): NativePointerArray = interopScope {
val handle = toInterop(result) val handle = toInteropForResult(result)
block(handle) block(handle)
handle.fromInterop(result) handle.fromInterop(result)
result result
......
...@@ -64,46 +64,65 @@ actual class InteropScope actual constructor() { ...@@ -64,46 +64,65 @@ actual class InteropScope actual constructor() {
} }
} }
actual fun toInterop(array: ByteArray?): InteropPointer { private fun toInterop(array: ByteArray?, copyArrayToWasm: Boolean): InteropPointer {
return if (array != null && array.isNotEmpty()) { return if (array != null && array.isNotEmpty()) {
val data = _malloc(array.size) val data = _malloc(array.size)
elements.add(data) elements.add(data)
toWasm(data, array) if (copyArrayToWasm) toWasm(data, array)
data data
} else { } else {
0 0
} }
} }
actual fun toInterop(array: ByteArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = true)
actual fun toInteropForResult(array: ByteArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = false)
actual fun InteropPointer.fromInterop(result: ShortArray) { actual fun InteropPointer.fromInterop(result: ShortArray) {
fromWasm(this@fromInterop, result) fromWasm(this@fromInterop, result)
} }
actual fun toInterop(array: ShortArray?): InteropPointer { private fun toInterop(array: ShortArray?, copyArrayToWasm: Boolean): InteropPointer {
return if (array != null && array.isNotEmpty()) { return if (array != null && array.isNotEmpty()) {
val data = _malloc(array.size * 2) val data = _malloc(array.size * 2)
elements.add(data) elements.add(data)
toWasm(data, array) if (copyArrayToWasm) toWasm(data, array)
data data
} else { } else {
0 0
} }
} }
actual fun toInterop(array: ShortArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = true)
actual fun toInteropForResult(array: ShortArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = false)
actual fun InteropPointer.fromInterop(result: IntArray) { actual fun InteropPointer.fromInterop(result: IntArray) {
fromWasm(this@fromInterop, result) fromWasm(this@fromInterop, result)
} }
actual fun toInterop(array: IntArray?): InteropPointer { private fun toInterop(array: IntArray?, copyArrayToWasm: Boolean): InteropPointer {
return if (array != null && array.isNotEmpty()) { return if (array != null && array.isNotEmpty()) {
val data = _malloc(array.size * 4) val data = _malloc(array.size * 4)
elements.add(data) elements.add(data)
toWasm(data, array) if (copyArrayToWasm) toWasm(data, array)
data data
} else { } else {
0 0
} }
} }
actual fun toInterop(array: IntArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = true)
actual fun toInteropForResult(array: IntArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = false)
actual fun InteropPointer.fromInterop(result: LongArray) { actual fun InteropPointer.fromInterop(result: LongArray) {
TODO("implement wasm fromInterop(LongArray)") TODO("implement wasm fromInterop(LongArray)")
} }
...@@ -116,47 +135,65 @@ actual class InteropScope actual constructor() { ...@@ -116,47 +135,65 @@ actual class InteropScope actual constructor() {
fromWasm(this@fromInterop, result) fromWasm(this@fromInterop, result)
} }
actual fun toInterop(array: FloatArray?): InteropPointer { private fun toInterop(array: FloatArray?, copyArrayToWasm: Boolean): InteropPointer {
return if (array != null && array.isNotEmpty()) { return if (array != null && array.isNotEmpty()) {
val data = _malloc(array.size * 4) val data = _malloc(array.size * 4)
elements.add(data) elements.add(data)
toWasm(data, array) if (copyArrayToWasm) toWasm(data, array)
data data
} else { } else {
0 0
} }
} }
actual fun toInterop(array: FloatArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = true)
actual fun toInteropForResult(array: FloatArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = false)
actual fun InteropPointer.fromInterop(result: DoubleArray) { actual fun InteropPointer.fromInterop(result: DoubleArray) {
fromWasm(this@fromInterop, result) fromWasm(this@fromInterop, result)
} }
actual fun toInterop(array: DoubleArray?): InteropPointer { private fun toInterop(array: DoubleArray?, copyArrayToWasm: Boolean): InteropPointer {
return if (array != null && array.isNotEmpty()) { return if (array != null && array.isNotEmpty()) {
val data = _malloc(array.size * 8) val data = _malloc(array.size * 8)
elements.add(data) elements.add(data)
toWasm(data, array) if (copyArrayToWasm) toWasm(data, array)
data data
} else { } else {
0 0
} }
} }
actual fun toInterop(array: DoubleArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = true)
actual fun toInteropForResult(array: DoubleArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = false)
actual fun InteropPointer.fromInterop(result: ByteArray) { actual fun InteropPointer.fromInterop(result: ByteArray) {
fromWasm(this@fromInterop, result) fromWasm(this@fromInterop, result)
} }
actual fun toInterop(array: NativePointerArray?): InteropPointer { private fun toInterop(array: NativePointerArray?, copyArrayToWasm: Boolean): InteropPointer {
return if (array != null && array.size > 0) { return if (array != null && array.size > 0) {
val data = _malloc(array.size * 4) val data = _malloc(array.size * 4)
elements.add(data) elements.add(data)
toWasm(data, array.backing) if (copyArrayToWasm) toWasm(data, array.backing)
data data
} else { } else {
0 0
} }
} }
actual fun toInterop(array: NativePointerArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = true)
actual fun toInteropForResult(array: NativePointerArray?): InteropPointer =
toInterop(array = array, copyArrayToWasm = false)
actual fun InteropPointer.fromInterop(result: NativePointerArray) { actual fun InteropPointer.fromInterop(result: NativePointerArray) {
return fromWasm(this@fromInterop, result.backing) return fromWasm(this@fromInterop, result.backing)
} }
......
...@@ -57,20 +57,34 @@ actual inline fun <T> interopScope(block: InteropScope.() -> T): T { ...@@ -57,20 +57,34 @@ actual inline fun <T> interopScope(block: InteropScope.() -> T): T {
actual open class InteropScope actual constructor() { actual open class InteropScope actual constructor() {
actual fun toInterop(string: String?): InteropPointer = string actual fun toInterop(string: String?): InteropPointer = string
actual fun toInterop(array: ByteArray?): InteropPointer = array actual fun toInterop(array: ByteArray?): InteropPointer = array
actual fun toInteropForResult(array: ByteArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: ByteArray) {} actual fun InteropPointer.fromInterop(result: ByteArray) {}
actual fun toInterop(array: ShortArray?): InteropPointer = array actual fun toInterop(array: ShortArray?): InteropPointer = array
actual fun toInteropForResult(array: ShortArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: ShortArray) {} actual fun InteropPointer.fromInterop(result: ShortArray) {}
actual fun toInterop(array: IntArray?): InteropPointer = array actual fun toInterop(array: IntArray?): InteropPointer = array
actual fun toInteropForResult(array: IntArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: IntArray) {} actual fun InteropPointer.fromInterop(result: IntArray) {}
actual fun toInterop(array: LongArray?): InteropPointer = array actual fun toInterop(array: LongArray?): InteropPointer = array
actual fun InteropPointer.fromInterop(result: LongArray) {} actual fun InteropPointer.fromInterop(result: LongArray) {}
actual fun toInterop(array: FloatArray?): InteropPointer = array actual fun toInterop(array: FloatArray?): InteropPointer = array
actual fun toInteropForResult(array: FloatArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: FloatArray) {} actual fun InteropPointer.fromInterop(result: FloatArray) {}
actual fun toInterop(array: DoubleArray?): InteropPointer = array actual fun toInterop(array: DoubleArray?): InteropPointer = array
actual fun toInteropForResult(array: DoubleArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: DoubleArray) {} actual fun InteropPointer.fromInterop(result: DoubleArray) {}
actual fun toInterop(array: NativePointerArray?): InteropPointer = array?.backing actual fun toInterop(array: NativePointerArray?): InteropPointer = array?.backing
actual fun toInteropForResult(array: NativePointerArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: NativePointerArray) {} actual fun InteropPointer.fromInterop(result: NativePointerArray) {}
actual fun toInterop(stringArray: Array<String>?): InteropPointer = stringArray actual fun toInterop(stringArray: Array<String>?): InteropPointer = stringArray
actual fun InteropPointer.fromInteropNativePointerArray(): NativePointerArray = actual fun InteropPointer.fromInteropNativePointerArray(): NativePointerArray =
NativePointerArray((this as LongArray).size, this) NativePointerArray((this as LongArray).size, this)
......
...@@ -89,6 +89,8 @@ actual class InteropScope actual constructor() { ...@@ -89,6 +89,8 @@ actual class InteropScope actual constructor() {
} }
} }
actual fun toInteropForResult(array: ByteArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: ByteArray) {} actual fun InteropPointer.fromInterop(result: ByteArray) {}
actual fun toInterop(array: ShortArray?): InteropPointer { actual fun toInterop(array: ShortArray?): InteropPointer {
...@@ -102,6 +104,8 @@ actual class InteropScope actual constructor() { ...@@ -102,6 +104,8 @@ actual class InteropScope actual constructor() {
} }
} }
actual fun toInteropForResult(array: ShortArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: ShortArray) {} actual fun InteropPointer.fromInterop(result: ShortArray) {}
actual fun toInterop(array: IntArray?): InteropPointer { actual fun toInterop(array: IntArray?): InteropPointer {
...@@ -115,6 +119,8 @@ actual class InteropScope actual constructor() { ...@@ -115,6 +119,8 @@ actual class InteropScope actual constructor() {
} }
} }
actual fun toInteropForResult(array: IntArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: IntArray) {} actual fun InteropPointer.fromInterop(result: IntArray) {}
actual fun toInterop(array: LongArray?): InteropPointer { actual fun toInterop(array: LongArray?): InteropPointer {
...@@ -141,6 +147,8 @@ actual class InteropScope actual constructor() { ...@@ -141,6 +147,8 @@ actual class InteropScope actual constructor() {
} }
} }
actual fun toInteropForResult(array: FloatArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: FloatArray) {} actual fun InteropPointer.fromInterop(result: FloatArray) {}
actual fun toInterop(array: DoubleArray?): InteropPointer { actual fun toInterop(array: DoubleArray?): InteropPointer {
...@@ -154,6 +162,8 @@ actual class InteropScope actual constructor() { ...@@ -154,6 +162,8 @@ actual class InteropScope actual constructor() {
} }
} }
actual fun toInteropForResult(array: DoubleArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: DoubleArray) {} actual fun InteropPointer.fromInterop(result: DoubleArray) {}
actual fun toInterop(array: NativePointerArray?): InteropPointer { actual fun toInterop(array: NativePointerArray?): InteropPointer {
...@@ -168,6 +178,8 @@ actual class InteropScope actual constructor() { ...@@ -168,6 +178,8 @@ actual class InteropScope actual constructor() {
} }
} }
actual fun toInteropForResult(array: NativePointerArray?): InteropPointer = toInterop(array)
actual fun InteropPointer.fromInterop(result: NativePointerArray) {} actual fun InteropPointer.fromInterop(result: NativePointerArray) {}
actual fun toInterop(stringArray: Array<String>?): InteropPointer { actual fun toInterop(stringArray: Array<String>?): InteropPointer {
...@@ -271,4 +283,4 @@ private external fun initCallbacks( ...@@ -271,4 +283,4 @@ private external fun initCallbacks(
callNativePointer: COpaquePointer, callNativePointer: COpaquePointer,
callVoid: COpaquePointer, callVoid: COpaquePointer,
dispose: COpaquePointer dispose: COpaquePointer
) )
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment