GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-84436: Add static flag in PyLongObject's lv_tag by eduardo-elizondo · Pull Request #103403 · python/cpython

Conversation

@eduardo-elizondo

@eduardo-elizondo eduardo-elizondo commented Apr 10, 2023 •
edited by bedevere-bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

This adds a new SIGN_STATIC flag to PyLongObject's lv_tag which is used to determine if a given long object was statically allocated. It also reworks all the functions that use NON_SIZE_BITS to correctly account for this new flag.

  • Issue: Fixing Copy on Writes from reference counting and immortal objects #84436

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@eduardo-elizondo
Add static flag in PyLongObject's lv_tag
cc8484a
@bedevere-bot bedevere-bot mentioned this pull request Apr 10, 2023
Fixing Copy on Writes from reference counting and immortal objects #84436
Closed
@bedevere-bot bedevere-bot added the awaiting review label Apr 10, 2023
@eduardo-elizondo
Also correctly set the flags in SetDigit functions
2a23b75
@eduardo-elizondo

eduardo-elizondo commented Apr 10, 2023

Copy link
Copy Markdown
Contributor Author

@markshannon here's a couple of changes to the recently introduced lv_flag so that we can use it in: #19474

cc @ericsnowcurrently

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@eduardo-elizondo eduardo-elizondo mentioned this pull request Apr 10, 2023
gh-84436: Implement Immortal Objects #19474
Merged
@markshannon

markshannon commented Apr 11, 2023

Copy link
Copy Markdown
Member

Why do we need a static bit separate from the immortal bit?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@markshannon

markshannon commented Apr 11, 2023

Copy link
Copy Markdown
Member

Also, all the checks for sign and compactness need to be as close to single machine instructions as possible.
Adding the extra masking operations is something I would rather avoid for integer operations.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@eduardo-elizondo

eduardo-elizondo commented Apr 12, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

Why do we need a static bit separate from the immortal bit?

The specific place the static check is needed is here: https://github.com/python/cpython/pull/19474/files#r1156466281. It's to be compliant with the added condition of PEP683 to be able to reset the reference count if an immortal object's refcount reaches zero.

For types like None, Bool, this is easy, we just add a new tp_dealloc that resets the value. For interned strings, we check the intern state. For small ints we can either check if it's a small int or use a flag somewhere in the object, like this one.

In my opinion, it's much better to just do the 'expensive' small int check in tp_dealloc of the longobject but if we are already making a bit here available for "immortal longs" we might as well use it. But, I'm open to either option.

Adding the extra masking operations is something I would rather avoid for integer operations.

Assuming that we do want to have the static check, I think we might be able to make this cheaper if we make the immortal bit to be the least significant bit and the sign mask be the second and third least significant bits. I can draft up a change like this.

However, before I do that, I'd like to get some thoughts in perhaps dropping the immortal bit in long's lv_tag and just have the more expensive small int check in tp_dealloc. If that's the case then we can just close this PR (or change NON_SIZE_BITS to 2 and make it clear that we only need the sign mask at the moment).

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@markshannon

markshannon commented Apr 25, 2023

Copy link
Copy Markdown
Member

I think you misunderstood my (poorly worded) question.

Why do we need a static flag in addition to an immortal flag?
Immortality protects an object from reclamation, so provides the safety guarantees we need.

I worry that having two bits to check will degrade performance too much.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@markshannon

markshannon commented Jun 2, 2023

Copy link
Copy Markdown
Member

@eduardo-elizondo?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@eduardo-elizondo

eduardo-elizondo commented Jun 19, 2023

Copy link
Copy Markdown
Contributor Author

@markshannon Somehow I missed this message, my bad.

Why do we need a static flag in addition to an immortal flag?

Short answer is: we don't need it! We just need one flag. Having two flags will make things cleaner in code, but harder in reasoning. I tried to explain that above but probably didn't come across correctly. Let me explain a bit more.

The original reason I created this change was to address one of Guido's comment in the Immortal Objects PR. The comment was made on the newly added LongObject's tp_dealloc function. For context, the tp_dealloc was added so that we could restore long objects that would be decref'd to zero due to extension incompatibility. Given that we can't rely on the reference count, the way that we can check if this value has to be restored is by checking if the object is statically allocated which we assume by checking if it's a small int. This leads a rather long check:

static void long_dealloc(PyObject *self) {
    PyLongObject *pylong = (PyLongObject*)self;
    if (pylong && _PyLong_IsCompact(pylong)) {
        stwodigits ival = medium_value(pylong);
        if (IS_SMALL_INT(ival)) {
            PyLongObject *small_pylong = (PyLongObject *)get_small_int((sdigit)ival);
            if (pylong == small_pylong) {
                _Py_SetImmortal(self);
                return;
            }
        }
    }
    Py_TYPE(self)->tp_free(self);
}        

To this, Guido asked:

We now have room for an "immortal" bit in long int objects, since gh-102464. Should use that bit rather than checking the value. @markshannon for more info.

Thus, I created this PR to be able to use this immortal bit. All this PR does is that it exposes: _PyLong_IsStatic which we can then use in long_dealloc to do and make things cleaner:

static void long_dealloc(PyObject *self) {
    PyLongObject *pylong = (PyLongObject*)self;
    if (_PyLong_IsStatic(pylong)) {
      _Py_SetImmortal(self);
      return;
    }
    Py_TYPE(self)->tp_free(self);
}

Going back to your original question:

Why do we need a static flag in addition to an immortal flag?

If we have the static flag we can make things a lot cleaner but it's not needed, we can keep the longer checks and we can still guarantee correctness.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@eduardo-elizondo

eduardo-elizondo commented Jun 19, 2023 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor Author

@markshannon Given all of the above, I instead propose to completely drop the "immortality bit" in the long value tag bits since we don't need this signal.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@encukou

encukou commented Sep 13, 2024

Copy link
Copy Markdown
Member

It looks like this PR can be closed, is that right?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@eduardo-elizondo

eduardo-elizondo commented Sep 14, 2024

Copy link
Copy Markdown
Contributor Author

@encukou yeah, should be safe to close

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@encukou encukou closed this Sep 16, 2024
@chris-eibl chris-eibl mentioned this pull request Dec 7, 2024
gh-127119: Faster check for small ints in long_dealloc #127620
Merged
@eendebakpt eendebakpt mentioned this pull request Dec 7, 2024
gh-127119: Remove check on accidental deallocation of immortal objects for free-threaded build #127120
Closed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

awaiting review

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@eduardo-elizondo @markshannon @encukou @bedevere-bot
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.