Merge branch 'adv-expr' into adv-expr-benchmarks-2

This commit is contained in:
Commander Tvis 2020-06-25 10:14:16 +07:00
commit da1cac5fa8
No known key found for this signature in database
GPG Key ID: 70D5F4DCB0972F1B
8 changed files with 140 additions and 147 deletions

View File

@ -24,20 +24,20 @@ For example, the following builder:
package scientifik.kmath.asm.generated; package scientifik.kmath.asm.generated;
import java.util.Map; import java.util.Map;
import scientifik.kmath.asm.internal.AsmCompiledExpression; import scientifik.kmath.expressions.Expression;
import scientifik.kmath.operations.Algebra;
import scientifik.kmath.operations.RealField; import scientifik.kmath.operations.RealField;
// The class's name is build with MST's hash-code and collision fixing number. public final class AsmCompiledExpression_1073786867_0 implements Expression<Double> {
public final class AsmCompiledExpression_45045_0 extends AsmCompiledExpression<Double> { private final RealField algebra;
// Plain constructor private final Object[] constants;
public AsmCompiledExpression_45045_0(Algebra algebra, Object[] constants) {
super(algebra, constants); public AsmCompiledExpression_1073786867_0(RealField algebra, Object[] constants) {
this.algebra = algebra;
this.constants = constants;
} }
// The actual dynamic code:
public final Double invoke(Map<String, ? extends Double> arguments) { public final Double invoke(Map<String, ? extends Double> arguments) {
return (Double)((RealField)super.algebra).add((Double)arguments.get("x"), (Double)2.0D); return (Double)this.algebra.add(((Double)arguments.get("x")).doubleValue(), 2.0D);
} }
} }
``` ```

View File

@ -6,6 +6,7 @@ import org.objectweb.asm.Opcodes.RETURN
import org.objectweb.asm.commons.InstructionAdapter import org.objectweb.asm.commons.InstructionAdapter
import scientifik.kmath.asm.internal.AsmBuilder.ClassLoader import scientifik.kmath.asm.internal.AsmBuilder.ClassLoader
import scientifik.kmath.ast.MST import scientifik.kmath.ast.MST
import scientifik.kmath.expressions.Expression
import scientifik.kmath.operations.Algebra import scientifik.kmath.operations.Algebra
import java.util.* import java.util.*
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -36,32 +37,27 @@ internal class AsmBuilder<T> internal constructor(
*/ */
private val classLoader: ClassLoader = ClassLoader(javaClass.classLoader) private val classLoader: ClassLoader = ClassLoader(javaClass.classLoader)
@Suppress("PrivatePropertyName") private val tAlgebraType: Type = algebra::class.asm
private val T_ALGEBRA_TYPE: Type = algebra::class.asm internal val tType: Type = classOfT.asm
private val classType: Type = Type.getObjectType(className.replace(oldChar = '.', newChar = '/'))!!
@Suppress("PrivatePropertyName")
internal val T_TYPE: Type = classOfT.asm
@Suppress("PrivatePropertyName")
private val CLASS_TYPE: Type = Type.getObjectType(className.replace(oldChar = '.', newChar = '/'))!!
/** /**
* Index of `this` variable in invoke method of [AsmCompiledExpression] built subclass. * Index of `this` variable in invoke method of the built subclass.
*/ */
private val invokeThisVar: Int = 0 private val invokeThisVar: Int = 0
/** /**
* Index of `arguments` variable in invoke method of [AsmCompiledExpression] built subclass. * Index of `arguments` variable in invoke method of the built subclass.
*/ */
private val invokeArgumentsVar: Int = 1 private val invokeArgumentsVar: Int = 1
/** /**
* List of constants to provide to [AsmCompiledExpression] subclass. * List of constants to provide to the subclass.
*/ */
private val constants: MutableList<Any> = mutableListOf() private val constants: MutableList<Any> = mutableListOf()
/** /**
* Method visitor of `invoke` method of [AsmCompiledExpression] subclass. * Method visitor of `invoke` method of the subclass.
*/ */
private lateinit var invokeMethodVisitor: InstructionAdapter private lateinit var invokeMethodVisitor: InstructionAdapter
internal var primitiveMode = false internal var primitiveMode = false
@ -72,78 +68,92 @@ internal class AsmBuilder<T> internal constructor(
@Suppress("PropertyName") @Suppress("PropertyName")
internal var PRIMITIVE_MASK_BOXED: Type = OBJECT_TYPE internal var PRIMITIVE_MASK_BOXED: Type = OBJECT_TYPE
private val typeStack = Stack<Type>() private val typeStack = Stack<Type>()
internal val expectationStack = Stack<Type>().apply { push(T_TYPE) } internal val expectationStack: Stack<Type> = Stack<Type>().apply { push(tType) }
/** /**
* The cache of [AsmCompiledExpression] subclass built by this builder. * The cache for instance built by this builder.
*/ */
private var generatedInstance: AsmCompiledExpression<T>? = null private var generatedInstance: Expression<T>? = null
/** /**
* Subclasses, loads and instantiates the [AsmCompiledExpression] for given parameters. * Subclasses, loads and instantiates [Expression] for given parameters.
* *
* The built instance is cached. * The built instance is cached.
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun getInstance(): AsmCompiledExpression<T> { fun getInstance(): Expression<T> {
generatedInstance?.let { return it } generatedInstance?.let { return it }
if (SIGNATURE_LETTERS.containsKey(classOfT.java)) { if (SIGNATURE_LETTERS.containsKey(classOfT)) {
primitiveMode = true primitiveMode = true
PRIMITIVE_MASK = SIGNATURE_LETTERS.getValue(classOfT.java) PRIMITIVE_MASK = SIGNATURE_LETTERS.getValue(classOfT)
PRIMITIVE_MASK_BOXED = T_TYPE PRIMITIVE_MASK_BOXED = tType
} }
val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) { val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) {
visit( visit(
Opcodes.V1_8, Opcodes.V1_8,
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER, Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER,
CLASS_TYPE.internalName, classType.internalName,
"L${ASM_COMPILED_EXPRESSION_TYPE.internalName}<${T_TYPE.descriptor}>;", "${OBJECT_TYPE.descriptor}L${EXPRESSION_TYPE.internalName}<${tType.descriptor}>;",
ASM_COMPILED_EXPRESSION_TYPE.internalName, OBJECT_TYPE.internalName,
arrayOf() arrayOf(EXPRESSION_TYPE.internalName)
)
visitField(
access = Opcodes.ACC_PRIVATE or Opcodes.ACC_FINAL,
name = "algebra",
descriptor = tAlgebraType.descriptor,
signature = null,
value = null,
block = FieldVisitor::visitEnd
)
visitField(
access = Opcodes.ACC_PRIVATE or Opcodes.ACC_FINAL,
name = "constants",
descriptor = OBJECT_ARRAY_TYPE.descriptor,
signature = null,
value = null,
block = FieldVisitor::visitEnd
) )
visitMethod( visitMethod(
Opcodes.ACC_PUBLIC, Opcodes.ACC_PUBLIC,
"<init>", "<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, ALGEBRA_TYPE, OBJECT_ARRAY_TYPE), Type.getMethodDescriptor(Type.VOID_TYPE, tAlgebraType, OBJECT_ARRAY_TYPE),
null, null,
null null
).instructionAdapter { ).instructionAdapter {
val thisVar = 0 val thisVar = 0
val algebraVar = 1 val algebraVar = 1
val constantsVar = 2 val constantsVar = 2
val l0 = Label() val l0 = label()
visitLabel(l0) load(thisVar, classType)
load(thisVar, CLASS_TYPE) invokespecial(OBJECT_TYPE.internalName, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE), false)
load(algebraVar, ALGEBRA_TYPE) label()
load(thisVar, classType)
load(algebraVar, tAlgebraType)
putfield(classType.internalName, "algebra", tAlgebraType.descriptor)
label()
load(thisVar, classType)
load(constantsVar, OBJECT_ARRAY_TYPE) load(constantsVar, OBJECT_ARRAY_TYPE)
putfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
invokespecial( label()
ASM_COMPILED_EXPRESSION_TYPE.internalName,
"<init>",
Type.getMethodDescriptor(Type.VOID_TYPE, ALGEBRA_TYPE, OBJECT_ARRAY_TYPE),
false
)
val l1 = Label()
visitLabel(l1)
visitInsn(RETURN) visitInsn(RETURN)
val l2 = Label() val l4 = label()
visitLabel(l2) visitLocalVariable("this", classType.descriptor, null, l0, l4, thisVar)
visitLocalVariable("this", CLASS_TYPE.descriptor, null, l0, l2, thisVar)
visitLocalVariable( visitLocalVariable(
"algebra", "algebra",
ALGEBRA_TYPE.descriptor, tAlgebraType.descriptor,
"L${ALGEBRA_TYPE.internalName}<${T_TYPE.descriptor}>;", null,
l0, l0,
l2, l4,
algebraVar algebraVar
) )
visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l2, constantsVar) visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, constantsVar)
visitMaxs(0, 3) visitMaxs(0, 3)
visitEnd() visitEnd()
} }
@ -151,22 +161,20 @@ internal class AsmBuilder<T> internal constructor(
visitMethod( visitMethod(
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL, Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL,
"invoke", "invoke",
Type.getMethodDescriptor(T_TYPE, MAP_TYPE), Type.getMethodDescriptor(tType, MAP_TYPE),
"(L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${T_TYPE.descriptor}>;)${T_TYPE.descriptor}", "(L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}",
null null
).instructionAdapter { ).instructionAdapter {
invokeMethodVisitor = this invokeMethodVisitor = this
visitCode() visitCode()
val l0 = Label() val l0 = label()
visitLabel(l0)
invokeLabel0Visitor() invokeLabel0Visitor()
areturn(T_TYPE) areturn(tType)
val l1 = Label() val l1 = label()
visitLabel(l1)
visitLocalVariable( visitLocalVariable(
"this", "this",
CLASS_TYPE.descriptor, classType.descriptor,
null, null,
l0, l0,
l1, l1,
@ -176,7 +184,7 @@ internal class AsmBuilder<T> internal constructor(
visitLocalVariable( visitLocalVariable(
"arguments", "arguments",
MAP_TYPE.descriptor, MAP_TYPE.descriptor,
"L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${T_TYPE.descriptor}>;", "L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;",
l0, l0,
l1, l1,
invokeArgumentsVar invokeArgumentsVar
@ -196,18 +204,16 @@ internal class AsmBuilder<T> internal constructor(
val thisVar = 0 val thisVar = 0
val argumentsVar = 1 val argumentsVar = 1
visitCode() visitCode()
val l0 = Label() val l0 = label()
visitLabel(l0)
load(thisVar, OBJECT_TYPE) load(thisVar, OBJECT_TYPE)
load(argumentsVar, MAP_TYPE) load(argumentsVar, MAP_TYPE)
invokevirtual(CLASS_TYPE.internalName, "invoke", Type.getMethodDescriptor(T_TYPE, MAP_TYPE), false) invokevirtual(classType.internalName, "invoke", Type.getMethodDescriptor(tType, MAP_TYPE), false)
areturn(T_TYPE) areturn(tType)
val l1 = Label() val l1 = label()
visitLabel(l1)
visitLocalVariable( visitLocalVariable(
"this", "this",
CLASS_TYPE.descriptor, classType.descriptor,
null, null,
l0, l0,
l1, l1,
@ -225,7 +231,7 @@ internal class AsmBuilder<T> internal constructor(
.defineClass(className, classWriter.toByteArray()) .defineClass(className, classWriter.toByteArray())
.constructors .constructors
.first() .first()
.newInstance(algebra, constants.toTypedArray()) as AsmCompiledExpression<T> .newInstance(algebra, constants.toTypedArray()) as Expression<T>
generatedInstance = new generatedInstance = new
return new return new
@ -235,21 +241,21 @@ internal class AsmBuilder<T> internal constructor(
* Loads a constant from * Loads a constant from
*/ */
internal fun loadTConstant(value: T) { internal fun loadTConstant(value: T) {
if (classOfT.java in INLINABLE_NUMBERS) { if (classOfT in INLINABLE_NUMBERS) {
val expectedType = expectationStack.pop()!! val expectedType = expectationStack.pop()!!
val mustBeBoxed = expectedType.sort == Type.OBJECT val mustBeBoxed = expectedType.sort == Type.OBJECT
loadNumberConstant(value as Number, mustBeBoxed) loadNumberConstant(value as Number, mustBeBoxed)
if (mustBeBoxed) typeStack.push(T_TYPE) else typeStack.push(PRIMITIVE_MASK) if (mustBeBoxed) typeStack.push(tType) else typeStack.push(PRIMITIVE_MASK)
return return
} }
loadConstant(value as Any, T_TYPE) loadConstant(value as Any, tType)
} }
private fun box(): Unit = invokeMethodVisitor.invokestatic( private fun box(): Unit = invokeMethodVisitor.invokestatic(
T_TYPE.internalName, tType.internalName,
"valueOf", "valueOf",
Type.getMethodDescriptor(T_TYPE, PRIMITIVE_MASK), Type.getMethodDescriptor(tType, PRIMITIVE_MASK),
false false
) )
@ -263,16 +269,16 @@ internal class AsmBuilder<T> internal constructor(
private fun loadConstant(value: Any, type: Type): Unit = invokeMethodVisitor.run { private fun loadConstant(value: Any, type: Type): Unit = invokeMethodVisitor.run {
val idx = if (value in constants) constants.indexOf(value) else constants.apply { add(value) }.lastIndex val idx = if (value in constants) constants.indexOf(value) else constants.apply { add(value) }.lastIndex
loadThis() loadThis()
getfield(CLASS_TYPE.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor) getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
iconst(idx) iconst(idx)
visitInsn(AALOAD) visitInsn(AALOAD)
checkcast(type) checkcast(type)
} }
private fun loadThis(): Unit = invokeMethodVisitor.load(invokeThisVar, CLASS_TYPE) private fun loadThis(): Unit = invokeMethodVisitor.load(invokeThisVar, classType)
/** /**
* Either loads a numeric constant [value] from [AsmCompiledExpression] constants field or boxes a primitive * Either loads a numeric constant [value] from the class's constants field or boxes a primitive
* constant from the constant pool (some numbers with special opcodes like [Opcodes.ICONST_0] aren't even loaded * constant from the constant pool (some numbers with special opcodes like [Opcodes.ICONST_0] aren't even loaded
* from it). * from it).
*/ */
@ -292,7 +298,7 @@ internal class AsmBuilder<T> internal constructor(
if (mustBeBoxed) { if (mustBeBoxed) {
box() box()
invokeMethodVisitor.checkcast(T_TYPE) invokeMethodVisitor.checkcast(tType)
} }
return return
@ -300,11 +306,11 @@ internal class AsmBuilder<T> internal constructor(
loadConstant(value, boxed) loadConstant(value, boxed)
if (!mustBeBoxed) unbox() if (!mustBeBoxed) unbox()
else invokeMethodVisitor.checkcast(T_TYPE) else invokeMethodVisitor.checkcast(tType)
} }
/** /**
* Loads a variable [name] from [AsmCompiledExpression.invoke] [Map] parameter. The [defaultValue] may be provided. * Loads a variable [name] arguments [Map] parameter of [Expression.invoke]. The [defaultValue] may be provided.
*/ */
internal fun loadVariable(name: String, defaultValue: T? = null): Unit = invokeMethodVisitor.run { internal fun loadVariable(name: String, defaultValue: T? = null): Unit = invokeMethodVisitor.run {
load(invokeArgumentsVar, OBJECT_ARRAY_TYPE) load(invokeArgumentsVar, OBJECT_ARRAY_TYPE)
@ -319,7 +325,7 @@ internal class AsmBuilder<T> internal constructor(
Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE, OBJECT_TYPE) Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE, OBJECT_TYPE)
) )
invokeMethodVisitor.checkcast(T_TYPE) invokeMethodVisitor.checkcast(tType)
return return
} }
@ -331,11 +337,11 @@ internal class AsmBuilder<T> internal constructor(
Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE) Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE)
) )
invokeMethodVisitor.checkcast(T_TYPE) invokeMethodVisitor.checkcast(tType)
val expectedType = expectationStack.pop()!! val expectedType = expectationStack.pop()!!
if (expectedType.sort == Type.OBJECT) if (expectedType.sort == Type.OBJECT)
typeStack.push(T_TYPE) typeStack.push(tType)
else { else {
unbox() unbox()
typeStack.push(PRIMITIVE_MASK) typeStack.push(PRIMITIVE_MASK)
@ -343,15 +349,11 @@ internal class AsmBuilder<T> internal constructor(
} }
/** /**
* Loads algebra from according field of [AsmCompiledExpression] and casts it to class of [algebra] provided. * Loads algebra from according field of the class and casts it to class of [algebra] provided.
*/ */
internal fun loadAlgebra() { internal fun loadAlgebra() {
loadThis() loadThis()
invokeMethodVisitor.getfield(classType.internalName, "algebra", tAlgebraType.descriptor)
invokeMethodVisitor.run {
getfield(ASM_COMPILED_EXPRESSION_TYPE.internalName, "algebra", ALGEBRA_TYPE.descriptor)
checkcast(T_ALGEBRA_TYPE)
}
} }
/** /**
@ -368,7 +370,12 @@ internal class AsmBuilder<T> internal constructor(
tArity: Int, tArity: Int,
opcode: Int = Opcodes.INVOKEINTERFACE opcode: Int = Opcodes.INVOKEINTERFACE
) { ) {
repeat(tArity) { if (!typeStack.empty()) typeStack.pop() } run loop@{
repeat(tArity) {
if (typeStack.empty()) return@loop
typeStack.pop()
}
}
invokeMethodVisitor.visitMethodInsn( invokeMethodVisitor.visitMethodInsn(
opcode, opcode,
@ -378,12 +385,12 @@ internal class AsmBuilder<T> internal constructor(
opcode == Opcodes.INVOKEINTERFACE opcode == Opcodes.INVOKEINTERFACE
) )
invokeMethodVisitor.checkcast(T_TYPE) invokeMethodVisitor.checkcast(tType)
val isLastExpr = expectationStack.size == 1 val isLastExpr = expectationStack.size == 1
val expectedType = expectationStack.pop()!! val expectedType = expectationStack.pop()!!
if (expectedType.sort == Type.OBJECT || isLastExpr) if (expectedType.sort == Type.OBJECT || isLastExpr)
typeStack.push(T_TYPE) typeStack.push(tType)
else { else {
unbox() unbox()
typeStack.push(PRIMITIVE_MASK) typeStack.push(PRIMITIVE_MASK)
@ -399,27 +406,18 @@ internal class AsmBuilder<T> internal constructor(
/** /**
* Maps JVM primitive numbers boxed types to their letters of JVM signature convention. * Maps JVM primitive numbers boxed types to their letters of JVM signature convention.
*/ */
private val SIGNATURE_LETTERS: Map<Class<out Any>, Type> by lazy { private val SIGNATURE_LETTERS: Map<KClass<out Any>, Type> by lazy {
hashMapOf( hashMapOf(
java.lang.Byte::class.java to Type.BYTE_TYPE, java.lang.Byte::class to Type.BYTE_TYPE,
java.lang.Short::class.java to Type.SHORT_TYPE, java.lang.Short::class to Type.SHORT_TYPE,
java.lang.Integer::class.java to Type.INT_TYPE, java.lang.Integer::class to Type.INT_TYPE,
java.lang.Long::class.java to Type.LONG_TYPE, java.lang.Long::class to Type.LONG_TYPE,
java.lang.Float::class.java to Type.FLOAT_TYPE, java.lang.Float::class to Type.FLOAT_TYPE,
java.lang.Double::class.java to Type.DOUBLE_TYPE java.lang.Double::class to Type.DOUBLE_TYPE
) )
} }
private val BOXED_TO_PRIMITIVES: Map<Type, Type> by lazy { private val BOXED_TO_PRIMITIVES: Map<Type, Type> by lazy { SIGNATURE_LETTERS.mapKeys { (k, _) -> k.asm } }
hashMapOf(
java.lang.Byte::class.asm to Type.BYTE_TYPE,
java.lang.Short::class.asm to Type.SHORT_TYPE,
java.lang.Integer::class.asm to Type.INT_TYPE,
java.lang.Long::class.asm to Type.LONG_TYPE,
java.lang.Float::class.asm to Type.FLOAT_TYPE,
java.lang.Double::class.asm to Type.DOUBLE_TYPE
)
}
private val NUMBER_CONVERTER_METHODS: Map<Type, String> by lazy { private val NUMBER_CONVERTER_METHODS: Map<Type, String> by lazy {
hashMapOf( hashMapOf(
@ -435,15 +433,15 @@ internal class AsmBuilder<T> internal constructor(
/** /**
* Provides boxed number types values of which can be stored in JVM bytecode constant pool. * Provides boxed number types values of which can be stored in JVM bytecode constant pool.
*/ */
private val INLINABLE_NUMBERS: Set<Class<out Any>> by lazy { SIGNATURE_LETTERS.keys } private val INLINABLE_NUMBERS: Set<KClass<out Any>> by lazy { SIGNATURE_LETTERS.keys }
internal val ASM_COMPILED_EXPRESSION_TYPE: Type = AsmCompiledExpression::class.asm internal val EXPRESSION_TYPE: Type by lazy { Expression::class.asm }
internal val NUMBER_TYPE: Type = java.lang.Number::class.asm internal val NUMBER_TYPE: Type by lazy { java.lang.Number::class.asm }
internal val MAP_TYPE: Type = java.util.Map::class.asm internal val MAP_TYPE: Type by lazy { java.util.Map::class.asm }
internal val OBJECT_TYPE: Type = java.lang.Object::class.asm internal val OBJECT_TYPE: Type by lazy { java.lang.Object::class.asm }
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "RemoveRedundantQualifierName") @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "RemoveRedundantQualifierName")
internal val OBJECT_ARRAY_TYPE: Type = Array<java.lang.Object>::class.asm internal val OBJECT_ARRAY_TYPE: Type by lazy { Array<java.lang.Object>::class.asm }
internal val ALGEBRA_TYPE: Type = Algebra::class.asm internal val ALGEBRA_TYPE: Type by lazy { Algebra::class.asm }
internal val STRING_TYPE: Type = java.lang.String::class.asm internal val STRING_TYPE: Type by lazy { java.lang.String::class.asm }
} }
} }

View File

@ -1,18 +0,0 @@
package scientifik.kmath.asm.internal
import scientifik.kmath.expressions.Expression
import scientifik.kmath.operations.Algebra
/**
* [Expression] partial implementation to have it subclassed by actual implementations. Provides unified storage for
* objects needed to implement the expression.
*
* @property algebra the algebra to delegate calls.
* @property constants the constants array to have persistent objects to reference in [invoke].
*/
internal abstract class AsmCompiledExpression<T> internal constructor(
@JvmField protected val algebra: Algebra<T>,
@JvmField protected val constants: Array<Any>
) : Expression<T> {
abstract override fun invoke(arguments: Map<String, T>): T
}

View File

@ -1,9 +1,10 @@
package scientifik.kmath.asm.internal package scientifik.kmath.asm.internal
import scientifik.kmath.ast.MST import scientifik.kmath.ast.MST
import scientifik.kmath.expressions.Expression
/** /**
* Creates a class name for [AsmCompiledExpression] subclassed to implement [mst] provided. * Creates a class name for [Expression] subclassed to implement [mst] provided.
* *
* This methods helps to avoid collisions of class name to prevent loading several classes with the same name. If there * This methods helps to avoid collisions of class name to prevent loading several classes with the same name. If there
* is a colliding class, change [collision] parameter or leave it `0` to check existing classes recursively. * is a colliding class, change [collision] parameter or leave it `0` to check existing classes recursively.

View File

@ -1,15 +1,17 @@
package scientifik.kmath.asm.internal package scientifik.kmath.asm.internal
import org.objectweb.asm.ClassWriter import org.objectweb.asm.ClassWriter
import org.objectweb.asm.FieldVisitor
import org.objectweb.asm.MethodVisitor import org.objectweb.asm.MethodVisitor
internal inline fun ClassWriter(flags: Int, block: ClassWriter.() -> Unit): ClassWriter = ClassWriter(flags).apply(block) internal inline fun ClassWriter(flags: Int, block: ClassWriter.() -> Unit): ClassWriter =
ClassWriter(flags).apply(block)
internal inline fun ClassWriter.visitMethod( internal inline fun ClassWriter.visitField(
access: Int, access: Int,
name: String, name: String,
descriptor: String, descriptor: String,
signature: String?, signature: String?,
exceptions: Array<String>?, value: Any?,
block: MethodVisitor.() -> Unit block: FieldVisitor.() -> Unit
): MethodVisitor = visitMethod(access, name, descriptor, signature, exceptions).apply(block) ): FieldVisitor = visitField(access, name, descriptor, signature, value).apply(block)

View File

@ -0,0 +1,10 @@
package scientifik.kmath.asm.internal
import org.objectweb.asm.Label
import org.objectweb.asm.commons.InstructionAdapter
internal fun InstructionAdapter.label(): Label {
val l = Label()
visitLabel(l)
return l
}

View File

@ -3,7 +3,7 @@ package scientifik.kmath.asm.internal
import org.objectweb.asm.MethodVisitor import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.commons.InstructionAdapter import org.objectweb.asm.commons.InstructionAdapter
fun MethodVisitor.instructionAdapter(): InstructionAdapter = InstructionAdapter(this) internal fun MethodVisitor.instructionAdapter(): InstructionAdapter = InstructionAdapter(this)
fun MethodVisitor.instructionAdapter(block: InstructionAdapter.() -> Unit): InstructionAdapter = internal fun MethodVisitor.instructionAdapter(block: InstructionAdapter.() -> Unit): InstructionAdapter =
instructionAdapter().apply(block) instructionAdapter().apply(block)

View File

@ -22,7 +22,7 @@ internal fun <T> AsmBuilder<T>.buildExpectationStack(context: Algebra<T>, name:
val aName = methodNameAdapters[name] ?: name val aName = methodNameAdapters[name] ?: name
val hasSpecific = context.javaClass.methods.find { it.name == aName && it.parameters.size == arity } != null val hasSpecific = context.javaClass.methods.find { it.name == aName && it.parameters.size == arity } != null
val t = if (primitiveMode && hasSpecific) PRIMITIVE_MASK else T_TYPE val t = if (primitiveMode && hasSpecific) PRIMITIVE_MASK else tType
repeat(arity) { expectationStack.push(t) } repeat(arity) { expectationStack.push(t) }
return hasSpecific return hasSpecific