From a4a9b887907db1eb883346cc71f914c2b746f708 Mon Sep 17 00:00:00 2001 From: CharlieTap Date: Thu, 30 Jan 2025 19:27:49 +0000 Subject: [PATCH] prevent boxing in throw ref --- .../instruction/control/ThrowRefExecutor.kt | 19 ++++++++++--------- .../executor/runtime/error/InvocationError.kt | 2 ++ .../chasm/executor/runtime/ext/LongExt.kt | 9 +++++++++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/executor/invoker/src/commonMain/kotlin/io/github/charlietap/chasm/executor/invoker/instruction/control/ThrowRefExecutor.kt b/executor/invoker/src/commonMain/kotlin/io/github/charlietap/chasm/executor/invoker/instruction/control/ThrowRefExecutor.kt index f3669901..e5177c6e 100644 --- a/executor/invoker/src/commonMain/kotlin/io/github/charlietap/chasm/executor/invoker/instruction/control/ThrowRefExecutor.kt +++ b/executor/invoker/src/commonMain/kotlin/io/github/charlietap/chasm/executor/invoker/instruction/control/ThrowRefExecutor.kt @@ -11,7 +11,8 @@ import io.github.charlietap.chasm.executor.runtime.exception.ExceptionHandler import io.github.charlietap.chasm.executor.runtime.exception.InvocationException import io.github.charlietap.chasm.executor.runtime.execution.ExecutionContext import io.github.charlietap.chasm.executor.runtime.ext.exception -import io.github.charlietap.chasm.executor.runtime.ext.popReference +import io.github.charlietap.chasm.executor.runtime.ext.isNullableReference +import io.github.charlietap.chasm.executor.runtime.ext.toExceptionAddress import io.github.charlietap.chasm.executor.runtime.ext.toLong import io.github.charlietap.chasm.executor.runtime.instruction.ControlInstruction import io.github.charlietap.chasm.executor.runtime.stack.ControlStack @@ -37,21 +38,21 @@ internal inline fun ThrowRefExecutor( val cstack = context.cstack val store = context.store - val ref = stack.popReference() + val ref = stack.pop() - val exceptionRef = if (ref is ReferenceValue.Null) { + val exceptionAddress = if (ref.isNullableReference()) { throw InvocationException(InvocationError.UnexpectedReferenceValue) } else { - ref as ReferenceValue.Exception + ref.toExceptionAddress() } - val instance = store.exception(exceptionRef.address) + val instance = store.exception(exceptionAddress) val address = instance.tagAddress val handler = jumpToHandlerInstruction(cstack) if (handler.instructions.isEmpty()) { - stack.push(ReferenceValue.Exception(exceptionRef.address).toLong()) + stack.push(ReferenceValue.Exception(exceptionAddress).toLong()) cstack.push(ThrowRefDispatcher(ControlInstruction.ThrowRef)) } else { @@ -83,7 +84,7 @@ internal inline fun ThrowRefExecutor( catchHandler is CatchHandler.CatchRef && tagMatches -> { instance.fields.reverse() stack.push(instance.fields) - stack.push(exceptionRef.toLong()) + stack.push(ref) cstack.push( breakDispatcher(ControlInstruction.Br(catchHandler.labelIndex)), ) @@ -94,7 +95,7 @@ internal inline fun ThrowRefExecutor( ) } catchHandler is CatchHandler.CatchAllRef -> { - stack.push(exceptionRef.toLong()) + stack.push(ref) cstack.push( breakDispatcher(ControlInstruction.Br(catchHandler.labelIndex)), ) @@ -105,7 +106,7 @@ internal inline fun ThrowRefExecutor( cstack.push(handler) val instruction = handlerDispatcher(handler) cstack.push(instruction) - stack.push(exceptionRef.toLong()) + stack.push(ref) cstack.push(ThrowRefDispatcher(ControlInstruction.ThrowRef)) } } diff --git a/executor/runtime-internal/src/commonMain/kotlin/io/github/charlietap/chasm/executor/runtime/error/InvocationError.kt b/executor/runtime-internal/src/commonMain/kotlin/io/github/charlietap/chasm/executor/runtime/error/InvocationError.kt index a4a554d1..a1fdd634 100644 --- a/executor/runtime-internal/src/commonMain/kotlin/io/github/charlietap/chasm/executor/runtime/error/InvocationError.kt +++ b/executor/runtime-internal/src/commonMain/kotlin/io/github/charlietap/chasm/executor/runtime/error/InvocationError.kt @@ -128,6 +128,8 @@ sealed interface InvocationError : ModuleTrapError { data object ReferenceValueExpected : InvocationError + data object ExceptionReferenceExpected : InvocationError + data object FunctionReferenceExpected : InvocationError data object StructReferenceExpected : InvocationError diff --git a/executor/runtime-internal/src/commonMain/kotlin/io/github/charlietap/chasm/executor/runtime/ext/LongExt.kt b/executor/runtime-internal/src/commonMain/kotlin/io/github/charlietap/chasm/executor/runtime/ext/LongExt.kt index c74681df..7cdaee71 100644 --- a/executor/runtime-internal/src/commonMain/kotlin/io/github/charlietap/chasm/executor/runtime/ext/LongExt.kt +++ b/executor/runtime-internal/src/commonMain/kotlin/io/github/charlietap/chasm/executor/runtime/ext/LongExt.kt @@ -43,6 +43,15 @@ inline fun Long.toArrayAddress(): Address.Array { return Address.Array(address) } +inline fun Long.toExceptionAddress(): Address.Exception { + val typeId = this and RV_TYPE_MASK + if (typeId != RV_TYPE_EXCEPTION) { + throw InvocationException(InvocationError.ExceptionReferenceExpected) + } + val address = (this shr RV_SHIFT_BITS).toInt() + return Address.Exception(address) +} + inline fun Long.toFunctionAddress(): Address.Function { val typeId = this and RV_TYPE_MASK if (typeId != RV_TYPE_FUNCTION) {