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

Bert Freudenberg bert at freudenbergs.de
Sat Nov 13 11:45:42 UTC 2010


On 13.11.2010, at 03:17, Igor Stasenko wrote:

> 
> 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.

Yes but that wouldn't build because the linker would complain about FakeObjTable being declared globally more than once.

The better way would be to declare it external in the header. But then you need to declare it for real in a single C file. interp.c would be a good one. You should try that :)

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

I think so, too. It is significant.

> 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.

But that's no different from what we have now. We only access memory if necessary. There would not be fewer lookups if you have an object table.

- Bert -

> 
>> - 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