1. 58
  1. 9

    Well, that was worth reading.

    I’d really like to see some benchmarks that compare the overall system performance of monomorphism vs polymorphism for generics. There are so many confounding factors (“inlining is the gateway optimization” after all), so I’m not sure how you’d make it fair or what it would even mean.

    1. 5

      C++‘s standard library isn’t very useful to dynamically link to

      Well, there’s 814 Kb of something in /usr/lib/libc++.so.1 on my system..

      C++ can be dynamically linked and used in an ABI-stable way! It’s just that it ends up looking a lot more like a C interface due to the limitations

      In practice, it looks a lot more like “you’ve updated Boost? You have to rebuild LibreOffice now, even though 90% of Boost is templates, your LibreOffice links to libboost_locale.so and libboost_date_time.so and uses maybe a couple monomorphic functions from there” :)

      btw, D supports dynamic linking in the same way.

      1. 4

        D supports dynamic linking in the same way

        In the same way as rust? Or c? Or c++?

        1. 3

          C++‘s standard library isn’t very useful to dynamically link to

          Well, there’s 814 Kb of something in /usr/lib/libc++.so.1 on my system..

          I think your next comment really got at what they were trying to say: because so much of modern C++ is templates-only, and templates-only code has no ABI/isn’t something you can put in a dynamic library, you’re in practice getting very few benefits from dynamic linking—this despite C++ having a formalized ABI on at least AMD64 these days. (Well, two of them, because Windows has a different calling system than literally everything else. (Not maliciously; there are good reasons for Windows to be the odd duck out here that largely have to do with them standardizing a subset of the C++ ABI for COM on x86 in ways that were useful for them to preserve for porting reasons, but that no one else needed to worry about. But it puts us in the same spot of two ABIs, regardless.))

          On your D comment, are you saying it’s the same as C++ or as Swift or as Rust?

          1. 2

            On your D comment, are you saying it’s the same as C++ or as Swift or as Rust?

            C++ of course, the whole comment was about C++.

            1. 2

              Could you please share some document/link/more info about why MS has chosen a different ABI than the rest of the (small, but still) world? I’m genuinely interested in this.

              1. 6

                It’s literally entirely Microsoft wanting to maintain binary compatibility with x86 binaries, and Unixes not caring.

                Looking purely at how register are used, for example: the Windows fastcall convention, which is dominant for later Win32 apps, uses ECX and EDX for argument passing, and otherwise spills to the stack. While Microsoft appreciated that adding some registers for arguments would be good, they wanted to do so conservatively, so they left the usage of the named registers as-was and only added R8 and R9 as extra argument parameters.

                Unixes, by contrast, generally do not care about binary backwards compatibility. In that world, it’s fine to re-purpose named registers, and passing more arguments by registers is better, so Unixes generally just developed their ABI fresh in the way best for AMD64 and AMD64 opcode patterns. That results in values going in RDI, RSI, RDX, RCX, R8, and R9.

                There are lots of other differences, but they keep coming back, again and again, to making it much easier for Windows to run 32- and 64-bit apps side-by-side. This Stack Overflow answer honestly does a great job getting into the weeds if you’re curious.