Dev #127
@ -24,20 +24,20 @@ For example, the following builder:
|
||||
package scientifik.kmath.asm.generated;
|
||||
|
||||
import java.util.Map;
|
||||
import scientifik.kmath.asm.internal.AsmCompiledExpression;
|
||||
import scientifik.kmath.operations.Algebra;
|
||||
import scientifik.kmath.expressions.Expression;
|
||||
import scientifik.kmath.operations.RealField;
|
||||
|
||||
// The class's name is build with MST's hash-code and collision fixing number.
|
||||
public final class AsmCompiledExpression_45045_0 extends AsmCompiledExpression<Double> {
|
||||
// Plain constructor
|
||||
public AsmCompiledExpression_45045_0(Algebra algebra, Object[] constants) {
|
||||
super(algebra, constants);
|
||||
public final class AsmCompiledExpression_1073786867_0 implements Expression<Double> {
|
||||
private final RealField algebra;
|
||||
private final Object[] 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -6,6 +6,7 @@ import org.objectweb.asm.Opcodes.RETURN
|
||||
import org.objectweb.asm.commons.InstructionAdapter
|
||||
import scientifik.kmath.asm.internal.AsmBuilder.ClassLoader
|
||||
import scientifik.kmath.ast.MST
|
||||
import scientifik.kmath.expressions.Expression
|
||||
import scientifik.kmath.operations.Algebra
|
||||
import java.util.*
|
||||
import kotlin.reflect.KClass
|
||||
@ -36,32 +37,27 @@ internal class AsmBuilder<T> internal constructor(
|
||||
*/
|
||||
private val classLoader: ClassLoader = ClassLoader(javaClass.classLoader)
|
||||
|
||||
@Suppress("PrivatePropertyName")
|
||||
private val T_ALGEBRA_TYPE: Type = algebra::class.asm
|
||||
|
||||
@Suppress("PrivatePropertyName")
|
||||
internal val T_TYPE: Type = classOfT.asm
|
||||
|
||||
@Suppress("PrivatePropertyName")
|
||||
private val CLASS_TYPE: Type = Type.getObjectType(className.replace(oldChar = '.', newChar = '/'))!!
|
||||
private val tAlgebraType: Type = algebra::class.asm
|
||||
internal val tType: Type = classOfT.asm
|
||||
private val classType: 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
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
/**
|
||||
* List of constants to provide to [AsmCompiledExpression] subclass.
|
||||
* List of constants to provide to the subclass.
|
||||
*/
|
||||
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
|
||||
internal var primitiveMode = false
|
||||
@ -72,78 +68,92 @@ internal class AsmBuilder<T> internal constructor(
|
||||
@Suppress("PropertyName")
|
||||
internal var PRIMITIVE_MASK_BOXED: Type = OBJECT_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.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun getInstance(): AsmCompiledExpression<T> {
|
||||
fun getInstance(): Expression<T> {
|
||||
generatedInstance?.let { return it }
|
||||
|
||||
if (SIGNATURE_LETTERS.containsKey(classOfT.java)) {
|
||||
if (SIGNATURE_LETTERS.containsKey(classOfT)) {
|
||||
primitiveMode = true
|
||||
PRIMITIVE_MASK = SIGNATURE_LETTERS.getValue(classOfT.java)
|
||||
PRIMITIVE_MASK_BOXED = T_TYPE
|
||||
PRIMITIVE_MASK = SIGNATURE_LETTERS.getValue(classOfT)
|
||||
PRIMITIVE_MASK_BOXED = tType
|
||||
}
|
||||
|
||||
val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) {
|
||||
visit(
|
||||
Opcodes.V1_8,
|
||||
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER,
|
||||
CLASS_TYPE.internalName,
|
||||
"L${ASM_COMPILED_EXPRESSION_TYPE.internalName}<${T_TYPE.descriptor}>;",
|
||||
ASM_COMPILED_EXPRESSION_TYPE.internalName,
|
||||
arrayOf()
|
||||
classType.internalName,
|
||||
"${OBJECT_TYPE.descriptor}L${EXPRESSION_TYPE.internalName}<${tType.descriptor}>;",
|
||||
OBJECT_TYPE.internalName,
|
||||
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(
|
||||
Opcodes.ACC_PUBLIC,
|
||||
"<init>",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, ALGEBRA_TYPE, OBJECT_ARRAY_TYPE),
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, tAlgebraType, OBJECT_ARRAY_TYPE),
|
||||
null,
|
||||
null
|
||||
).instructionAdapter {
|
||||
val thisVar = 0
|
||||
val algebraVar = 1
|
||||
val constantsVar = 2
|
||||
val l0 = Label()
|
||||
visitLabel(l0)
|
||||
load(thisVar, CLASS_TYPE)
|
||||
load(algebraVar, ALGEBRA_TYPE)
|
||||
val l0 = label()
|
||||
load(thisVar, classType)
|
||||
invokespecial(OBJECT_TYPE.internalName, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE), false)
|
||||
label()
|
||||
load(thisVar, classType)
|
||||
load(algebraVar, tAlgebraType)
|
||||
putfield(classType.internalName, "algebra", tAlgebraType.descriptor)
|
||||
label()
|
||||
load(thisVar, classType)
|
||||
load(constantsVar, OBJECT_ARRAY_TYPE)
|
||||
|
||||
invokespecial(
|
||||
ASM_COMPILED_EXPRESSION_TYPE.internalName,
|
||||
"<init>",
|
||||
Type.getMethodDescriptor(Type.VOID_TYPE, ALGEBRA_TYPE, OBJECT_ARRAY_TYPE),
|
||||
false
|
||||
)
|
||||
|
||||
val l1 = Label()
|
||||
visitLabel(l1)
|
||||
putfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
|
||||
label()
|
||||
visitInsn(RETURN)
|
||||
val l2 = Label()
|
||||
visitLabel(l2)
|
||||
visitLocalVariable("this", CLASS_TYPE.descriptor, null, l0, l2, thisVar)
|
||||
val l4 = label()
|
||||
visitLocalVariable("this", classType.descriptor, null, l0, l4, thisVar)
|
||||
|
||||
visitLocalVariable(
|
||||
"algebra",
|
||||
ALGEBRA_TYPE.descriptor,
|
||||
"L${ALGEBRA_TYPE.internalName}<${T_TYPE.descriptor}>;",
|
||||
tAlgebraType.descriptor,
|
||||
null,
|
||||
l0,
|
||||
l2,
|
||||
l4,
|
||||
algebraVar
|
||||
)
|
||||
|
||||
visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l2, constantsVar)
|
||||
visitLocalVariable("constants", OBJECT_ARRAY_TYPE.descriptor, null, l0, l4, constantsVar)
|
||||
visitMaxs(0, 3)
|
||||
visitEnd()
|
||||
}
|
||||
@ -151,22 +161,20 @@ internal class AsmBuilder<T> internal constructor(
|
||||
visitMethod(
|
||||
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL,
|
||||
"invoke",
|
||||
Type.getMethodDescriptor(T_TYPE, MAP_TYPE),
|
||||
"(L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${T_TYPE.descriptor}>;)${T_TYPE.descriptor}",
|
||||
Type.getMethodDescriptor(tType, MAP_TYPE),
|
||||
"(L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;)${tType.descriptor}",
|
||||
null
|
||||
).instructionAdapter {
|
||||
invokeMethodVisitor = this
|
||||
visitCode()
|
||||
val l0 = Label()
|
||||
visitLabel(l0)
|
||||
val l0 = label()
|
||||
invokeLabel0Visitor()
|
||||
areturn(T_TYPE)
|
||||
val l1 = Label()
|
||||
visitLabel(l1)
|
||||
areturn(tType)
|
||||
val l1 = label()
|
||||
|
||||
visitLocalVariable(
|
||||
"this",
|
||||
CLASS_TYPE.descriptor,
|
||||
classType.descriptor,
|
||||
null,
|
||||
l0,
|
||||
l1,
|
||||
@ -176,7 +184,7 @@ internal class AsmBuilder<T> internal constructor(
|
||||
visitLocalVariable(
|
||||
"arguments",
|
||||
MAP_TYPE.descriptor,
|
||||
"L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${T_TYPE.descriptor}>;",
|
||||
"L${MAP_TYPE.internalName}<${STRING_TYPE.descriptor}+${tType.descriptor}>;",
|
||||
l0,
|
||||
l1,
|
||||
invokeArgumentsVar
|
||||
@ -196,18 +204,16 @@ internal class AsmBuilder<T> internal constructor(
|
||||
val thisVar = 0
|
||||
val argumentsVar = 1
|
||||
visitCode()
|
||||
val l0 = Label()
|
||||
visitLabel(l0)
|
||||
val l0 = label()
|
||||
load(thisVar, OBJECT_TYPE)
|
||||
load(argumentsVar, MAP_TYPE)
|
||||
invokevirtual(CLASS_TYPE.internalName, "invoke", Type.getMethodDescriptor(T_TYPE, MAP_TYPE), false)
|
||||
areturn(T_TYPE)
|
||||
val l1 = Label()
|
||||
visitLabel(l1)
|
||||
invokevirtual(classType.internalName, "invoke", Type.getMethodDescriptor(tType, MAP_TYPE), false)
|
||||
areturn(tType)
|
||||
val l1 = label()
|
||||
|
||||
visitLocalVariable(
|
||||
"this",
|
||||
CLASS_TYPE.descriptor,
|
||||
classType.descriptor,
|
||||
null,
|
||||
l0,
|
||||
l1,
|
||||
@ -225,7 +231,7 @@ internal class AsmBuilder<T> internal constructor(
|
||||
.defineClass(className, classWriter.toByteArray())
|
||||
.constructors
|
||||
.first()
|
||||
.newInstance(algebra, constants.toTypedArray()) as AsmCompiledExpression<T>
|
||||
.newInstance(algebra, constants.toTypedArray()) as Expression<T>
|
||||
|
||||
generatedInstance = new
|
||||
return new
|
||||
@ -235,21 +241,21 @@ internal class AsmBuilder<T> internal constructor(
|
||||
* Loads a constant from
|
||||
*/
|
||||
internal fun loadTConstant(value: T) {
|
||||
if (classOfT.java in INLINABLE_NUMBERS) {
|
||||
if (classOfT in INLINABLE_NUMBERS) {
|
||||
val expectedType = expectationStack.pop()!!
|
||||
val mustBeBoxed = expectedType.sort == Type.OBJECT
|
||||
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
|
||||
}
|
||||
|
||||
loadConstant(value as Any, T_TYPE)
|
||||
loadConstant(value as Any, tType)
|
||||
}
|
||||
|
||||
private fun box(): Unit = invokeMethodVisitor.invokestatic(
|
||||
T_TYPE.internalName,
|
||||
tType.internalName,
|
||||
"valueOf",
|
||||
Type.getMethodDescriptor(T_TYPE, PRIMITIVE_MASK),
|
||||
Type.getMethodDescriptor(tType, PRIMITIVE_MASK),
|
||||
false
|
||||
)
|
||||
|
||||
@ -263,16 +269,16 @@ internal class AsmBuilder<T> internal constructor(
|
||||
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
|
||||
loadThis()
|
||||
getfield(CLASS_TYPE.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
|
||||
getfield(classType.internalName, "constants", OBJECT_ARRAY_TYPE.descriptor)
|
||||
iconst(idx)
|
||||
visitInsn(AALOAD)
|
||||
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
|
||||
* from it).
|
||||
*/
|
||||
@ -292,7 +298,7 @@ internal class AsmBuilder<T> internal constructor(
|
||||
|
||||
if (mustBeBoxed) {
|
||||
box()
|
||||
invokeMethodVisitor.checkcast(T_TYPE)
|
||||
invokeMethodVisitor.checkcast(tType)
|
||||
}
|
||||
|
||||
return
|
||||
@ -300,11 +306,11 @@ internal class AsmBuilder<T> internal constructor(
|
||||
|
||||
loadConstant(value, boxed)
|
||||
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 {
|
||||
load(invokeArgumentsVar, OBJECT_ARRAY_TYPE)
|
||||
@ -319,7 +325,7 @@ internal class AsmBuilder<T> internal constructor(
|
||||
Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE, OBJECT_TYPE)
|
||||
)
|
||||
|
||||
invokeMethodVisitor.checkcast(T_TYPE)
|
||||
invokeMethodVisitor.checkcast(tType)
|
||||
return
|
||||
}
|
||||
|
||||
@ -331,11 +337,11 @@ internal class AsmBuilder<T> internal constructor(
|
||||
Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE)
|
||||
)
|
||||
|
||||
invokeMethodVisitor.checkcast(T_TYPE)
|
||||
invokeMethodVisitor.checkcast(tType)
|
||||
val expectedType = expectationStack.pop()!!
|
||||
|
||||
if (expectedType.sort == Type.OBJECT)
|
||||
typeStack.push(T_TYPE)
|
||||
typeStack.push(tType)
|
||||
else {
|
||||
unbox()
|
||||
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() {
|
||||
loadThis()
|
||||
|
||||
invokeMethodVisitor.run {
|
||||
getfield(ASM_COMPILED_EXPRESSION_TYPE.internalName, "algebra", ALGEBRA_TYPE.descriptor)
|
||||
checkcast(T_ALGEBRA_TYPE)
|
||||
}
|
||||
invokeMethodVisitor.getfield(classType.internalName, "algebra", tAlgebraType.descriptor)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -368,7 +370,12 @@ internal class AsmBuilder<T> internal constructor(
|
||||
tArity: Int,
|
||||
opcode: Int = Opcodes.INVOKEINTERFACE
|
||||
) {
|
||||
repeat(tArity) { if (!typeStack.empty()) typeStack.pop() }
|
||||
run loop@{
|
||||
repeat(tArity) {
|
||||
if (typeStack.empty()) return@loop
|
||||
typeStack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
invokeMethodVisitor.visitMethodInsn(
|
||||
opcode,
|
||||
@ -378,12 +385,12 @@ internal class AsmBuilder<T> internal constructor(
|
||||
opcode == Opcodes.INVOKEINTERFACE
|
||||
)
|
||||
|
||||
invokeMethodVisitor.checkcast(T_TYPE)
|
||||
invokeMethodVisitor.checkcast(tType)
|
||||
val isLastExpr = expectationStack.size == 1
|
||||
val expectedType = expectationStack.pop()!!
|
||||
|
||||
if (expectedType.sort == Type.OBJECT || isLastExpr)
|
||||
typeStack.push(T_TYPE)
|
||||
typeStack.push(tType)
|
||||
else {
|
||||
unbox()
|
||||
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.
|
||||
*/
|
||||
private val SIGNATURE_LETTERS: Map<Class<out Any>, Type> by lazy {
|
||||
private val SIGNATURE_LETTERS: Map<KClass<out Any>, Type> by lazy {
|
||||
hashMapOf(
|
||||
java.lang.Byte::class.java to Type.BYTE_TYPE,
|
||||
java.lang.Short::class.java to Type.SHORT_TYPE,
|
||||
java.lang.Integer::class.java to Type.INT_TYPE,
|
||||
java.lang.Long::class.java to Type.LONG_TYPE,
|
||||
java.lang.Float::class.java to Type.FLOAT_TYPE,
|
||||
java.lang.Double::class.java to Type.DOUBLE_TYPE
|
||||
java.lang.Byte::class to Type.BYTE_TYPE,
|
||||
java.lang.Short::class to Type.SHORT_TYPE,
|
||||
java.lang.Integer::class to Type.INT_TYPE,
|
||||
java.lang.Long::class to Type.LONG_TYPE,
|
||||
java.lang.Float::class to Type.FLOAT_TYPE,
|
||||
java.lang.Double::class to Type.DOUBLE_TYPE
|
||||
)
|
||||
}
|
||||
|
||||
private val BOXED_TO_PRIMITIVES: Map<Type, Type> by lazy {
|
||||
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 BOXED_TO_PRIMITIVES: Map<Type, Type> by lazy { SIGNATURE_LETTERS.mapKeys { (k, _) -> k.asm } }
|
||||
|
||||
private val NUMBER_CONVERTER_METHODS: Map<Type, String> by lazy {
|
||||
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.
|
||||
*/
|
||||
private val INLINABLE_NUMBERS: Set<Class<out Any>> by lazy { SIGNATURE_LETTERS.keys }
|
||||
internal val ASM_COMPILED_EXPRESSION_TYPE: Type = AsmCompiledExpression::class.asm
|
||||
internal val NUMBER_TYPE: Type = java.lang.Number::class.asm
|
||||
internal val MAP_TYPE: Type = java.util.Map::class.asm
|
||||
internal val OBJECT_TYPE: Type = java.lang.Object::class.asm
|
||||
private val INLINABLE_NUMBERS: Set<KClass<out Any>> by lazy { SIGNATURE_LETTERS.keys }
|
||||
internal val EXPRESSION_TYPE: Type by lazy { Expression::class.asm }
|
||||
internal val NUMBER_TYPE: Type by lazy { java.lang.Number::class.asm }
|
||||
internal val MAP_TYPE: Type by lazy { java.util.Map::class.asm }
|
||||
internal val OBJECT_TYPE: Type by lazy { java.lang.Object::class.asm }
|
||||
|
||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "RemoveRedundantQualifierName")
|
||||
internal val OBJECT_ARRAY_TYPE: Type = Array<java.lang.Object>::class.asm
|
||||
internal val ALGEBRA_TYPE: Type = Algebra::class.asm
|
||||
internal val STRING_TYPE: Type = java.lang.String::class.asm
|
||||
internal val OBJECT_ARRAY_TYPE: Type by lazy { Array<java.lang.Object>::class.asm }
|
||||
internal val ALGEBRA_TYPE: Type by lazy { Algebra::class.asm }
|
||||
internal val STRING_TYPE: Type by lazy { java.lang.String::class.asm }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
package scientifik.kmath.asm.internal
|
||||
|
||||
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
|
||||
* is a colliding class, change [collision] parameter or leave it `0` to check existing classes recursively.
|
||||
|
@ -1,15 +1,17 @@
|
||||
package scientifik.kmath.asm.internal
|
||||
|
||||
import org.objectweb.asm.ClassWriter
|
||||
import org.objectweb.asm.FieldVisitor
|
||||
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,
|
||||
name: String,
|
||||
descriptor: String,
|
||||
signature: String?,
|
||||
exceptions: Array<String>?,
|
||||
block: MethodVisitor.() -> Unit
|
||||
): MethodVisitor = visitMethod(access, name, descriptor, signature, exceptions).apply(block)
|
||||
value: Any?,
|
||||
block: FieldVisitor.() -> Unit
|
||||
): FieldVisitor = visitField(access, name, descriptor, signature, value).apply(block)
|
||||
|
@ -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
|
||||
}
|
@ -3,7 +3,7 @@ package scientifik.kmath.asm.internal
|
||||
import org.objectweb.asm.MethodVisitor
|
||||
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)
|
||||
|
@ -22,7 +22,7 @@ internal fun <T> AsmBuilder<T>.buildExpectationStack(context: Algebra<T>, name:
|
||||
val aName = methodNameAdapters[name] ?: name
|
||||
|
||||
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) }
|
||||
|
||||
return hasSpecific
|
||||
|
Loading…
Reference in New Issue
Block a user