Fix specification bug

This commit is contained in:
Iaroslav 2020-06-13 16:48:45 +07:00
parent e65d1e43cf
commit f9835979ea
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
3 changed files with 26 additions and 12 deletions

View File

@ -57,13 +57,13 @@ internal class AsmBinaryOperation<T>(
override fun invoke(gen: AsmGenerationContext<T>) {
gen.visitLoadAlgebra()
if (!hasSpecific(context, name, 1))
if (!hasSpecific(context, name, 2))
gen.visitStringConstant(name)
first.invoke(gen)
second.invoke(gen)
if (gen.tryInvokeSpecific(context, name, 1))
if (gen.tryInvokeSpecific(context, name, 2))
return
gen.visitAlgebraOperation(

View File

@ -4,6 +4,7 @@ import org.objectweb.asm.ClassWriter
import org.objectweb.asm.Label
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes
import scientifik.kmath.asm.AsmGenerationContext.ClassLoader
import scientifik.kmath.operations.Algebra
/**
@ -245,8 +246,10 @@ class AsmGenerationContext<T>(
}
visitLdcInsn(name)
visitMethodInsn(Opcodes.INVOKEINTERFACE,
MAP_CLASS, "get", "(L$OBJECT_CLASS;)L$OBJECT_CLASS;", true)
visitMethodInsn(
Opcodes.INVOKEINTERFACE,
MAP_CLASS, "get", "(L$OBJECT_CLASS;)L$OBJECT_CLASS;", true
)
visitCastToT()
}
@ -262,9 +265,15 @@ class AsmGenerationContext<T>(
invokeMethodVisitor.visitTypeInsn(Opcodes.CHECKCAST, T_ALGEBRA_CLASS)
}
internal fun visitAlgebraOperation(owner: String, method: String, descriptor: String) {
internal fun visitAlgebraOperation(
owner: String,
method: String,
descriptor: String,
opcode: Int = Opcodes.INVOKEINTERFACE,
isInterface: Boolean = true
) {
maxStack++
invokeMethodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, method, descriptor, true)
invokeMethodVisitor.visitMethodInsn(opcode, owner, method, descriptor, isInterface)
visitCastToT()
}

View File

@ -1,15 +1,14 @@
package scientifik.kmath.asm
import org.objectweb.asm.Opcodes
import scientifik.kmath.operations.Algebra
import kotlin.reflect.full.memberFunctions
import kotlin.reflect.jvm.jvmName
private val methodNameAdapters: Map<String, String> = mapOf("+" to "add", "*" to "multiply", "/" to "divide")
internal fun <T> hasSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
val aName = methodNameAdapters[name] ?: name
context::class.memberFunctions.find { it.name == aName && it.parameters.size == arity }
context::class.java.methods.find { it.name == aName && it.parameters.size == arity }
?: return false
return true
@ -18,10 +17,10 @@ internal fun <T> hasSpecific(context: Algebra<T>, name: String, arity: Int): Boo
internal fun <T> AsmGenerationContext<T>.tryInvokeSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
val aName = methodNameAdapters[name] ?: name
context::class.memberFunctions.find { it.name == aName && it.parameters.size == arity }
context::class.java.methods.find { it.name == aName && it.parameters.size == arity }
?: return false
val owner = context::class.jvmName.replace('.', '/')
val owner = context::class.java.name.replace('.', '/')
val sig = buildString {
append('(')
@ -30,7 +29,13 @@ internal fun <T> AsmGenerationContext<T>.tryInvokeSpecific(context: Algebra<T>,
append("L${AsmGenerationContext.OBJECT_CLASS};")
}
visitAlgebraOperation(owner = owner, method = aName, descriptor = sig)
visitAlgebraOperation(
owner = owner,
method = aName,
descriptor = sig,
opcode = Opcodes.INVOKEVIRTUAL,
isInterface = false
)
return true
}