Skip to content

ILGenerator computation of maxstack is too conservative #63805

Description

@shonk-msft

Description

When generating a dynamic method both with many unconditional jumps, the ILGenerator's computation of maxstack is way to large - it adds the max stack of each basic block ending with an unconditional transfer (br, ret, throw, etc). If the generated code has many such bbs (eg, from the "then" clauses of if-then-else constructs) this sum can overflow 2^16. When it does, the maxstack recorded/used is the computed value mod 2^16. When that is less than the correct value, the JIT throws an InvalidProgramException.

For example, if there are 2^12 (4096) such blocks, each with a max stack of 2^4 (16), the computed maxstack is 2^16. That value mod 2^16 is zero. Since that is less than the actual (16 or more), the JIT will throw.

See the attached example code. This is written as a "test" that passes when the bug is present. The line enclosed by Assert.ThrowsException really should not throw.

ClrBugTests.cs.txt

Reproduction Steps

Build and run the unit test code above with .Net Core (verified with 3.1, and many later versions).

Expected behavior

The line marked with Assert.ThrowsException should not throw.

Actual behavior

An InvalidProgramException is thrown. Also, the computed max stack values (as written to console) are way too large. The actual max stack needed for this dynamic method is 4, and it doesn't depend on the number of basic blocks (the num parameter). The computed max stack values increase with num.

Regression?

No response

Known Workarounds

No good ones. This is blocking.

Configuration

No response

Other information

I'm working on a fix by fixing the computation in ILGenerator.cs.

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Jan 14, 2022
  2. steveharter commented on Feb 15, 2022

    @steveharter
    Contributor

    See also #62913 for discussion on how maxstack is (or can be) calculated.

  3. steveharter commented on Feb 15, 2022

    @steveharter
    Contributor

    I'm working on a fix by fixing the computation in ILGenerator.cs.

    @shonk-msft any update?

  4. removed
    untriagedNew issue has not been triaged by the area owner
    on Feb 15, 2022
  5. added this to the 7.0.0 milestone on Feb 15, 2022
  6. shonk-msft commented on May 13, 2022

    @shonk-msft
    Author

    Hi @steveharter, sorry for the delay. I implemented a fix long ago but haven't gotten around to submitting the PR. I'll be handing this off to a co-worker Monday who should be more responsive :-).

  7. added a commit that references this issue on Jun 7, 2022
    c0ba1b6
  8. ghost added
    in-prThere is an active PR which will close this issue when it is merged
    on Jun 7, 2022
  9. added a commit that references this issue on Jun 22, 2022
    f310367
  10. ghost removed
    in-prThere is an active PR which will close this issue when it is merged
    on Jun 22, 2022
  11. ghost locked as resolved and limited conversation to collaborators on Jul 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions