<div dir="ltr">Hi !<br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, May 30, 2016 at 2:39 PM, Ben Coman <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:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span class=""><br>
On Sun, May 29, 2016 at 10:14 AM, Ben Coman &lt;<a href="mailto:btc@openinworld.com">btc@openinworld.com</a>&gt; wrote:<br>
&gt; Hi Clement, Thanks for your detailed reply.  I particularly liked your<br>
&gt; warm up exercises.  Goal directed learning is better than general<br>
&gt; browsing.<br>
&gt;<br>
&gt; On Tue, May 24, 2016 at 1:29 AM, Clément Bera &lt;<a href="mailto:bera.clement@gmail.com">bera.clement@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hi Ben,<br>
&gt;&gt;<br>
&gt;&gt; The REPL image expects chunk format. Hence you need to write &quot;3 + 4 !&quot;<br>
&gt;&gt;<br>
&gt;&gt; To get warmed-up:<br>
&gt;&gt; 1) Inspect the object memory, then look for the first class table page instance variable. It&#39;s an oop referencing an array, try in the simulator to &quot;printOop:&quot; the address of the first class table page that you found. It should print it in the Transcript, the first entries are immediate, in Spur32 SmallInteger/Character/SmallInteger.<br>
&gt;<br>
&gt; The inspector showed a Spur32MMLECoSimulator and classTableFirstPage<br>
</span>&gt; held 16r5311F8. Plugging that into [print oop...] showed...<br>
<br>
  16r5311F8: a(n) Array<br>
   16r52D108 nil  16r15C3A50 class SmallInteger   16r878D70 class<br>
Character  16r15C3A50 class SmallInteger<br>
  16r1111DC0 class SmallFloat64   16r52D108 nil   16r52D108 nil   16r52D108 nil<br>
   16r52D108 nil   16r52D108 nil   16r52D108 nil   16r52D108 nil<br>
   16r52D108 nil   16r52D108 nil   16r52D108 nil   16r52D108 nil<br>
   16r87AE60 class Array   16r52D108 nil   16r52D108 nil   16r52D108 nil<br>
   16r52D108 nil   16r52D108 nil   16r52D108 nil   16r52D108 nil<br>
   16r52D108 nil   16r52D108 nil   16r52D108 nil   16r52D108 nil<br>
   16r52D108 nil   16r52D108 nil   16r52D108 nil   16r52D108 nil<br>
   16r878C58 class LargeNegativeInteger   16r878C90 class<br>
LargePositiveInteger  16r10AEAE8 class BoxedFloat64   16r879438 class<br>
Message</blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
All the nils I guess are due to the class table being a hash map?<br>
<br>
Is there some way from within the simulation to reference an object by<br>
its hex number.  For example, to use the size of that array from<br>
within the simulation, something like...<br>
<br>
   classTableSize := 16r5311F8 objectFromHex size<br></blockquote><div><br></div><div>You got the right result. The the class table is a linked list of pages, each page being an array. The first page, shown here, is reserved for frequently used classes. <br></div><div><br></div><div>Indexes 0-15 are reserved for tagged object. </div><div>Indexes 16-32 are reserved for hidden classes. Typically the class table pages are instances of Array, but the use index 16 so the VM know they are hidden.</div><div>The rest is for real classes that are frequently used. There are many nils so we have free space for new features. It&#39;s not a hash map.</div><div><br></div><div>I don&#39;t think things like that exists: <i>classTableSize := 16r5311F8 objectFromHex size. </i>For oops debugging features are tied to printing through the simulator instance right now. However there is something like that in the JIT. In the machine code zone we can access part of the bytes as CogMethodSurrogate and its subclasses and in the stack we can do the same for stack pages with the corresponding surrogate. In this case one can do something like:</div><div><font face="monospace, monospace">CogMethodSurrogate at: 16r51578 objectMemory: objectMemory cogit: cogit<br></font></div><div>And then one can ask the surrogate things like:</div><div><font face="monospace, monospace">surrogate cmRefersToYoung</font></div><div>And it reads the correct bytes for you, in this case answering if the cog method has a reference to a young object.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<span class=""><br>
&gt;<br>
&gt;<br>
&gt;&gt; 2) print the active stack, look for the method&#39;s address. Try to print it as an oop, and if it tells you &quot;address in the machine code zone&quot;, print the cog method and its machine code instead.<br>
<br>
</span>I presume is the active stack is<br>
[print call stack] which produces...<br>
<br>
  16r1012F8 M MultiByteFileStream(StandardFileStream)&gt;basicNext<br>
16r1E7408: a(n) MultiByteFileStream<br>
  16r101334 M UTF8TextConverter&gt;nextFromStream: 16r1EA418: a(n)<br>
UTF8TextConverter<br>
  16r10135C M MultiByteFileStream&gt;next 16r1E7408: a(n) MultiByteFileStream<br>
  16r10138C I MultiByteFileStream(PositionableStream)&gt;nextChunkNoTag<br>
16r1E7408: a(n) MultiByteFileStream<br>
  16r1013B0 I StdioListener&gt;run 16r1E7C98: a(n) StdioListener<br>
  16r1013D0 I [] in UndefinedObject&gt;(nil) 16r52D108: a(n) UndefinedObject<br>
  16r1013F0 I [] in BlockClosure&gt;newProcess 16r1E7E00: a(n) BlockClosure<br>
---------<br>
<br>
[print oop...] 16r1012F8   tells me...<br>
    16r1012F8 is in the stack zone<br>
<br>
[print cog method for...] 16r1012F8    tells me...<br>
    not a method<br>
<br>
[print mc/cog frame]   says...<br>
Assertion failed<br>
with debugger at CogVMSimulatorLSD(CoInterpreter)&gt;&gt;isMachineCodeFrame:<br>
<br>
So I seem to be missing something.<br>
<br>
<br>
I restarted the simulator and this time...<br>
[print call stack...]<br>
  16r1012F8 M MultiByteFileStream(StandardFileStream)&gt;basicNext<br>
16r2A1BA8: a(n) MultiByteFileStream<br>
  16r101334 M UTF8TextConverter&gt;nextFromStream: 16r2A2188: a(n)<br>
UTF8TextConverter<br>
  16r10135C M MultiByteFileStream&gt;next 16r2A1BA8: a(n) MultiByteFileStream<br>
  16r10138C I MultiByteFileStream(PositionableStream)&gt;nextChunkNoTag<br>
16r2A1BA8: a(n) MultiByteFileStream<br>
  16r1013B0 I StdioListener&gt;run 16r2A1B00: a(n) StdioListener<br>
  16r1013D0 I [] in UndefinedObject&gt;(nil) 16r52D108: a(n) UndefinedObject<br>
  16r1013F0 I [] in BlockClosure&gt;newProcess 16r2A1690: a(n) BlockClosure<br>
----------<br>
<br>
[print oop...] 16r1012F8<br>
  16r1012F8 is in the stack zone<br>
<br>
[print oop...] 16r2A1BA8<br>
  16r2A1BA8: a(n) MultiByteFileStream<br>
   16r2A2740 &#39;????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????&#39;<br>
       16r1 =0 (16r0)        16r1 =0 (16r0)   16r52D108 nil<br>
   16r52D108 nil   16r52D118 false   16r9AA1E8 #stdin   16r24CC18 a ByteArray<br>
   16r2A2728 &#39;?&#39;   16r52D108 nil   16r2A2188 an UTF8TextConverter<br>
16r6DF1D8 #lf<br>
   16r52D128 true<br>
-----------<br>
<br>
Now after doing 3+4! several times,<br>
[print call stack...] produces...<br>
  16r101300 M MultiByteFileStream(StandardFileStream)&gt;basicNext<br>
16r2A1BA8: a(n) MultiByteFileStream<br>
  16r10133C M UTF8TextConverter&gt;nextFromStream: 16r2A2188: a(n)<br>
UTF8TextConverter<br>
  16r101364 M MultiByteFileStream&gt;next 16r2A1BA8: a(n) MultiByteFileStream<br>
  16r10138C M MultiByteFileStream(PositionableStream)&gt;nextChunkNoTag<br>
16r2A1BA8: a(n) MultiByteFileStream<br>
  16r1013B0 I StdioListener&gt;run 16r2A1B00: a(n) StdioListener<br>
  16r1013D0 I [] in UndefinedObject&gt;(nil) 16r52D108: a(n) UndefinedObject<br>
  16r1013F0 I [] in BlockClosure&gt;newProcess 16r2A1690: a(n) BlockClosure<br>
<br>
btw, What is the meaning of the M and I in the second column?  I<br>
notice that 16r10138C has changed from an I to a M.<br>
<br>
Also the address associated with basicNext changed from 16r1012F8 to<br>
16r101300. Can some meaning be inferred from that?<br></blockquote><div><br></div><div>Some explanations are needed here :-)</div><div><br></div><div>The M or I at the beginning of the printing are for &#39;Interpreted frame&#39; or &#39;Machine code frame&#39;.</div><div><br></div><div>When you do [print call stack], you print the list of stack frame in the current stack. For example,   </div><div><font face="monospace, monospace">16r101300 M MultiByteFileStream(StandardFileStream)&gt;basicNext</font></div><div>means that: </div><div>- the stack frame address in the stack zone is <span style="font-family:monospace,monospace">16r101300</span></div>- the machine code version of the method is executed in this frame (M and not I).<br class="">- the receiver has the type <span style="font-family:monospace,monospace">MultiByteFileStream</span><div>- the stack frame on top of the stack is the activation for the method <span style="font-family:monospace,monospace">StandardFileStream&gt;&gt;</span><span style="font-family:monospace,monospace">basicNext </span></div><div> </div><div>Now what you tried to do is to print the frame as a method, and that won&#39;t work (It&#39;s not obvious and my exercise was not very precised, sorry).</div><div><br></div><div>You can use [print frame ...] and put the frame&#39;s hex to print it. Alternatively, asyou usually want the top (a.k.a. head) frame, you can directly use [print ext head frame] if it&#39;s a machine code frame.</div><div><br></div><div>That should print something like that (I print a random frame here):</div><div><div><font face="monospace, monospace"> 16r103160:        arg1:     16r8239<span class="" style="white-space:pre">        </span>=16668(16r411C)</font></div><div><font face="monospace, monospace">  16r10315C:        arg2:     16r825D<span class="" style="white-space:pre">        </span>=16686(16r412E)</font></div><div><font face="monospace, monospace">  16r103158:        arg3:   16r2E21C0<span class="" style="white-space:pre">        </span>=a(n) Point</font></div><div><font face="monospace, monospace">  16r103154:        arg4:   16r9BC480<span class="" style="white-space:pre">        </span>=a(n) StrikeFont</font></div><div><font face="monospace, monospace">  16r103150:        arg5:        16r1<span class="" style="white-space:pre">        </span>=0(16r0)</font></div><div><font face="monospace, monospace">  16r10314C:   caller ip:    16r564E0=353504</font></div><div><font face="monospace, monospace">  16r103148:    saved fp:   16r103184=1061252</font></div><div><font face="monospace, monospace">  16r103144:      method:    16r51578<span class="" style="white-space:pre">        </span> 16r102BDD0 16r102BDD0: a(n) CompiledMethod</font></div><div><font face="monospace, monospace">  16r103144: mcfrm flags:        16r0  numArgs: 6 noContext notBlock</font></div><div><font face="monospace, monospace">  16r103140:     context:   16r52D108<span class="" style="white-space:pre">                </span>nil</font></div><div><font face="monospace, monospace">  16r10313C:    receiver:   16r2E0078<span class="" style="white-space:pre">                </span>a GrafPort</font></div><div><font face="monospace, monospace">  16r103138:        stck:   16r2E0078<span class="" style="white-space:pre">                </span>a GrafPort</font></div><div><font face="monospace, monospace">  16r103134:        stck:  16r1A115D0</font><span class="" style="white-space:pre"><font face="monospace, monospace">        </font>        </span></div></div><div><span class="" style="white-space:pre"><br></span></div><div><span class="" style="white-space:pre">Now that you&#39;ve print the frame, you can see the method addresses in this line:</span></div><div><span class="" style="white-space:pre"><span style="font-family:monospace,monospace;white-space:normal">16r103144:      method:    16r51578</span><span class="" style="font-family:monospace,monospace">        </span><span style="font-family:monospace,monospace;white-space:normal"> 16r102BDD0 16r102BDD0: a(n) CompiledMethod.</span><br></span></div><div><span class="" style="white-space:pre">This is a machine code frame, so the method has two addresses:</span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="monospace, monospace">16r51578</font> =&gt; in generated method, so you need to use [disassembleMethod/trampoline...] and write down the hex to see the disassembly. (Toggle Transcript first and open a large Transcript if you do that).</span><br></span></div><div><span class="" style="white-space:pre"><span style="font-family:monospace,monospace;white-space:normal">16r102BDD0 </span><span style="white-space:normal"><font face="arial, helvetica, sans-serif">=&gt; in the heap. This is the bytecode version of the method. You can print it using [print oop...]</font></span><span style="white-space:normal"><br></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif"><br></font></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif"><br></font></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif">Ok ! One last warm-up exercise:</font></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif"><br></font></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif">3) When the simulator has started and the REPL window has popped up, select [single step]. Then enter something in the REPL window and execute it. Once done, do [report recent instructions]. You should be able to see in the Transcript the last 100 machine instruction with the register state in-between each instruction.</font></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif"><br></font></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif">I think I should write down those exercise as a blog post...</font></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif"><br></font></span></span></div><div><span class="" style="white-space:pre"><span style="white-space:normal"><font face="arial, helvetica, sans-serif"><br></font></span></span></div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
cheers -ben<br>
</blockquote></div><br></div></div>