Implementing a tag pointer class

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • alan

    #1

    Implementing a tag pointer class

    Hello world,

    I'm trying to implement a (hopefully portable!) tagged pointer class.
    Basically, I have my own allocator which will ensure alignment at 8-
    byte boundaries (where "byte" is "size of a char"), and allocates
    objects of type Generic. My tagged pointer class will support either
    Generic* (tag = 0b000) or small integers (tag=0b001) for now (in the
    future maybe add unicode chars, and/or Cons* etc.).

    A rough sketch of what I intend to do:

    class Generic;

    class Object {
    //public for now, will private this and make the
    //external functions friends later
    public:
    union types {
    void* ptr;
    int num;
    };
    types dat;

    Object(void* x) {
    // in case sizeof(void*) != sizeof(int)
    if(sizeof(int) sizeof(void*)) {
    dat.num = 0;
    }
    dat.ptr = x;
    }
    Object(int x) {
    if(sizeof(void* ) sizeof(int)) {
    dat.ptr = 0;
    }
    dat.num = x;
    }

    public:
    static inline Object smallint(int x) {
    x = (x << 3) + 0x1;
    return Object(x);
    }
    static inline Object obj(Generic* x) {
    if(x & 0x7) throw AlignmentError( );
    char* tmp = ((char*)(void*) x) + 0x0;
    return Object((void*) tmp);
    }
    };

    static inline char tag(Object x) {
    if(sizeof(void* ) sizeof(int)) {
    return (char)(((long) x.dat.ptr) & 0x7);
    } else {
    return (char)(x.dat.nu m & 0x7);
    }
    }

    static inline bool is_smallint(Obj ect x) {
    return tag(x) == 0x1;
    }
    static inline bool is_obj(Object x) {
    return tag(x) == 0x0;
    }

    static inline int as_smallint(Obj ect x) {
    if(!is_smallint (x)) throw TypeError();
    return x.dat.num >3;
    }

    static inline Generic* as_obj(Object x) {
    if(!is_obj(x)) throw TypeError();
    char* tmp = ((char*) x.dat.ptr) - 0x0;
    return (Generic*)(void *)tmp;
    }

    I've tested a version of the above code in a 32-bit x86 GNU/Linux
    system with gcc, but I wonder if it's portable, say to big-endian
    machines. Also, if optimizations are turned on (-O), it seems to
    generate code which approximately looks like what I would expect for
    explicit tagged pointers.

    I would prefer to use a class-based solution for cleanliness, but I'm
    concerned about using unions of potentially differently-sized objects,
    especially if the code ends up in a big-endian system with a different
    size for pointers and int.

    I could also try to dig out the class/type/etc. I saw once which is
    supposed to be an integral type that is the same size as the smallest
    integer that can fit a void*.

    Any pointers and suggestions, as well as analyses on how well this
    might perform on various systems/compilers are welcome.

    Sincerely,
    AmkG
  • Victor Bazarov

    #2
    Re: Implementing a tag pointer class

    alan wrote:
    I'm trying to implement a (hopefully portable!) tagged pointer class.
    [..]
    static inline Object obj(Generic* x) {
    if(x & 0x7) throw AlignmentError( );
    How does this compile? AFAIUI the binary operator & is not defined for
    pointer types...
    char* tmp = ((char*)(void*) x) + 0x0;
    What's the point of adding 0?
    return Object((void*) tmp);
    }
    };
    [..]
    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask

    Comment

    • anon

      #3
      Re: Implementing a tag pointer class

      Victor Bazarov wrote:
      alan wrote:
      >I'm trying to implement a (hopefully portable!) tagged pointer class.
      >[..]
      > static inline Object obj(Generic* x) {
      > if(x & 0x7) throw AlignmentError( );
      >
      Yeah, he might want to cast x to an int
      How does this compile? AFAIUI the binary operator & is not defined for
      pointer types...
      >
      > char* tmp = ((char*)(void*) x) + 0x0;
      >
      What's the point of adding 0?
      >
      To add: what's point in doing (char*)(void*) ?

      Comment

      • alan

        #4
        Re: Implementing a tag pointer class

        On Oct 29, 11:01 pm, Victor Bazarov <v.Abaza...@com Acast.netwrote:
        alan wrote:
        I'm trying to implement a (hopefully portable!) tagged pointer class.
        [..]
            static inline Object obj(Generic* x) {
                if(x & 0x7) throw AlignmentError( );
        >
        How does this compile?  AFAIUI the binary operator & is not defined for
        pointer types...
        Sorry, must have forgot to insert the cast at this point.
        >
                char* tmp = ((char*)(void*) x) + 0x0;
        >
        What's the point of adding 0?
        It's a pattern which I intend to copy for, say, types other than
        Generic*. Say Cons*. Or Sym*. The 0x0 is the tag. I can probably
        replace the 0x0 with something like:

        #define GENERIC_TAG 0x0
        #define CONS_TAG 0x2

        .....

        char* tmp = ((char*)(void*) x) + GENERIC_TAG;

        .....

        char* tmp = ((char*)(void*) x) + CONS_TAG;

        ....later on.
        >
                return Object((void*) tmp);
            }
        };
        [..]
        >
        V
        --
        Please remove capital 'A's when replying by e-mail
        I do not respond to top-posted replies, please don't ask

        Comment

        • alan

          #5
          Re: Implementing a tag pointer class

          On Oct 29, 11:01 pm, Victor Bazarov <v.Abaza...@com Acast.netwrote:
          alan wrote:
          I'm trying to implement a (hopefully portable!) tagged pointer class.
          [..]
              static inline Object obj(Generic* x) {
                  if(x & 0x7) throw AlignmentError( );
          >
          How does this compile?  AFAIUI the binary operator & is not defined for
          pointer types...
          Yes, I probably want to add a cast there.
          >
                  char* tmp = ((char*)(void*) x) + 0x0;
          >
          What's the point of adding 0?
          It's a pattern I want to copy for other types. Say Cons*. Or Sym*.

          I could do:

          #define GENERIC_TAG 0x0
          #define CONS_TAG 0x2

          ....

          char* tmp = ((char*)(void*) x) + GENERIC_TAG;

          ....

          char* tmp = ((char*)(void*) x) + CONS_TAG;
          >
                  return Object((void*) tmp);
              }
          };
          [..]
          >
          V
          --
          Please remove capital 'A's when replying by e-mail
          I do not respond to top-posted replies, please don't ask

          Comment

          • alan

            #6
            Re: Implementing a tag pointer class

            On Oct 30, 12:56 am, anon <a...@no.invali dwrote:
            Victor Bazarov wrote:
            alan wrote:
            I'm trying to implement a (hopefully portable!) tagged pointer class.
            [..]
                static inline Object obj(Generic* x) {
                    if(x & 0x7) throw AlignmentError( );
            >
            Yeah, he might want to cast x to an int
            >
            How does this compile?  AFAIUI the binary operator & is not defined for
            pointer types...
            >
                    char* tmp = ((char*)(void*) x) + 0x0;
            >
            What's the point of adding 0?
            >
            To add: what's point in doing (char*)(void*) ?
            Sorry, I wasn't aware of reinterpret_cas t at the time.

            Comment

            Working...