Merge various codegen utilities into one file

This commit is contained in:
Iaroslav 2020-06-27 20:15:14 +07:00
parent efcfb44253
commit e98fc126c4
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
6 changed files with 63 additions and 66 deletions

View File

@ -1,22 +0,0 @@
package scientifik.kmath.asm.internal
import scientifik.kmath.ast.MST
import scientifik.kmath.expressions.Expression
/**
* 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.
*/
internal tailrec fun buildName(mst: MST, collision: Int = 0): String {
val name = "scientifik.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision"
try {
Class.forName(name)
} catch (ignored: ClassNotFoundException) {
return name
}
return buildName(mst, collision + 1)
}

View File

@ -1,17 +0,0 @@
package scientifik.kmath.asm.internal
import org.objectweb.asm.ClassWriter
import org.objectweb.asm.FieldVisitor
@Suppress("FunctionName")
internal inline fun ClassWriter(flags: Int, block: ClassWriter.() -> Unit): ClassWriter =
ClassWriter(flags).apply(block)
internal inline fun ClassWriter.visitField(
access: Int,
name: String,
descriptor: String,
signature: String?,
value: Any?,
block: FieldVisitor.() -> Unit
): FieldVisitor = visitField(access, name, descriptor, signature, value).apply(block)

View File

@ -1,7 +0,0 @@
package scientifik.kmath.asm.internal
import org.objectweb.asm.Type
import kotlin.reflect.KClass
internal val KClass<*>.asm: Type
get() = Type.getType(java)

View File

@ -1,8 +1,12 @@
package scientifik.kmath.asm.internal package scientifik.kmath.asm.internal
import org.objectweb.asm.*
import org.objectweb.asm.Opcodes.INVOKEVIRTUAL import org.objectweb.asm.Opcodes.INVOKEVIRTUAL
import org.objectweb.asm.Type import org.objectweb.asm.commons.InstructionAdapter
import scientifik.kmath.ast.MST
import scientifik.kmath.expressions.Expression
import scientifik.kmath.operations.Algebra import scientifik.kmath.operations.Algebra
import kotlin.reflect.KClass
private val methodNameAdapters: Map<Pair<String, Int>, String> by lazy { private val methodNameAdapters: Map<Pair<String, Int>, String> by lazy {
hashMapOf( hashMapOf(
@ -15,6 +19,60 @@ private val methodNameAdapters: Map<Pair<String, Int>, String> by lazy {
) )
} }
internal val KClass<*>.asm: Type
get() = Type.getType(java)
/**
* Creates an [InstructionAdapter] from this [MethodVisitor].
*/
private fun MethodVisitor.instructionAdapter(): InstructionAdapter = InstructionAdapter(this)
/**
* Creates an [InstructionAdapter] from this [MethodVisitor] and applies [block] to it.
*/
internal fun MethodVisitor.instructionAdapter(block: InstructionAdapter.() -> Unit): InstructionAdapter =
instructionAdapter().apply(block)
/**
* Constructs a [Label], then applies it to this visitor.
*/
internal fun MethodVisitor.label(): Label {
val l = Label()
visitLabel(l)
return l
}
/**
* 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.
*/
internal tailrec fun buildName(mst: MST, collision: Int = 0): String {
val name = "scientifik.kmath.asm.generated.AsmCompiledExpression_${mst.hashCode()}_$collision"
try {
Class.forName(name)
} catch (ignored: ClassNotFoundException) {
return name
}
return buildName(mst, collision + 1)
}
@Suppress("FunctionName")
internal inline fun ClassWriter(flags: Int, block: ClassWriter.() -> Unit): ClassWriter =
ClassWriter(flags).apply(block)
internal inline fun ClassWriter.visitField(
access: Int,
name: String,
descriptor: String,
signature: String?,
value: Any?,
block: FieldVisitor.() -> Unit
): FieldVisitor = visitField(access, name, descriptor, signature, value).apply(block)
/** /**
* Checks if the target [context] for code generation contains a method with needed [name] and [arity], also builds * Checks if the target [context] for code generation contains a method with needed [name] and [arity], also builds
* type expectation stack for needed arity. * type expectation stack for needed arity.
@ -60,6 +118,9 @@ private fun <T> AsmBuilder<T>.tryInvokeSpecific(context: Algebra<T>, name: Strin
return true return true
} }
/**
* Builds specialized algebra call with option to fallback to generic algebra operation accepting String.
*/
internal fun <T> AsmBuilder<T>.buildAlgebraOperationCall( internal fun <T> AsmBuilder<T>.buildAlgebraOperationCall(
context: Algebra<T>, context: Algebra<T>,
name: String, name: String,
@ -84,3 +145,4 @@ internal fun <T> AsmBuilder<T>.buildAlgebraOperationCall(
expectedArity = arity expectedArity = arity
) )
} }

View File

@ -1,10 +0,0 @@
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

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