Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce support for constants in the MDC. #7

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

marchermans
Copy link
Member

This introduces constant field data to the MDC and processes it as if it was a JDoc entry.

Allows for unpick data to be stored here.
@marchermans marchermans requested a review from sciwhiz12 May 29, 2023 09:42
@sciwhiz12 sciwhiz12 added the enhancement New feature or request label May 30, 2023
Copy link
Member

@sciwhiz12 sciwhiz12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was discussed internally by some members of the team and external stakeholders, brought about by FabricMC/community#124 (comment).

Background

javac performs constant inlining at compile-time, inlining compile-time constant expressions (such as static final numerical constants, and operations on constants) in the class bytecode without having to reference the original constant. For example, a call of setBlockState(pos, block, Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS) would have constant inlining on the third parameter, leading to an effective bytecode-level call of setBlockState(pos, block, 3) (where Block.UPDATE_NEIGHBORS is 1 and Block.UPDATE_CLIENTS is 2).

However, this presents difficulties when reading decompiled source, because there is no trace that links these 'folded' constants from their originating counterparts. Per above, a viewer of decompiled source would only see the 3, and have no clue (outside of external or pre-obtained knowledge) that it came from Block.UPDATE_NEIGHBORS | Block.UPDATE_CLIENTS (or maybe even Block.UPDATE_ALL).

Constant un-inlining or unpicking attempts to solve this problem by building a database of known places in the codebase where constants are used, and a database of these constants, and then using this information to 'reverse' a combined constant back into its constituent fields. In the above example, it would know the third parameter of setBlockState is a potential constant unpicking site, and it would know the series of Block constant fields which fit there, and act accordingly (either on bytecode or on source) to recreate the bitwise operation of those constant fields.

This PR is the first step to adding such constant unpicking information to Parchment, to be carried alongside our mappings. As Parchment stands as a modloader-neutral set of mappings, we can be a centralized source of unpicking information for consumption by any modloader or toolchain which so chooses to use that information.


There's two things in this PR which I feel needs to be addressed:

  1. Pseudo-examples of how the constant data would be stored, such as for exmaple setBlockState, must be given so we can properly contextualize how this information might be written or read.

  2. The Mapping Data Container format version needs to be bumped on its minor version, per our specification. We also need to update the specification accordingly, once this PR is through

    We might also think on including the specifications as part of the repository proper, so it is always available as a reference, rather than being part of the GitHub repository wiki. I think it would be good to include the current specification into the repository as a separate PR, so this PR can then modify it accordingly.

  3. The test data should be properly modified to include tests for this constant data, so the automated IO tests can check that the data is serialized and deserialized properly.

  4. I have the concern that, if I understand the current situation, there will be a lot of copy-pasting constant data for parameters between methods that share the same constant characteristics -- for example, setBlockState, setBlock, sendBlockUpdated, and others.

    However, I do think it might be the purview of higher-level tools to do that collation and automated duplication of data per user-given inputs. For example, a tool like Enigma would maintain some such file with constant 'groups' (containing the list of constant fields), and mappings of such 'groups' to appropriate method parameters.

    On this, I'm thinking on the previously discussed possibility that we ought to put the constant data in a separate file entirely, and leave the MDC format unchanged. However, that would mean making a new file format and codifying it through specification and code, which would be a burden indeed.

    I'd like your input on that matter.

Comment on lines -252 to +265
if (!(o instanceof FieldData)) return false;
FieldData that = (FieldData) o;
return getName().equals(that.getName()) && Objects.equals(getDescriptor(), that.getDescriptor())
&& getJavadoc().equals(that.getJavadoc());
if (!(o instanceof ImmutableFieldData)) return false;

ImmutableFieldData that = (ImmutableFieldData) o;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change would mean ImmutableFieldData would be incomparable to other FieldData instances (such as mutable ones). It should only check if it is an instance of FieldData.

Same comment on all other similar instances.

Comment on lines -260 to +281
return Objects.hash(getName(), getDescriptor(), getJavadoc());
int result = getName() != null ? getName().hashCode() : 0;
result = 31 * result + (getDescriptor() != null ? getDescriptor().hashCode() : 0);
result = 31 * result + (getJavadoc() != null ? getJavadoc().hashCode() : 0);
result = 31 * result + (getConstant() != null ? getConstant().hashCode() : 0);
return result;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change from Objects.hash? Are there any substantial benefits to hardcoding ourselves to this pattern of hashcoding? (I'd also like a source on how this pattern was decided.)

Same comment on all other similar instances.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants