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>) { override fun invoke(gen: AsmGenerationContext<T>) {
gen.visitLoadAlgebra() gen.visitLoadAlgebra()
if (!hasSpecific(context, name, 1)) if (!hasSpecific(context, name, 2))
gen.visitStringConstant(name) gen.visitStringConstant(name)
first.invoke(gen) first.invoke(gen)
second.invoke(gen) second.invoke(gen)
if (gen.tryInvokeSpecific(context, name, 1)) if (gen.tryInvokeSpecific(context, name, 2))
return return
gen.visitAlgebraOperation( gen.visitAlgebraOperation(

View File

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

View File

@ -1,15 +1,14 @@
package scientifik.kmath.asm package scientifik.kmath.asm
import org.objectweb.asm.Opcodes
import scientifik.kmath.operations.Algebra 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") 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 { internal fun <T> hasSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
val aName = methodNameAdapters[name] ?: name 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 false
return true 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 { internal fun <T> AsmGenerationContext<T>.tryInvokeSpecific(context: Algebra<T>, name: String, arity: Int): Boolean {
val aName = methodNameAdapters[name] ?: name 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 false
val owner = context::class.jvmName.replace('.', '/') val owner = context::class.java.name.replace('.', '/')
val sig = buildString { val sig = buildString {
append('(') append('(')
@ -30,7 +29,13 @@ internal fun <T> AsmGenerationContext<T>.tryInvokeSpecific(context: Algebra<T>,
append("L${AsmGenerationContext.OBJECT_CLASS};") 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 return true
} }