That may be partially to blame, but depending on your implementation (was this x32 or actual compressed pointers?) the overhead of “decompressing” each pointer dereference may have been a significant factor. For null-safe languages like Java or JavaScript you already have null checks and may have GC barrier checks on most dereferences, so the extra costs are already expected- but adding a shift and/or constant add to each access is going to be a more noticeable cost compared to plain accesses in native code.