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

[pull] master from erlang:master #196

Merged
merged 23 commits into from
Jan 29, 2025
Merged

[pull] master from erlang:master #196

merged 23 commits into from
Jan 29, 2025

Conversation

pull[bot]
Copy link

@pull pull bot commented Jan 29, 2025

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.1)

Can you help keep this open source service alive? 💖 Please sponsor : )

Summary by Sourcery

Optimize bitstring matching by ensuring the bitstring length before matching and using specialized instructions for various match operations.

Bug Fixes:

  • Fix a bug where the validator did not check that operations were preceded by bs_ensure_at_least or bs_ensure_exactly.

Enhancements:

  • Improve the performance of bitstring matching.
  • Reduce the number of Y registers required for landingpad instructions.

Tests:

  • Add tests for bitstring matching operations with and without the bs_ensure instruction.

jhogberg and others added 23 commits January 23, 2025 12:21
The internal instructions `bs_checked_get` and `bs_checked_skip` have
confusing names. One might think that they do some extra checking,
while the opposite is true.

Rename them to `bs_ensured_get` and `bs_ensured_skip` to make the
connection to the `bs_ensure` instruction clearer.
The compiler could sometimes generate unsafe code when
matching literal data in a binary. For example:

    t(Data) ->
        <<Rest/bits>> = Data,
        {_, Bits} = ext:ernal(Rest),
        case Rest of
            <<0, _:Bits>> -> not_empty;
            <<>> -> empty
        end.

The generated code for the first clause of the `case` would
look like this:

    {bs_match,{f,20},{y,2},{commands,[{'=:=',nil,8,0}]}}.

That is unsafe because the first command in a `bs_match` instruction
must always be an `ensure*` instruction to ensure that the bitstring
is of sufficient size.

This unsafe code generation was introduced in 60f8f9e.

This commit ensures that a `bs_match_string` instruction will be
emitted instead of a `bs_match` instruction:

    {test,bs_match_string,{f,20},[{y,2},8,{string,<<0>>}]}.

Fixes #9304
Consider this function:

    do_try(F) ->
        try
            F()
        catch
            C:R:Stk ->
                {'EXIT',C,R,Stk}
        end.

The compiler in Erlang/OTP 27 generates the following code for the
body of the function:

        {allocate,3,1}.    % Allocate three Y registers.
        {init_yregs,{list,[{y,0},{y,1}]}}.
        {'try',{y,2},{f,3}}.
        {call_fun,0}.
        {try_end,{y,2}}.
        {deallocate,3}.
        return.
      {label,3}.
        {try_case,{y,2}}.
        %% {y,2} is free, but is not being reused.
        {move,{x,1},{y,0}}.
        {move,{x,0},{y,1}}.
        {move,{x,2},{x,0}}.
        build_stacktrace.
        {test_heap,5,1}.
        {put_tuple2,{x,0},{list,[{atom,'EXIT'},{y,1},{y,0},{x,0}]}}.
        {deallocate,3}.
        return.

Note that a stackframe with three Y registers will be allocated. It
would be sufficient to allocate two Y registers if `{y,2}` could be
reused following the `{try_case,{y,2}}` instruction.

This commit extends an existing optimization to ensure that `{y,2}`
can be reused, resulting in the following code:

        {allocate,2,1}.   % Allocate two Y registers.
        {init_yregs,{list,[{y,0}]}}.
        {'try',{y,1},{f,3}}.
        {line,[{location,"t.erl",7}]}.
        {call_fun,0}.
        {try_end,{y,1}}.
        {deallocate,2}.
        return.
      {label,3}.
        {try_case,{y,1}}.
        {move,{x,0},{y,0}}.
        {move,{x,1},{y,1}}.   % Reusing {y,1}.
        {move,{x,2},{x,0}}.
        build_stacktrace.
        {test_heap,5,1}.
        {put_tuple2,{x,0},{list,[{atom,'EXIT'},{y,0},{y,1},{x,0}]}}.
        {deallocate,2}.
        return.

This optimization improves the code in more than 200 modules out of
the sample of about 1000 modules compiled by `./scripts/diffable`.
We assert that if we are in a literal range, the literal tag
should also be set. This will only be true in the debug build,
but as asserts are only active in debug builds that is fine.
* lukas/doc/update_ex_doc:
  Updated ex_doc version to v0.37.0-rc.2
  otp: Fix redirect js scripts
erts: Use `processes_iterator/0, processes_next/1`
…OTP-19448

Fix unsafe code generation for binary matching
* bjorn/compiler/beam_validator/OTP-19449:
  beam_validator: Catch insufficient ensure_at_least/ensure_exactly
* maint:
  beam_validator: Catch insufficient ensure_at_least/ensure_exactly
…ord/OTP-19315

kernel: Add basic password support for noshell raw
…nto maint

* lukas/erts/fix-persistent-term-literal-tag/OTP-19458:
  erts: Mark error in erl.c as noreturn
  erts: Strengthen literal tag assert
  erts: Make sure to tag orig with literal ptr
Improve register allocation for try ... catch constructs
@pull pull bot added the ⤵️ pull label Jan 29, 2025
@pull pull bot merged commit 0411d8a into garazdawi:master Jan 29, 2025
Copy link

sourcery-ai bot commented Jan 29, 2025

Reviewer's Guide by Sourcery

This pull request introduces several changes to the bitstring matching functionality in the compiler, including new instructions and optimizations. It also fixes a bug in the literal area collector and adds a new function to the io module.

Sequence diagram for optimized bitstring matching

sequenceDiagram
    participant C as Compiler
    participant V as Validator
    participant R as Runtime

    C->>V: Translate bs_match to bs_ensured_* instructions
    Note over C,V: When length check is already done
    V->>V: Validate bs_match commands
    V->>V: Track ensured bits
    V->>R: Generate optimized code
    Note over R: Execute bs_ensured_* instructions
    Note over R: Skip redundant length checks
Loading

Class diagram for updated bitstring matching instructions

classDiagram
    class bs_match_instructions {
        bs_get
        bs_ensured_get
        bs_skip
        bs_ensured_skip
        bs_match_string
        bs_ensured_match_string
    }
    note for bs_match_instructions "New bs_ensured_* variants
don't check bitstring length"

    class bs_match_command {
        ensure_at_least(Size, Unit)
        ensure_exactly(Size)
        =:=(Bits, Value)
        skip(Size)
        get_tail(Live, Unit, Dst)
    }

    bs_match_instructions --> bs_match_command: translates to
Loading

State diagram for bitstring matching optimization

stateDiagram-v2
    [*] --> Initial
    Initial --> LengthChecked: bs_ensure
    LengthChecked --> Matching: bs_ensured_* instructions
    Initial --> Matching: bs_* instructions
    Matching --> [*]: Success
    Matching --> Failed: Match error
    note right of LengthChecked: Length check done once
    note right of Matching: Optimized path skips
redundant length checks
Loading

File-Level Changes

Change Details Files
Introduces bs_ensured_* instructions for bitstring matching.
  • Adds bs_ensured_get, bs_ensured_skip, and bs_ensured_match_string instructions.
  • Rewrites bs_skip to bs_ensured_skip when the bitstring length is ensured.
  • Rewrites bs_match_string to bs_ensured_match_string when the bitstring length is ensured and the string is small enough.
  • Modifies the code generator to handle the new instructions.
  • Modifies the validator to handle the new instructions.
  • Removes bs_checked_skip and bs_checked_get instructions.
lib/compiler/src/beam_ssa_pre_codegen.erl
lib/compiler/src/beam_ssa_codegen.erl
lib/compiler/src/beam_ssa.erl
lib/compiler/src/beam_validator.erl
Optimizes register usage in copy_retval_is and copy_landingpad.
  • Introduces a new copy_landingpad function to optimize register usage in try/catch blocks.
  • Modifies copy_retval_is to use copy_landingpad.
lib/compiler/src/beam_ssa_pre_codegen.erl
Fixes a bug in the literal area collector.
  • Modifies the literal area collector to correctly handle sub-binaries of literals.
  • Modifies the literal tagging logic to handle sub-binaries correctly.
erts/preloaded/src/erts_literal_area_collector.erl
erts/emulator/beam/erl_term.c
Adds a get_password function to the io module.
  • Adds a get_password function to the io module that reads a password without echoing it to the terminal.
  • Modifies the group module to handle the new get_password request.
  • Modifies the ssh module to use the new get_password function.
  • Modifies the shell module to document the new noshell/raw mode.
  • Adds a test case for the new get_password function.
lib/stdlib/src/io.erl
lib/kernel/src/group.erl
lib/ssh/src/ssh_io.erl
lib/stdlib/src/shell.erl
lib/kernel/test/interactive_shell_SUITE.erl
Adds a test case for bitstring matching.
  • Adds a test case for bitstring matching that exposed a bug in the compiler.
lib/compiler/test/bs_match_SUITE.erl
Adds a test case for the beam validator.
  • Adds a test case for the beam validator that checks that operations are preceded by ensure_at_least / ensure_exactly.
lib/compiler/test/beam_validator_SUITE.erl
Fixes a bug in the persistent term module.
  • Adds a test case that exposed a bug in the persistent term module related to garbage collection of binaries.
erts/emulator/test/persistent_term_SUITE.erl
Improves process iteration in erts_ptab_processes_next.
  • Improves process iteration in erts_ptab_processes_next to avoid unnecessary heap allocations.
erts/emulator/beam/erl_ptab.c
Improves process iteration in erts_code_purger.
  • Improves process iteration in erts_code_purger to use erlang:processes_iterator().
erts/preloaded/src/erts_code_purger.erl
Improves process iteration in erts_literal_area_collector.
  • Improves process iteration in erts_literal_area_collector to use erlang:processes_iterator().
erts/preloaded/src/erts_literal_area_collector.erl
Improves process killing in init.erl.
  • Improves process killing in init.erl to use erlang:processes_iterator().
erts/preloaded/src/init.erl
Updates documentation and build files.
  • Updates documentation to include the new get_password function.
  • Updates build files to include the new documentation.
  • Updates the otp_check_html_links.exs script to use a specific commit of floki.
system/doc/top/docs.exs
system/doc/top/Makefile
scripts/otp_check_html_links.exs
make/ex_doc.sha1sum
make/ex_doc.sha256sum
make/ex_doc_link
make/ex_doc_vsn

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants