<br><br><div class="gmail_quote">On Fri, Mar 22, 2013 at 6:18 PM,  <span dir="ltr">&lt;<a href="mailto:btc@openinworld.com" target="_blank">btc@openinworld.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 <br><u></u>


  

<div bgcolor="#ffffff" text="#000000">
John McIntosh wrote:
<blockquote type="cite">
  <pre> </pre>
  <pre><hr size="4" width="90%">
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

  </pre>
  <blockquote type="cite">
    <pre> Earlier note sent to a few folks, but let&#39;s widen the audience.
    </pre>
  </blockquote>
  <pre>Ok, I&#39;m driven to compile an Old VM for IOS with LLVM, as you know
this broken, still I&#39;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.
  </pre>
</blockquote>
One day I will have time to actually dive into the VM source, but for
now I only lurk.  Just curious though...<br>
Given that the codebase is decades old (true?) is there a chance there
is a mix of:<br>
* K&amp;R function declarations <br>
* ANSI-C function prototypes <br>
* K&amp;R function declarations<br>
* ANSI-C function declarations<br></div></blockquote><div><br></div><div>No.  Good thought though.  I suspect Nicolas is right.  We are cavalier with integral types.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#ffffff" text="#000000">
<br>
see p209 &quot;Where Protoypes Break Down&quot; <br>
<a href="http://files.openinworld.com/misc/ExpertCProgramming-declarations.pdf" target="_blank">http://files.openinworld.com/misc/ExpertCProgramming-declarations.pdf</a><br>
<br>
cheers -ben<br>
<br>
<blockquote type="cite">
  <pre>As it&#39;s one in the morning I&#39;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&#39;t have to
swizzle the bytes, or alter the offset, so the VM startup code isn&#39;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 = &amp;fum;
    sqInt atIx;
    sqInt rcvr;
    sqInt result;
    sqInt index;
    sqInt sp;
    sqInt sp1;


        /* Sets successFlag */

        index = positive32BitValueOf(longAt(foo-&gt;stackPointer));
        rcvr = longAt(foo-&gt;stackPointer - (1 * BytesPerWord));
        if (!(foo-&gt;successFlag &amp;&amp; (!((rcvr &amp; 1))))) {
                /* begin primitiveFail */
                foo-&gt;successFlag = 0;
  </pre>
  <blockquote type="cite">
    <blockquote type="cite">
      <blockquote type="cite">
        <blockquote type="cite">
          <blockquote type="cite">
            <pre>       fprintf(stderr,&quot;\n failure for %u given %i&quot;,rcvr,index);
            </pre>
          </blockquote>
        </blockquote>
      </blockquote>
    </blockquote>
  </blockquote>
  <pre>//Happy puppy when -O0   not happy with -O1 (or others)
                return null;
        }




so given

sqInt primitiveSecondsClock(void) {
register struct foo * foo = &amp;fum;
    sqInt oop;
    sqInt sp;

        /* begin pop:thenPush: */
        oop = positive32BitIntegerFor(ioSeconds());
        longAtput(sp = foo-&gt;stackPointer - ((1 - 1) * BytesPerWord), oop);
        foo-&gt;stackPointer = sp;
}

*seems to work as the positive32BitIntegerFor feeds back something I
push back to positive32BitValueOf and print all the little pieces...

sqInt -&gt;D2F68C2F&lt;- Bytes 2F 8C F6 D2   integer value 3539373103  value
from ioSeconds going into positive 3539373103 push as 3539373103&lt;&gt;

On Fri, Mar 22, 2013 at 5:25 PM, Nicolas Cellier &lt;
<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>&gt; wrote:

  </pre>
  <blockquote type="cite">
    <pre>2013/3/22 Bert Freudenberg <a href="mailto:bert@freudenbergs.de" target="_blank">&lt;bert@freudenbergs.de&gt;</a>:
    </pre>
    <blockquote type="cite">
      <pre>On 2013-03-22, at 05:43, David T. Lewis <a href="mailto:lewis@mail.msen.com" target="_blank">&lt;lewis@mail.msen.com&gt;</a> wrote:

      </pre>
      <blockquote type="cite">
        <pre>&quot;It ain&#39;t what you don&#39;t know that gets you into trouble. It&#39;s what you
        </pre>
      </blockquote>
    </blockquote>
    <pre>know for sure that just ain&#39;t so.&quot;
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre>-- Mark Twain

An interpreter VM compiled with the normal C macros in sqMemoryAccess.h
        </pre>
      </blockquote>
    </blockquote>
    <pre>(for &quot;performance&quot;):
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre>0 tinyBenchmarks. &#39;417277913 bytecodes/sec; 14395420 sends/sec&#39;
0 tinyBenchmarks. &#39;414239482 bytecodes/sec; 14646769 sends/sec&#39;
0 tinyBenchmarks. &#39;417277913 bytecodes/sec; 14406658 sends/sec&#39;

The same interpreter VM with C macros replaced by Smalltalk slang
        </pre>
      </blockquote>
    </blockquote>
    <pre>(class MemoryAccess):
    </pre>
    <blockquote type="cite">
      <blockquote type="cite">
        <pre>0 tinyBenchmarks. &#39;455111111 bytecodes/sec; 14217973 sends/sec&#39;
0 tinyBenchmarks. &#39;451897616 bytecodes/sec; 14485815 sends/sec&#39;
0 tinyBenchmarks. &#39;453900709 bytecodes/sec; 14497194 sends/sec&#39;

Dave
        </pre>
      </blockquote>
      <pre>That is ... unexpected :)

      </pre>
    </blockquote>
    <pre>Well, that&#39;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: &#39;char *&#39;.
        self var: #val type: &#39;unsigned int&#39;.
        ^ self cCoerce:
                        ((self cCoerce: ptr to: &#39;unsigned int *&#39;)
                                at: 0
                                put: val)
                to: &#39;sqInt&#39;

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-&gt;unsigned int is no-op on
2-complement machines.
But it&#39;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-&gt;int, but MemoryAccess uses the
opposite cast unsigned int-&gt;int
It&#39;s also a no-op except that:
- the cast can overflow, which would be UB.
- gcc has a licence to presume you don&#39;t rely on UB and thus can
further consider the returned int is always &gt;= 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

    </pre>
    <blockquote type="cite">
      <pre>But it again shows the importance of the 3rd rule of Optimization.
<a href="http://c2.com/cgi/wiki?RulesOfOptimization" target="_blank">http://c2.com/cgi/wiki?RulesOfOptimization</a>

- Bert -

      </pre>
    </blockquote>
  </blockquote>
  <pre>  </pre>
</blockquote>
<br>
</div>

<br></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div>