From a3721f857c2432925c9d777c47ce1bc19e4b5f85 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Tue, 19 Sep 2017 12:23:25 +0300 Subject: [PATCH] Optimize `Arena` and `memScoped` Also do minor refactoring. --- .../kotlin/kotlinx/cinterop/JvmNativeMem.kt | 4 +-- .../src/main/kotlin/kotlinx/cinterop/Types.kt | 5 ++++ .../src/main/kotlin/kotlinx/cinterop/Utils.kt | 27 +++++++++---------- .../kotlin/kotlinx/cinterop/NativeMem.kt | 4 +-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmNativeMem.kt b/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmNativeMem.kt index 99280aa5098..3b34cfa4073 100644 --- a/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmNativeMem.kt +++ b/Interop/Runtime/src/jvm/kotlin/kotlinx/cinterop/JvmNativeMem.kt @@ -98,15 +98,13 @@ internal object nativeMemUtils { return unsafe.allocateInstance(T::class.java) as T } - internal class NativeAllocated(rawPtr: NativePtr) : NativePointed(rawPtr) - fun alloc(size: Long, align: Int): NativePointed { val address = unsafe.allocateMemory( if (size == 0L) 1L else size // It is a hack: `sun.misc.Unsafe` can't allocate zero bytes ) if (address % align != 0L) TODO(align.toString()) - return interpretPointed(address) + return interpretOpaquePointed(address) } fun free(mem: NativePtr) { diff --git a/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt b/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt index 88719d7c672..9ac50e2bd04 100644 --- a/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt +++ b/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Types.kt @@ -40,6 +40,11 @@ val NativePointed?.rawPtr: NativePtr */ inline fun interpretPointed(ptr: NativePtr): T = interpretNullablePointed(ptr)!! +private class OpaqueNativePointed(rawPtr: NativePtr) : NativePointed(rawPtr) + +fun interpretOpaquePointed(ptr: NativePtr): NativePointed = interpretPointed(ptr) +fun interpretNullableOpaquePointed(ptr: NativePtr): NativePointed? = interpretNullablePointed(ptr) + /** * Changes the interpretation of the pointed data or code. */ diff --git a/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt b/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt index 1de7f3d3bd7..c4d3ddd1985 100644 --- a/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt +++ b/Interop/Runtime/src/main/kotlin/kotlinx/cinterop/Utils.kt @@ -65,31 +65,30 @@ open class DeferScope { } } -// TODO: implement optimally open class ArenaBase(private val parent: NativeFreeablePlacement = nativeHeap) : NativePlacement, DeferScope() { - private val allocatedChunks = ArrayList() + private var lastChunk: NativePointed? = null final override fun alloc(size: Long, align: Int): NativePointed { - val res = parent.alloc(size, align) - try { - allocatedChunks.add(res) - return res - } catch (e: Throwable) { - parent.free(res) - throw e - } + // Reserve space for a pointer: + val gapForPointer = maxOf(pointerSize, align) + + val chunk = parent.alloc(size = gapForPointer + size, align = gapForPointer) + nativeMemUtils.putNativePtr(chunk, lastChunk.rawPtr) + lastChunk = chunk + return interpretOpaquePointed(chunk.rawPtr + gapForPointer.toLong()) } @PublishedApi internal fun clearImpl() { this.executeAllDeferred() - allocatedChunks.forEach { - parent.free(it) + var chunk = lastChunk + while (chunk != null) { + val nextChunk = nativeMemUtils.getNativePtr(chunk) + parent.free(chunk) + chunk = interpretNullableOpaquePointed(nextChunk) } - - allocatedChunks.clear() } } diff --git a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt index 409520218d4..22bde023517 100644 --- a/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt +++ b/Interop/Runtime/src/native/kotlin/kotlinx/cinterop/NativeMem.kt @@ -83,14 +83,12 @@ internal object nativeMemUtils { } } - private class NativeAllocated(rawPtr: NativePtr) : NativePointed(rawPtr) - fun alloc(size: Long, align: Int): NativePointed { val ptr = malloc(size, align) if (ptr == nativeNullPtr) { throw OutOfMemoryError("unable to allocate native memory") } - return interpretPointed(ptr) + return interpretOpaquePointed(ptr) } fun free(mem: NativePtr) {