[Vm-dev] VMBIGENDIAN question

Eliot Miranda eliot.miranda at gmail.com
Sat Mar 23 23:22:11 UTC 2013


On Fri, Mar 22, 2013 at 6:18 PM, <btc at openinworld.com> wrote:

>
> **
> John McIntosh wrote:
>
>  ------------------------------
>
> Likely this relates to a problem with LLVM and it playing more by the rules.
>
> (a) lack of prototypes makes LLVM generate bad code.
>
> Fix that then you can compile and run VM with -O0
> And run a bit with -O2 -Os
>
>
>
>   Earlier note sent to a few folks, but let's widen the audience.
>
>
>  Ok, I'm driven to compile an Old VM for IOS with LLVM, as you know
> this broken, still I'm millions of bytecodes in now...
>
> What I found is the lack of prototypes would cause LLVM on anything
> but -O0 to throw an ARM exception at the first longAtPointer
> Once I added prototypes then well we run millions of bytecode. Right
> up to the point we die attempting to print the friggen Time on the
> Transcript.
>
>
>  One day I will have time to actually dive into the VM source, but for now
> I only lurk.  Just curious though...
> Given that the codebase is decades old (true?) is there a chance there is
> a mix of:
> * K&R function declarations
> * ANSI-C function prototypes
> * K&R function declarations
> * ANSI-C function declarations
>

No.  Good thought though.  I suspect Nicolas is right.  We are cavalier
with integral types.


>
> see p209 "Where Protoypes Break Down"
> http://files.openinworld.com/misc/ExpertCProgramming-declarations.pdf
>
> cheers -ben
>
>  As it's one in the morning I'll throw it out for clues and maybe
> someone wants to fight with it, give clues, throw beer or heckle from
> the sidelines...
>
> I know that the  commonAt:  is given an invalid or zero index value,
> so the digitValue: throws a failure of at: not working... Er then in
> my image we run off to print the crash report, with time stamp....
> repeat until you run out of 20MB of memory.
>
> PS other fun notes because the endian and mmap memory offset is the
> same between my mac and my iOS device and the saved image then on
> startup I don't have to
> swizzle the bytes, or alter the offset, so the VM startup code isn't
> given a chance to stomp on anything. On an iPhone 3G this cut many
> seconds off the VM startup.
>
> Add handy fprintf on failure to commonAt:
> sqInt commonAt(sqInt stringy) {
> register struct foo * foo = &fum;
>     sqInt atIx;
>     sqInt rcvr;
>     sqInt result;
>     sqInt index;
>     sqInt sp;
>     sqInt sp1;
>
>
>         /* Sets successFlag */
>
>         index = positive32BitValueOf(longAt(foo->stackPointer));
>         rcvr = longAt(foo->stackPointer - (1 * BytesPerWord));
>         if (!(foo->successFlag && (!((rcvr & 1))))) {
>                 /* begin primitiveFail */
>                 foo->successFlag = 0;
>
>
>           fprintf(stderr,"\n failure for %u given %i",rcvr,index);
>
>
>    //Happy puppy when -O0   not happy with -O1 (or others)
>                 return null;
>         }
>
>
>
>
> so given
>
> sqInt primitiveSecondsClock(void) {
> register struct foo * foo = &fum;
>     sqInt oop;
>     sqInt sp;
>
>         /* begin pop:thenPush: */
>         oop = positive32BitIntegerFor(ioSeconds());
>         longAtput(sp = foo->stackPointer - ((1 - 1) * BytesPerWord), oop);
>         foo->stackPointer = sp;
> }
>
> *seems to work as the positive32BitIntegerFor feeds back something I
> push back to positive32BitValueOf and print all the little pieces...
>
> sqInt ->D2F68C2F<- Bytes 2F 8C F6 D2   integer value 3539373103  value
> from ioSeconds going into positive 3539373103 push as 3539373103<>
>
> On Fri, Mar 22, 2013 at 5:25 PM, Nicolas Cellier <nicolas.cellier.aka.nice at gmail.com> wrote:
>
>
>
>  2013/3/22 Bert Freudenberg <bert at freudenbergs.de> <bert at freudenbergs.de>:
>
>
>  On 2013-03-22, at 05:43, David T. Lewis <lewis at mail.msen.com> <lewis at mail.msen.com> wrote:
>
>
>
>  "It ain't what you don't know that gets you into trouble. It's what you
>
>
>  know for sure that just ain't so."
>
>
>  -- Mark Twain
>
> An interpreter VM compiled with the normal C macros in sqMemoryAccess.h
>
>
>  (for "performance"):
>
>
>  0 tinyBenchmarks. '417277913 bytecodes/sec; 14395420 sends/sec'
> 0 tinyBenchmarks. '414239482 bytecodes/sec; 14646769 sends/sec'
> 0 tinyBenchmarks. '417277913 bytecodes/sec; 14406658 sends/sec'
>
> The same interpreter VM with C macros replaced by Smalltalk slang
>
>
>  (class MemoryAccess):
>
>
>  0 tinyBenchmarks. '455111111 bytecodes/sec; 14217973 sends/sec'
> 0 tinyBenchmarks. '451897616 bytecodes/sec; 14485815 sends/sec'
> 0 tinyBenchmarks. '453900709 bytecodes/sec; 14497194 sends/sec'
>
> Dave
>
>
>  That is ... unexpected :)
>
>
>
>  Well, that's almost the same code both in MemoryAcess and
> sqMemoryAccess.h right?
> Maybe a bit different if you define USE_INLINE_MEMORY_ACCESSORS:
>
>   static inline sqInt byteAt(sqInt oop)                         { return
> byteAtPointer(pointerForOop(oop)); }
>   static inline sqInt byteAtPointer(char *ptr)                  { return
> (sqInt)(*((unsigned char *)ptr)); }
>   static inline char *pointerForOop(usqInt oop)                 { return
> sqMemoryBase + oop; }
>
> Though I do not well see why it would not inline such simple piece,
> gcc has a license to not honour the inline request.
> On the other side MemoryAccess will always inline as we asked the code
> generator to (self inline: true)
> It would be worth verifying if one of the static function is generated
> in the executable (with nm -a or something).
>
> But I also see other subtle differences like this:
>
> intAtPointer: ptr put: val
>         self inline: true.
>         self var: #ptr type: 'char *'.
>         self var: #val type: 'unsigned int'.
>         ^ self cCoerce:
>                         ((self cCoerce: ptr to: 'unsigned int *')
>                                 at: 0
>                                 put: val)
>                 to: 'sqInt'
>
> while the header tells
>   static inline sqInt intAtPointerput(char *ptr, int val)       { return
> (sqInt)(*((unsigned int *)ptr)= (int)val); }
>
> OK, you might think that casting int->unsigned int is no-op on
> 2-complement machines.
> But it's a distraction, we must omit the intermediate (*(unsigned int
> *)) and just consider that the return value is assigned with the
> parameter val.
> So the header just copy an int->int, but MemoryAccess uses the
> opposite cast unsigned int->int
> It's also a no-op except that:
> - the cast can overflow, which would be UB.
> - gcc has a licence to presume you don't rely on UB and thus can
> further consider the returned int is always >= 0
> That assertion cannot be done in the case of sqMemoryAccess.h
>
> So all I see here has nothing to do with premature optimization.
> It has to do with lack of understanding of the modern C standards, and
> the absolute casualness attitude we take with signed and unsigned
> types.
>
> Nicolas
>
>
>
>  But it again shows the importance of the 3rd rule of Optimization.http://c2.com/cgi/wiki?RulesOfOptimization
>
> - Bert -
>
>
>
>
>
>


-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20130323/479ff21f/attachment.htm


More information about the Vm-dev mailing list