This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: dict_contains first argument declared register, and shouldn't be
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Arfrever, Mark.Shannon, amaury.forgeotdarc, ezio.melotti, gvanrossum, larry, mark.dickinson, pitrou, rhettinger, serhiy.storchaka, skrah, terry.reedy
Priority: low Keywords:

Created on 2013-05-29 01:49 by larry, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (11)
msg190263 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2013-05-29 01:49
I'm monkeying around with CPython trunk, and just noticed the following declaration in Objects/dictobject.c:

    static PyObject *
    dict_contains(register PyDictObject *mp, PyObject *key)

Although dict_contains is a static method, it's cast to PyCFunction and stored in the methoddef array for the dict class.  Therefore it must be callable when cast to a PyCFunction--indeed, that's the only way it is ever called.

Although the "register" keyword is at best a vague hope, surely it'd be bad news if our wish was granted?  The first argument to the PyCFunction typedef is *not* declared register.  So if the caller pushed the first argument on the stack, and dict_contains went looking for its first argument in a register... kablooey.

Surely we must remove the "register" keyword to this function, and similarly clean up all other functions ever cast to PyCFunction or PyCFunctionWithKeywords.

The "register" keyword isn't just a euphemism for "I want this code to go faster" -ly yours,
msg190289 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-05-29 11:22
I would recommend suppressing all "register" keywords from our C source files. It shouldn't make any difference these days.
msg190327 - (view) Author: Mark Shannon (Mark.Shannon) * (Python committer) Date: 2013-05-29 20:36
The register qualifier on the parameter does not alter the calling convention, it determines the storage class of the parameter variable within the function.

Having said that I am all in favour in removing any and all "register" declarations.
msg190328 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2013-05-29 20:43
> The register qualifier on the parameter does not alter the calling
> convention, it determines the storage class of the parameter variable
> within the function.

You assert that declaring a parameter as "register" instructs the compiler that callers should pass in the argument on the stack, but the function should then copy it to a register?  Can you cite a reference?

(I admit in advance I can't cite a reference for my assertion that it asks to pass the argument in a register.  And we all know the "register" keyword is more or less an unfunny joke to the compiler anyway.)
msg190369 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2013-05-30 15:56
I poked around in a draft of the next ANSI C standard dated April 12 2011.  They don't have much to say about the semantics of "register".  The definition is found in 6.7.1.6:

    A declaration of an identifier for an object with storage-class
    specifier "register" suggests that access to the object be as fast
    as possible.

In a footnote they say you can't take the address of something declared "register".

In 6.7.6.3.2 they explicitly allow using "register" as part of the specification of a function parameter.  However, in 6.9.2 they say "register" cannot appear as part of an external declaration, including those for functions.

6.9.2 is where I stake my claim.  If "register" is irrelevant to calling convention, then why would the C standard preclude using it in an external declaration?  If it had no effect on the call they wouldn't care.

Therefore, declaring a parameter as "register" affects its calling convention.  (Or, it would, if "register" actually did anything). Therefore casting a function from using "register" to not using "register" is a bug.  Therefore we shouldn't do it.
msg190374 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2013-05-30 18:03
+1 for removing all occurrences of "register".


Regarding the grammar, we have:

function-definition:
    declaration-specifiers-opt declarator declaration-list-opt compound-statement


So I think that "part of an external declaration" refers to the outermost
declaration-specifiers, not to some inner declaration-specifiers that are
part of the parameter-type-list. Otherwise it would also be forbidden to
use "register" in the compound-statement. ;)

Thus, IMO this is legal:

   a) int f (register int x) {return x;}


But this is not allowed:

   b) register int f (int x) {return x;}


As Mark said, a) does not alter the calling convention. It's just a request
to keep x in a register in the function body once the parameter passing is
done.
msg190375 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2013-05-30 18:29
> If "register" is irrelevant to calling convention, then why would the C
> standard preclude using it in an external declaration?

Maybe here "external" is the opposite of "static": "register" is OK in a single translation unit (where the calling convention does not really matter), but not allowed between multiple .c files (which register, anyway?)

+1 for removing it.
msg190379 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2013-05-30 19:18
Having re-read the spec a couple times, I am now thoroughly confused and don't know what to think.  Certainly I now believe I was previously misinterpreting aspects of the spec.

I still think removing "register" from the parameter lists of external functions is a good idea.  But smart people work on CPython, particularly on dictobject.c, so I find it easy to believe I'm missing something.  If having it there is actually a good idea I'd love to learn why!
msg190380 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-05-30 19:49
> +1 for removing all occurrences of "register".

Seconded.
msg190421 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-05-31 22:45
Guido, do you still believe in using 'register' in C code in general or in particular, for function arguments. Many of the uses in dictobject.c go back to your rev1256 and rev5396. The one that caught Larry's eye for dict_contains appears to be from the latter.

(Many other appearances are credited to Antoine as solipsis, though these may be from merges or something, and he has already said he thinks they could go.)
msg195095 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2013-08-13 19:14
Closed as this is a subset of #18722.
History
Date User Action Args
2022-04-11 14:57:46adminsetgithub: 62290
2013-08-13 19:14:43larrysetstatus: open -> closed
resolution: fixed
messages: + msg195095

stage: needs patch -> resolved
2013-05-31 22:45:22terry.reedysetnosy: + terry.reedy, gvanrossum
messages: + msg190421
2013-05-30 19:49:14mark.dickinsonsetmessages: + msg190380
2013-05-30 19:22:36ezio.melottisetnosy: + ezio.melotti
2013-05-30 19:18:25larrysetmessages: + msg190379
2013-05-30 18:29:11amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg190375
2013-05-30 18:03:34skrahsetnosy: + skrah
messages: + msg190374
2013-05-30 15:56:40larrysetmessages: + msg190369
2013-05-30 15:45:12Arfreversetnosy: + Arfrever
2013-05-29 20:43:22larrysetmessages: + msg190328
2013-05-29 20:36:40Mark.Shannonsetmessages: + msg190327
2013-05-29 20:24:34serhiy.storchakasetnosy: + mark.dickinson
2013-05-29 19:49:05pitrousetnosy: + serhiy.storchaka
2013-05-29 11:22:02pitrousetnosy: + pitrou
messages: + msg190289
2013-05-29 10:58:53larrysetnosy: + rhettinger, Mark.Shannon
2013-05-29 01:49:54larrycreate