[Vm-dev] Direct object pointers vs indirect ones pros and cons

Igor Stasenko siguctua at gmail.com
Sat Nov 13 02:17:02 UTC 2010


On 12 November 2010 17:44, Bert Freudenberg <bert at freudenbergs.de> wrote:
>
> On 12.11.2010, at 14:41, Igor Stasenko wrote:
>
>> I'm inviting you to make own version of benchmark
>
> I don't think this can be realistically simulated inside Squeak. But possibly you could change the macros in sqMemoryAccess.h to fake an object table access?
>
> I just tried that. Using tinyBenchmarks, byte code performance drops to 63% and sends to 78%.
>
> Now declaring that variable volatile might be overkill as it prevents all caching, but I couldn't quite figure out a more realistic declaration.
>
you mean that non-volatile like:

int FakeObjTable = 0;

could be optimized away by compiler?
Well, since compiler compiles module by module (a separate C files),
if you remove 'static'
it can no longer able to optimize it to no-op, since it can't guess
what may happen to this variable in another object file,
since even if in one module there only a read-only access to it, some
other module could contain a code which modifying it.

So, i think this is the worst case performance slowdown. :)

If we take into account that to get object location you need to do
object table look only once,
and then any consequent read/write operations on object won't require
table lookup, this can be improved.
Consider, for example, that to read ivar, interpreter reads & checks
header, and only then ivar slot, so it should cost:
1 table lookup and 2 reads at object location.
instead of 2 table lookups + 2 reads at object location.

> - Bert -
>
> #else
> # ifndef FAKE_OBJ_TABLE
> # define FAKE_OBJ_TABLE
>  static volatile int FakeObjTable= 0;
> # define OBJTABLELOOKUP(oop) (oop + FakeObjTable)
> # endif
>  /* Use macros when static inline functions aren't efficient. */
> # define byteAtPointer(ptr)             ((sqInt)(*((unsigned char *)(OBJTABLELOOKUP(ptr)))))
> # define byteAtPointerput(ptr, val)     ((sqInt)(*((unsigned char *)(OBJTABLELOOKUP(ptr)))= (unsigned char)(val)))
> # define shortAtPointer(ptr)            ((sqInt)(*((short *)(OBJTABLELOOKUP(ptr)))))
> # define shortAtPointerput(ptr, val)    ((sqInt)(*((short *)(OBJTABLELOOKUP(ptr)))= (short)(val)))
> # define intAtPointer(ptr)              ((sqInt)(*((unsigned int *)(OBJTABLELOOKUP(ptr)))))
> # define intAtPointerput(ptr, val)      ((sqInt)(*((unsigned int *)(OBJTABLELOOKUP(ptr)))= (int)(val)))
> # define longAtPointer(ptr)             ((sqInt)(*((sqInt *)(OBJTABLELOOKUP(ptr)))))
> # define longAtPointerput(ptr, val)     ((sqInt)(*((sqInt *)(OBJTABLELOOKUP(ptr)))= (sqInt)(val)))
> # define oopAtPointer(ptr)              (sqInt)(*((sqInt *)OBJTABLELOOKUP(ptr)))
> # define oopAtPointerput(ptr, val)      (sqInt)(*((sqInt *)OBJTABLELOOKUP(ptr))= (sqInt)val)
> # define pointerForOop(oop)             ((char *)(sqMemoryBase + ((usqInt)(oop))))
> # define oopForPointer(ptr)             ((sqInt)(((char *)(ptr)) - (sqMemoryBase)))
> # define byteAt(oop)                    byteAtPointer(pointerForOop(oop))
> # define byteAtput(oop, val)            byteAtPointerput(pointerForOop(oop), (val))
> # define shortAt(oop)                   shortAtPointer(pointerForOop(oop))
> # define shortAtput(oop, val)           shortAtPointerput(pointerForOop(oop), (val))
> # define longAt(oop)                    longAtPointer(pointerForOop(oop))
> # define longAtput(oop, val)            longAtPointerput(pointerForOop(oop), (val))
> # define intAt(oop)                     intAtPointer(pointerForOop(oop))
> # define intAtput(oop, val)             intAtPointerput(pointerForOop(oop), (val))
> # define oopAt(oop)                     oopAtPointer(pointerForOop(oop))
> # define oopAtput(oop, val)             oopAtPointerput(pointerForOop(oop), (val))
> #endif
>
>



-- 
Best regards,
Igor Stasenko AKA sig.


More information about the Vm-dev mailing list