Unpick
Unpick is a minimal Java constant uninlining library. It depends only on ObjectWeb ASM.
This project forked from weavemc/unpick
A minimal Java constant uninlining library
License: MIT License
Unpick is a minimal Java constant uninlining library. It depends only on ObjectWeb ASM.
From FabricMC/yarn#2553, it seems that lambda methods currently aren't resolved for unpicking. I forgot where the related unpick code is, but we can just probably visit the invoke dynamic handles (bootstrap method referred in indy bytecode) and unpick the linked synthetic methods.
Yes, in Java, constant values can be non-static, and they exist in Minecraft (and are optimized by javac). Examples:
SpawnGroup.despawnStartRange
ServerLoginNetworkHandler.serverId
Technically, to generate bytecode, instead of just using getstatic
to replace ldc
, you might need a bit more instructions, like aload_0
and then getfield
(might need to expand maxs as a result), and check to ensure the method is non-static.
It usually uses System.lineSeparator
, but the first newline after the header is always \n
:
When two constants have the same value, it would be useful to be able to specify classes where one of these constants should be used.
For example, Minecraft has two constants with value 10 for entity statuses: one in EntityStatuses, for sheeps eating grass, and one in TntMinecartEntity for primed tnt.
Specifying a class where one or the other should be used would allow something like "when sendEntityStatus()
is called in TntMinecartEntity, use the constant of this class, otherwise use the constant in EntityStatuses".
Say there is a use case of an unpick:
private static final int SOME_VALUE = 0;
public void user() {
call(0);
}
public void call(int value) {
if (value == 0) { /* do stuff */ }
}
If it's unpicked, unpick will only replace the 0 in the user()
; it won't replace that in call(int)
's value == 0
check.
Note: migrated from FabricMC/yarn#2268
Sometimes, some constants would be stored as a narrower type and be used as a wider type downstream:
For example:
In the game state change s2c packet, a few values for demo states are stored as integers but always read as floats.
In the packet byte buf, the max nbt size is an int but passed to a ctor that takes longs; the default max string length is a short but the length accepts an int.
Currently, a workaround is to specify a descriptor and a value. However, the problem with that is unpick seems to generate wrong getstatic opcodes with wrong descriptors (than use instruction like i2f), because what i see in decompiler is unresolved field references.
Currently, it seems that unpick handles constant unpicking globally. This isn't bad as things like nbt types or world event ids indeed are accessed pretty much exclusively with constant values.
However, there are other more delicate cases, such as a constant (used as some easily toggled preconfigured value) for max nbt size from a private static field. Such constants currently are replaced by targetting all calls to a specific method, but this is a waste of resource as the constant usage is usually restricted to within one class, or even 1 method.
Long story short, we just want a way to specify that a constant usage is restricted to one method/class than the whole classpath in order to avoid inadvertent bugs.
This technically shouldn't be too hard; those fields can just be treated as a union of getter and setter methods in pretty much all senses. And yes, we indeed might have fields using constants/flags that are public. Just for consideration.
If the target method is defined multiple times, only the latest definition is taken into account and previous unpick data will be lost.
This is a slight problem in Yarn where we want to split Unpick files mostly by constant groups, and the same method might have multiple constant groups, so we have to put all categories into a longer file.
I think this is the cause (not 100% sure, just found this when digging around on GH):
put
call just ignores existing data.Currently invalid constants log a message at WARN level. This was done so that all invalid constants are detected at once.
However they are really a fatal error, so they should instead be collected, and then Unpick should fail.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.