Skip to content

Commit

Permalink
move propagator to be directly on jvm side
Browse files Browse the repository at this point in the history
  • Loading branch information
wagyourtail committed Jul 11, 2024
1 parent ba0ffc3 commit dd599c8
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 115 deletions.
4 changes: 2 additions & 2 deletions src/jvmMain/kotlin/xyz/wagyourtail/unimined/mapping/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import okio.buffer
import okio.sink
import okio.source
import xyz.wagyourtail.unimined.mapping.formats.FormatRegistry
import xyz.wagyourtail.unimined.mapping.propogator.PropogatorImpl
import xyz.wagyourtail.unimined.mapping.propogator.Propagator
import xyz.wagyourtail.unimined.mapping.tree.MemoryMappingTree
import xyz.wagyourtail.unimined.mapping.util.mutliAssociate
import xyz.wagyourtail.unimined.mapping.visitor.delegate.copyTo
Expand Down Expand Up @@ -50,7 +50,7 @@ class Main: CliktCommand() {
if (prop.isNotEmpty() || cp.isNotEmpty()) {
LOGGER.info { "Propogating..." }
val t = measureTime {
PropogatorImpl(Namespace(propogationNs!!), mappings, prop + cp)
Propagator(Namespace(propogationNs!!), mappings, prop + cp)
.propagate(mappings.namespaces.toSet() - Namespace(propogationNs!!))
}
LOGGER.info { "Propogated in ${t.inWholeMilliseconds}ms" }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
package xyz.wagyourtail.unimined.mapping.visitor.fixes.propogator
package xyz.wagyourtail.unimined.mapping.propogator

import io.github.oshai.kotlinlogging.KotlinLogging
import org.apache.commons.compress.archivers.zip.ZipFile
import org.objectweb.asm.ClassReader
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.ClassNode
import xyz.wagyourtail.unimined.mapping.Namespace
import xyz.wagyourtail.unimined.mapping.jvms.four.AccessFlag
import xyz.wagyourtail.unimined.mapping.jvms.four.ElementType
import xyz.wagyourtail.unimined.mapping.jvms.four.minus
import xyz.wagyourtail.unimined.mapping.jvms.four.plus
import xyz.wagyourtail.unimined.mapping.jvms.four.three.three.MethodDescriptor
import xyz.wagyourtail.unimined.mapping.jvms.four.two.one.InternalName
import xyz.wagyourtail.unimined.mapping.tree.AbstractMappingTree
import xyz.wagyourtail.unimined.mapping.visitor.AccessType
import xyz.wagyourtail.unimined.mapping.visitor.MappingVisitor
import xyz.wagyourtail.unimined.mapping.visitor.use
import java.io.InputStream
import java.nio.file.Files
import java.nio.file.Path
import kotlin.streams.asStream

abstract class Propagator<T: Propagator<T>>(val namespace: Namespace, val tree: AbstractMappingTree) {
private val LOGGER = KotlinLogging.logger { }
class Propagator(val namespace: Namespace, val tree: AbstractMappingTree, required: Set<Path>) {
val LOGGER = KotlinLogging.logger { }

abstract val classes: Map<InternalName, ClassInfo<T>>
val classes: Map<InternalName, ClassInfo> = run {
val classes = mutableMapOf<InternalName, ClassInfo>()
required.parallelStream().forEach { path ->
ZipFile.builder().setSeekableByteChannel(Files.newByteChannel(path)).get().use { zf ->
zf.entries.asSequence().asStream().parallel().forEach {
if (!it.isDirectory && !it.name.startsWith("META-INF/versions") && it.name.endsWith(".class")) {
val className = InternalName.read(it.name.removeSuffix(".class"))
classes[className] = ClassInfo(className, zf.getInputStream(it))
}
}
}
}
classes
}


init {
classes.values.parallelStream().forEach {
it.resolved
}
}

private val propagationList: Map<Pair<InternalName, Pair<String, MethodDescriptor?>>, Set<InternalName>> by lazy {
val methods = mutableMapOf<Pair<InternalName, Pair<String, MethodDescriptor?>>, MutableSet<InternalName>>()
Expand Down Expand Up @@ -81,28 +114,51 @@ abstract class Propagator<T: Propagator<T>>(val namespace: Namespace, val tree:
}
}

abstract class ClassInfo<T: Propagator<T>>(val info: T, val name: InternalName) {
protected abstract val parent: InternalName?
protected abstract val interfaces: List<InternalName>

protected abstract val methods: List<Pair<String, MethodDescriptor?>>
inner class ClassInfo(val name: InternalName, val inputStream: InputStream) {

protected val classNode by lazy {
info.tree.getClass(info.namespace, name)
private val self = try {
ClassReader(inputStream).let { reader ->
val node = ClassNode()
reader.accept(node, ClassReader.SKIP_CODE)
node
}
} catch (e: Exception) {
LOGGER.error(e) { "Failed to read class $name" }
val cn = ClassNode()
cn.name = name.value
cn.superName = "java/lang/Object"
cn
}

val classNode by lazy {
tree.getClass(namespace, name)
}

private fun traverseParents(): Sequence<ClassInfo<T>> {
var current: ClassInfo<T>? = this
return generateSequence {
val c = current
current = c?.parent?.let { info.classes[it] }
c
}.flatMap { c ->
sequenceOf(c) + c.interfaces.asSequence()
.mapNotNull { info.classes[it] }
.flatMap { sequenceOf(it) + it.traverseParents() }
val parent = InternalName.read(self.superName)

val interfaces = self.interfaces.map { InternalName.read(it) }

val methods: List<Pair<String, MethodDescriptor?>> = self.methods.filter { method ->
var access = method.access

// modify access according to mapping's access rules for this class
classNode?.getMethods(namespace, method.name, MethodDescriptor.read(method.desc))?.forEach { mNode ->
for (node in mNode.access) {
if (node.conditions.check(AccessFlag.of(ElementType.METHOD, access))) {
if (node.namespaces.contains(namespace)) {
if (node.accessType == AccessType.ADD) {
access = method.access + node.accessFlag
} else if (node.accessType == AccessType.REMOVE) {
access = method.access - node.accessFlag
}
}
}
}
}
}

access and (Opcodes.ACC_STATIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_FINAL) == 0
}.map { it.name to MethodDescriptor.read(it.desc) }

val resolved: Map<Pair<String, MethodDescriptor?>, Set<InternalName>> by lazy {
val md = mutableMapOf<Pair<String, MethodDescriptor?>, MutableSet<InternalName>>()
Expand All @@ -114,5 +170,19 @@ abstract class Propagator<T: Propagator<T>>(val namespace: Namespace, val tree:
md
}

private fun traverseParents(): Sequence<ClassInfo> {
var current: ClassInfo? = this
return generateSequence {
val c = current
current = c?.parent?.let { classes[it] }
c
}.flatMap { c ->
sequenceOf(c) + c.interfaces.asSequence()
.mapNotNull { classes[it] }
.flatMap { sequenceOf(it) + it.traverseParents() }
}
}

}
}

}

This file was deleted.

0 comments on commit dd599c8

Please sign in to comment.