<p>Say I'm designing a virtual machine for a bytecode compiler/interpreter, using C as the implementation language. Some kind of “tagged” representation of values is simplest for this language, where every object carries information about what kind of object it is. Most objects are heap-allocated, so their usual representation at runtime is as a pointer.</p>
<p>A common way of doing tagged pointers is to allocate with a certain alignment so that some of the least significant bits don't matter; the tag goes in those bits. However, as I understand it, this is sketchy in C as far as portability is concerned (at least, <a href="https://www.lua.org/doc/jucs05.pdf#page=5" rel="nofollow noreferrer">that's why the Lua developers decided to use a normal union</a>).</p>
<p>Is there a reason not to use offsets from the start of my language's heap instead of “raw“ pointers? Tagging offsets is easy, and I have better control over how the tagging works (e.g. it can be in the high bits and it can be more than a few bits wide).</p>
<p>I feel that <code>heap[p]</code> isn't too much worse than <code>*p</code>; in fact, the intent is clearer in my opinion. Also fewer casts would be necessary.</p>
<p>One potential objection is that I'd have to do my own memory management. But my language already requires garbage collection, so that isn't too bad.</p>
<hr />
<p><a href="https://langdev.stackexchange.com/questions/3857/compressed-pointers-why-not-relative-rather-than-base-encoding">A recent question</a> is related to this one, but it does not really help me, since the question and the existing answer take the use of an offset instead of a pointer for granted. And that answer addresses the specific question about a modification of the offset representation.</p>
<p>I'd like to clarify here that I am not interested in pointer compression or saving space. I really don't care about “wasted” bits in a 64-bit word; I don't plan on significantly limiting the heap size available to programs in my language, so the larger the address space the better. <em>If</em> it turns out to be a problem I can consider compression mechanisms. For now I find it simpler to reserve some bits for tagging and let the rest of the word be an address or offset.</p>

<implementation><memory-management><pointers><virtual-machine>
Is there a downside to using offsets instead of raw pointers in a virtual machine?
CC BY-SA 4.0
2024-06-13T17:42:26.550Z
This is discussed at some length on the V8 dev blog: [Pointer Compression in V8](https://v8.dev/blog/pointer-compression).
kaya3
CC BY-SA 4.0
2024-06-13T20:08:46.660Z
Does this answer your question? [Compressed pointers, why not "relative" rather than "base" encoding?](https://langdev.stackexchange.com/questions/3857/compressed-pointers-why-not-relative-rather-than-base-encoding)
Greg Hewgill
CC BY-SA 4.0
2024-06-13T20:21:34.483Z
@GregHewgill It's closely related, but I'm not asking about compressed pointers and it focuses on an alteration to the basic “offset instead of pointer” scheme. I'm not really interested in trying to save space. *An* answer to that question might be an answer to this one, but the existing answer addresses primarily the specific concerns with relative offsets. However, the viability of offsets as a strategy is implicitly confirmed by the cited real-world uses, which is good to know.
texdr.aft
CC BY-SA 4.0
2024-06-14T05:52:42.197Z
Possibly a slight hit to performance.  Every memory reference will need an extra add to compute `heap+p` (in addition to masking off the tag bits of `p`, but that would apply to tagged raw pointers too).  But some machines have addressing modes where the add could come for free.  Also, you'll need to load the `heap` pointer frequently, and probably spend a register in most functions to keep it around.  The overall impact may or may not be significant; only profiling can tell you for sure.
Nate Eldredge
CC BY-SA 4.0
2024-06-14T23:03:36.487Z
@NateEldredge Definitely something to profile, although I feel that it could be partially mitigated by converting the offset to a pointer in "hot" areas of code, as long as I know that the pointer will remain valid (something that the C compiler may not be able to detect).
texdr.aft
CC BY-SA 4.0
2024-06-15T21:54:41.973Z
I think the "common" implementation is a legacy of implementations from decades ago, where the performance hit was more significant. The heap+offset mechanism is probably more acceptable today.
Barmar
CC BY-SA 4.0
2024-06-16T05:33:10.370Z
@Barmar You may very well be right. I think I'll just go for it. If any problems present themselves I'll post an answer with them. And if I do any profiling comparing raw pointers I'll post the results.
texdr.aft
# Is there a downside to using offsets instead of raw pointers in a virtual machine?
Posted by: username_0 on 2024-06-13
Say I'm designing a virtual machine for a bytecode compiler/interpreter, using C as the implementation language. Some kind of “tagged” representation of values is simplest for this language, where every object carries information about what kind of object it is. Most objects are heap-allocated, so their usual representation at runtime is as a pointer.

A common way of doing tagged pointers is to allocate with a certain alignment so that some of the least significant bits don't matter; the tag goes in those bits. However, as I understand it, this is sketchy in C as far as portability is concerned (at least, [that's why the Lua developers decided to use a normal union](https://www.lua.org/doc/jucs05.pdf#page=5)).

Is there a reason not to use offsets from the start of my language's heap instead of “raw“ pointers? Tagging offsets is easy, and I have better control over how the tagging works (e.g. it can be in the high bits and it can be more than a few bits wide).

I feel that `heap[p]` isn't too much worse than `*p`; in fact, the intent is clearer in my opinion. Also fewer casts would be necessary.

One potential objection is that I'd have to do my own memory management. But my language already requires garbage collection, so that isn't too bad.

---

[A recent question](https://langdev.stackexchange.com/questions/3857/compressed-pointers-why-not-relative-rather-than-base-encoding) is related to this one, but it does not really help me, since the question and the existing answer take the use of an offset instead of a pointer for granted. And that answer addresses the specific question about a modification of the offset representation.

I'd like to clarify here that I am not interested in pointer compression or saving space. I really don't care about “wasted” bits in a 64-bit word; I don't plan on significantly limiting the heap size available to programs in my language, so the larger the address space the better. *If* it turns out to be a problem I can consider compression mechanisms. For now I find it simpler to reserve some bits for tagging and let the rest of the word be an address or offset.
**Tags:** implementation memory-management pointers virtual-machine
> **Comments:**
> **username_1**: This is discussed at some length on the V8 dev blog: [Pointer Compression in V8](https://v8.dev/blog/pointer-compression).  
> **username_2**: Does this answer your question? [Compressed pointers, why not "relative" rather than "base" encoding?](https://langdev.stackexchange.com/questions/3857/compressed-pointers-why-not-relative-rather-than-base-encoding)  
> **username_0**: @GregHewgill It's closely related, but I'm not asking about compressed pointers and it focuses on an alteration to the basic “offset instead of pointer” scheme. I'm not really interested in trying to save space. *An* answer to that question might be an answer to this one, but the existing answer addresses primarily the specific concerns with relative offsets. However, the viability of offsets as a strategy is implicitly confirmed by the cited real-world uses, which is good to know.  
> **username_3**: Possibly a slight hit to performance.  Every memory reference will need an extra add to compute `heap+p` (in addition to masking off the tag bits of `p`, but that would apply to tagged raw pointers too).  But some machines have addressing modes where the add could come for free.  Also, you'll need to load the `heap` pointer frequently, and probably spend a register in most functions to keep it around.  The overall impact may or may not be significant; only profiling can tell you for sure.  
> **username_0**: @NateEldredge Definitely something to profile, although I feel that it could be partially mitigated by converting the offset to a pointer in "hot" areas of code, as long as I know that the pointer will remain valid (something that the C compiler may not be able to detect).  
> **username_4**: I think the "common" implementation is a legacy of implementations from decades ago, where the performance hit was more significant. The heap+offset mechanism is probably more acceptable today.  
> **username_0**: @Barmar You may very well be right. I think I'll just go for it. If any problems present themselves I'll post an answer with them. And if I do any profiling comparing raw pointers I'll post the results.  
---
## 0 answers
