[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Implementing a tag pointer class

alan

10/29/2008 2:53:00 PM

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.num & 0x7);
}
}

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

static inline int as_smallint(Object 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
5 Answers

Victor Bazarov

10/29/2008 3:02:00 PM

0

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

anon

10/29/2008 4:57:00 PM

0

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*) ?

alan

10/29/2008 9:50:00 PM

0

On Oct 29, 11:01 pm, Victor Bazarov <v.Abaza...@comAcast.net> 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();
>
> 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

alan

10/29/2008 9:52:00 PM

0

On Oct 29, 11:01 pm, Victor Bazarov <v.Abaza...@comAcast.net> 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();
>
> 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

alan

10/29/2008 9:58:00 PM

0

On Oct 30, 12:56 am, anon <a...@no.invalid> wrote:
> 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_cast at the time.