3 ms·
Jesus Fucking Christ, now we're exploiting undefined behaviour to remove one compare instruction? You don't even need the jump, just use a conditional move. Jus
by anon4 11y ago
Jesus Fucking Christ, now we're exploiting undefined behaviour to remove one compare instruction? You don't even need the jump, just use a conditional move. Just..
test rax, rax
add rax, $offset
cmovz rax, 0
Or keep the damn jump and expect the cpu to profile it correctly.
Sorry for sounding angry, but this kind of thing isn't what makes my programs faster, this kind of thing is what makes it harder to write correct programs.
Edit: clang does exactly this at -O1: https://godbolt.org/g/o6gh0M https://godbolt.org/g/o6gh0M
- redmorphium 11y agoA small nitpick, your code is incorrect because the add operation will set ZF.
- catnaroek 11y agoThat you need to invoke undefined behavior to remove the compare instruction is only the symptom. The actual disease is nullable pointers themselves, which create the need for a compare instruction at every pointer dereference in the first place.
- titzer 11y agoNo. Java has nullable pointers and almost all JVMs implement them with a pointer to address 0 and unmap the first couple of pages of the address space. That will cause a fault, leading to a signal, which is then handled to materialize and throw the exception. No compare. Just naked loads/stores with fixed offsets. The disease is multiple (implementation) inheritance.
- catnaroek 11y ago> No. Java has nullable pointers and almost all JVMs implement them with a pointer to address 0 and unmap the first couple of pages of the address space. This is just plain ugly. Why should the normal operation of a program written in a high-level language trigger page faults? But, leaving aesthetic concerns aside, I'm not even sure it works. How do you guarantee that the OS won't give you back the same pages you unmapped when you try to map new pages (say, to grow the heap)?
- titzer 11y ago> This is just plain ugly. Yeah. Unfortunately the only really efficient protection mechanisms that modern processors have is virtual memory. C++ programs generally unmap the first few pages for exactly the same reason; to catch nullptr derefs. > Why should the normal operation of a program written in a high-level language trigger page faults? NullPointerExceptions are not considered normal operation. They are safety violations that have a controlled, well-defined semantics. BTW page faults happen all the time; the OS transparently handles them and maps in new pages as necessary. The problem you are referring occurs when a page fault happens and the OS knows there is no mapping for those addresses. > How do you guarantee that the OS won't give you back the same pages you unmapped Because the mapping is for an address space range (e.g. 0-N), and the OS does not overlap new request with existing mappings unless specified in the request.
- catnaroek 11y ago> and the OS does not overlap new request with existing mappings unless specified in the request. Ah, so by “unmap”, you actually something like POSIX's `mprotect()`, rather than `munmap()`?
- titzer 11y agoSorry, yes. You can do this just through segment declarations in both ELF and MachO binary formats, to prevent anything getting accidentally mapped there before startup.
- catnaroek 11y ago> NullPointerExceptions are not considered normal operation. They are safety violations that have a controlled, well-defined semantics. I'm not really buying this. My definition of “normal operation” is very simple: Everything but FFI calls. Normal operation in a safe language is supposed to be safe.
- the8472 11y agoGarbage collectors (and various other parts of the JVM) use similar tricks to coordinate threads without using memory barriers. The compiler just inserts TEST instructions to some fixed memory address in strategic places in the code. When the garbage collector needs to run it protects the page and waits until all threads have segfaulted and transferred control to the collector.