4 ms·
I wonder if you could apply a simpler version of this to ordinary C/C++ programs? If you allocate a chunk on the heap with 8-byte alignment, then you can throw
by timmaxw 4y ago
I wonder if you could apply a simpler version of this to ordinary C/C++ programs? If you allocate a chunk on the heap with 8-byte alignment, then you can throw away the lowest 3 bits of precision, and then you can address 32GB with a 32-bit pointer. You'd need the cooperation of the memory allocator to ensure it gives you addresses in the first 32GB of address space, and it might interfere with things like ASLR, but it doesn't seem impossible.
Something like this in C++:
template<class T>
class CompressedPointer {
public:
T &operator*() const {
return *static_cast<T *>((uint64_t)ptr << 3);
}
/* It's not safe to construct a CompressedPointer<T> from an arbitrary T*;
you probably want to malloc and construct via the CompressedPointer itself */
template<Args...>
static CompressedPointer malloc(Args...) {
/* allocate 8-byte aligned sizeof(T) in first 32GB, then construct T in it */
}
private:
uint32_t ptr;
}
[Edit] Extra crazy idea: Take an existing large C++ codebase. For each struct T in the codebase, use static analysis to determine if T is ever stack-allocated (or otherwise incompatible with CompressedPointer). If not, automatically rewrite all "T*" to "CompressedPointer<T>" and all "new T(...)" with "CompressedPointer<T>::malloc(...)". I suspect this would work for 90% of the heap allocations in a typical C++ codebase...
- bremac 4y ago> If you allocate a chunk on the heap with 8-byte alignment, then you can throw away the lowest 3 bits of precision, and then you can address 32GB with a 32-bit pointer. This part is totally doable, and in fact it's one of the pointer compression modes built into the JVM: https://shipilev.net/jvm/anatomy-quarks/23-compressed-references/ https://shipilev.net/jvm/anatomy-quarks/23-compressed-refere... For C++, it's a really interesting thought experiment, but in practice there are a few rough edges: 1. Your debugging tools will probably struggle to interpret compressed pointers. 2. You'll need to roll your own containers too. Otherwise, vectors, strings, maps, smart pointers, etc. will still use 64-bit pointers. In my experience, containers account for most pointers in a modern C++ code base. 3. _Technically_, the representation of null pointers is implementation-defined, so truncating to 32 bits and then zero-extending is not portable: it could convert a null pointer to a non-null pointer. In practice it doesn't matter though, since every modern target uses a zero bit pattern for null pointers.
- fweimer 4y agoICC has an option that is documented as: auto-p32 Instructs the compiler to analyze the program to determine if there are 64-bit pointers that can be safely shrunk to 32-bit pointers. I don't know how good it is in practice, having never tried it. GCC has -mx32, but that changes ABI completely, you have to recompile everything, and you need a new kernel with another system call table (which your favorite kernel might have disabled).
- chubot 4y agoI think this is a compelling idea, and I did some experiments with it a few years ago, but I don't think it works. I think you have to rewrite all your code in C++ to get smaller pointers, e.g. see my comments on Zig and Sorbet (C++) in this thread. Also some on this wiki page: https://github.com/oilshell/oil/wiki/Compact-AST-Representation https://github.com/oilshell/oil/wiki/Compact-AST-Representat... I don't think there is any way to retrofit existing software with this technique. In addition to the issues you mentioned, you would have to deal with pointer arithmetic (interior pointers), Base* and Derived* semantics (covariance, arrays, templates, etc.), composition with other pointer-like types, etc. Not to mention dealing with external code that doesn't traffic in compressed pointers