I now have a reduced test case. Ian could you take a look and say whether this code looks OK to you? -- Vyacheslav Egorov
#include <stdint.h> #include <cstdio> #include <cstring> #include <cstdlib> typedef uint8_t byte; typedef byte* Address; static const int kHeapObjectTag = 1; class Object { }; class Context : public Object { public: static const int kSize = 40; }; class GlobalObject : public Object { public: #define FIELD_ADDR(obj, offset) \ (reinterpret_cast<Address>(obj) - kHeapObjectTag + (offset)) #define WRITE_FIELD(obj, offset, value) \ (*reinterpret_cast<Object**>(FIELD_ADDR(obj, offset)) = (value)) #define READ_FIELD(obj, offset) \ (*reinterpret_cast<Object**>(FIELD_ADDR(obj, offset))) void set_global_context (Context* ctx) { WRITE_FIELD(this, kGlobalContextOffset, ctx); } Context* get_global_context () { return reinterpret_cast<Context*>(READ_FIELD(this, kGlobalContextOffset)); } static const int kGlobalContextOffset = 32; static const int kSize = 2*kGlobalContextOffset; }; template <class Dest, class Source> inline Dest BitCast(const Source& source) { // Compile time assertion: sizeof(Dest) == sizeof(Source) // A compile error here means your Dest and Source have different sizes. typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; Dest dest; memcpy(&dest, &source, sizeof(dest)); return dest; } template <class Dest, class Source> inline Dest BitCast(Source* source) { return BitCast<Dest>(reinterpret_cast<uintptr_t>(source)); } template<typename T> class Handle { public: explicit Handle(T** location) : location_(location) {} T* operator -> () const { return operator*(); } T* operator * () const { return *BitCast<T**>(location_); } private: T** location_; }; __attribute__((noinline)) void set_global_context(Handle<GlobalObject> bar, Handle<Context> ctx) { bar->set_global_context(*ctx); } template<typename T> inline T* Allocate() { Address addr = (Address)malloc(T::kSize); return (T*) (addr + kHeapObjectTag); } int main(int argc, char* argv[]) { Context* global_context = Allocate<Context>(); GlobalObject* global_object = Allocate<GlobalObject>(); Handle<Context> h_global_context (&global_context); Handle<GlobalObject> h_global_object (&global_object); printf("global_context = %p, global_object->get_global_context() = %p\n", (void*)*h_global_context, (void*)h_global_object->get_global_context()); set_global_context(h_global_object, h_global_context); printf("global_context = %p, global_object->get_global_context() = %p\n", (void*)*h_global_context, (void*)h_global_object->get_global_context()); return 0; }