@ -57,7 +57,7 @@ public class StaticFieldUnscrambler(
return fields
return fields
}
}
private fun MethodNode . extractEntryExitBlocks ( ) : Lis t< AbstractInsnNode > {
private fun MethodNode . extractEntryExitBlocks ( ) : Se t< AbstractInsnNode > {
/ *
/ *
* Most ( or all ? ) of the < clinit > methods have " simple " initializers
* Most ( or all ? ) of the < clinit > methods have " simple " initializers
* that we ' re capable of moving in the first and last basic blocks of
* that we ' re capable of moving in the first and last basic blocks of
@ -69,14 +69,14 @@ public class StaticFieldUnscrambler(
val last = instructions . lastOrNull ( )
val last = instructions . lastOrNull ( )
if ( last == null || last . opcode != Opcodes . RETURN ) {
if ( last == null || last . opcode != Opcodes . RETURN ) {
return entry
return entry . toSet ( )
}
}
val exit = instructions . toList ( )
val exit = instructions . toList ( )
. dropLast ( 1 )
. dropLast ( 1 )
. takeLastWhile { it . isSequential }
. takeLastWhile { it . isSequential }
return entry . plus ( exit )
return ( entry + exit ) . toSet ( )
}
}
private fun MethodNode . extractInitializers (
private fun MethodNode . extractInitializers (
@ -86,26 +86,35 @@ public class StaticFieldUnscrambler(
val simpleInitializers = mutableMapOf < MemberDesc , List < AbstractInsnNode > > ( )
val simpleInitializers = mutableMapOf < MemberDesc , List < AbstractInsnNode > > ( )
val complexInitializers = instructions . asSequence ( )
val complexInitializers = instructions . asSequence ( )
. filter { ! entryExitBlocks . contains ( it ) }
. filter { it !in entryExitBlocks }
. filterIsInstance < FieldInsnNode > ( )
. filterIsInstance < FieldInsnNode > ( )
. filter { it . opcode == Opcodes . GETSTATIC && it . owner == owner }
. filter { it . owner == owner }
. filter { ! excludedFields . matches ( it . owner , it . name , it . desc ) }
. map ( :: MemberDesc )
. map ( :: MemberDesc )
. toSet ( )
. toMutable Set ( )
val putstatics = entryExitBlocks
val putstatics = entryExitBlocks
. filterIsInstance < FieldInsnNode > ( )
. filterIsInstance < FieldInsnNode > ( )
. filter { it . opcode == Opcodes . PUTSTATIC && it . owner == owner }
. filter { it . opcode == Opcodes . PUTSTATIC && it . owner == owner }
. filter { ! excludedFields . matches ( it . owner , it . name , it . desc ) }
for ( putstatic in putstatics ) {
for ( putstatic in putstatics ) {
val desc = MemberDesc ( putstatic )
val desc = MemberDesc ( putstatic )
if ( simpleInitializers . containsKey ( desc ) || complexInitializers . contains ( desc ) ) {
if ( desc in complexInitializers ) {
continue
}
if ( desc in simpleInitializers ) {
simpleInitializers -= desc
complexInitializers += desc
continue
continue
}
}
// TODO(gpe): use a filter here (pure with no *LOADs?)
// TODO(gpe): use a filter here (pure with no *LOADs?)
simpleInitializers [ desc ] = getExpression ( putstatic ) ?: continue
val initializer = getExpression ( putstatic )
if ( initializer != null ) {
simpleInitializers [ desc ] = initializer
} else {
complexInitializers += desc
}
}
}
return Pair ( simpleInitializers , complexInitializers )
return Pair ( simpleInitializers , complexInitializers )