<div dir="ltr">BTW, I have changes for the suggested speedup that are not yet complete.  The complication is closed PICs which need to check for the odd SmallInteger receiver in a different place.  If you're burning with curiosity and want to try and make this work then find the changes I have so far attached...</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Aug 3, 2018 at 5:35 PM, Eliot Miranda <span dir="ltr"><<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">BTW, I have hanges for the suggested speedup that are not yet complete.  The compilation is ClosedPICs which need to check for the odd SmnallInteger in a different place.  If you're burning with curiosity and want to try and make this work find the changes I have so far attached...</div><div class="gmail_extra"><div><div class="h5"><br><div class="gmail_quote">On Fri, Aug 3, 2018 at 4:04 PM, Eliot Miranda <span dir="ltr"><<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="m_-7960500590263559118h5">On Fri, Aug 3, 2018 at 3:54 PM, Eliot Miranda <span dir="ltr"><<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>></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"><div dir="ltr">Hi Ben,<div class="gmail_extra"><br><div class="gmail_quote"><span class="m_-7960500590263559118m_2381506301062988246gmail-">On Thu, Aug 2, 2018 at 7:28 PM, Ben Coman <span dir="ltr"><<a href="mailto:btc@openinworld.com" target="_blank">btc@openinworld.com</a>></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"> <br>
Just a brain twitch about something I'd like to understand better...<br>
<br>
At <a href="http://www.mirandabanda.org/cogblog/2011/03/01/build-me-a-jit-as-fast-as-you-can/" rel="noreferrer" target="_blank">http://www.mirandabanda.org/co<wbr>gblog/2011/03/01/build-me-a-ji<wbr>t-as-fast-as-you-can/</a><br>
it says... "[Monomorphic] inline caching depends on the fact that in<br>
most programs at most send sites there is no polymorphism and that<br>
most sends bind to *exactly_one* class of receiver over some usefully<br>
long period of time. ... In Cog we implement inline caches in three<br>
forms ... monomorphic inline cache ... closed polymorphic inline cache<br>
... open polymorphic cache.  What’s nice is that while these sends are<br>
increasingly expensive moving from monomorphic to megamorphic they are<br>
also decreasingly common in roughly a 90%, 9% 0.9% ratio, at least for<br>
typical Smalltalk programs"<br>
<br>
First, I'm curious what is the relative performance of the three<br>
different caches ?<br></blockquote><div><br></div></span><div>here's a measurement for Spur:</div><div><br></div><div>| n null void homogenousImmediateA homogenousImmediateB homogenousNormal polymorphic megamorphic |</div><div>Smalltalk garbageCollect.</div><div>n := 1000000.</div><div>void := Array new: 1024 withAll: nil.</div><div>homogenousImmediateA := Array new: 1024 withAll: 1.</div><div>homogenousImmediateB := Array new: 1024 withAll: $1.</div><div>homogenousNormal := Array new: 1024 withAll: 1 / 2.</div><div>polymorphic := Array new: 1024.</div><div>1 to: polymorphic size by: 4 do:</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                </span>[:i|</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">               </span>polymorphic</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                                </span>at: i put: i;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                              </span>at: i + 1 put: i asFloat;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                          </span>at: i + 2 put: i / 1025;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                           </span>at: i + 3 put: i * 1.0s1 "scaled decimal"].</div><div>megamorphic := Array new: 1024.</div><div>1 to: megamorphic size by: 8 do:</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">         </span>[:i|</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">               </span>megamorphic</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                                </span>at: i put: i;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                              </span>at: i + 1 put: i asFloat;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                          </span>at: i + 2 put: i / 1025;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                           </span>at: i + 3 put: i * 1.0s1; "scaled decimal"</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                               </span>at: i + 4 put: i class;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                            </span>at: i + 5 put: i asFloat class;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                            </span>at: i + 6 put: (i / 1025) class;</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                           </span>at: i + 7 put: (i * 1.0s1) class].</div><div>null := [1 to: 1024 * n do: [:k| | e | e := void at: k \\ 1024 + 1. e "yourself"]] timeToRun; timeToRun.</div><div>{ homogenousImmediateA. homogenousImmediateB. homogenousNormal. polymorphic. megamorphic } collect:</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">              </span>[:a| </div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">             </span>"Smalltalk voidCogVMState."</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">              </span>([1 to: 1024 * n do: [:k| | e | e := a at: k \\ 1024 + 1. e yourself". e yourself"]] timeToRun; timeToRun) - null]</div><div><br></div><div>And results on my 2.3GHz Intel Core i7 MacMini (in a far from quiet state, so take these with a pinch of salt) are</div><div><br></div><div>64-bit: #(1510 1703 1612 1830 2451)</div><div>32-bit: #(2852 4133 2843 3534 5317)</div><div><br></div><div>or...</div><div><span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">                                  </span>64-bit<span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">    32-bit</span></div><div>monomorphic to 1<span class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail-Apple-tab-span" style="white-space:pre-wrap">             </span>1510<span style="white-space:pre-wrap">    </span>2852</div><div>monomorphic to $1<span style="white-space:pre-wrap">            </span>1703<span style="white-space:pre-wrap">    </span>4133</div><div><span style="white-space:pre-wrap">monomorphic to obj</span><span style="white-space:pre-wrap">   </span>1612<span style="white-space:pre-wrap">    </span>2843</div><div>closed polymorphic<span style="white-space:pre-wrap">           </span>1830<span style="white-space:pre-wrap">    </span>3534</div><div>open polymorphic<span style="white-space:pre-wrap">             </span>2451<span style="white-space:pre-wrap">    </span>5317</div><div><br></div><div>The sad thing is that Spur's monomorphic sends to immediate are very slow because 32-bit Spur supports 31-bit SmallInteger immediates (for compatibility with 32-bit V3).  Were it to use the simple tagging scheme of two bit tags sends would look more like the 64-bit ones.<br></div><div><br></div><div>The difference between monomorphic sends to 1 and sends to $1 on 64-bit shows the variability in timing due to a heavily loaded machine.  There's no difference in the instructions executed.</div><div><br></div><div><div>Here's the  monomorphic cache checking sequence generated for the prolog of each method in (32-bit) V3:</div><div><div><br></div><div>LstackOverflow:<span style="white-space:pre-wrap"> </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># first byte of code, aligned on an 8 byte boundary</span></div><div><span style="white-space:pre-wrap">      </span>xorl %edx, %edx</div><div>Lfail:</div><div></div><div><span style="white-space:pre-wrap">      </span>call ceMethodAbort0Args</div><div><span style="white-space:pre-wrap">  </span>nop</div><div>entry:<span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># aligned on an 8 byte boundary</span></div><div><span style="white-space:pre-wrap">  </span>movl %edx, %eax</div><div><span style="white-space:pre-wrap">  </span>andl $1, %eax<span style="white-space:pre-wrap">   </span><span style="white-space:pre-wrap"># only immediate class is SmallInteger </span></div><div><span style="white-space:pre-wrap">  </span>jnz Lcompare</div><div><span style="white-space:pre-wrap">     </span>movl (%edx), %eax</div><div><span style="white-space:pre-wrap">        </span>andl $0x1f000, %eax<span style="white-space:pre-wrap">     </span><span style="white-space:pre-wrap"># if non-zero, class is compact & compact class index used as cache tag</span></div><div><span style="white-space:pre-wrap">      </span>jnz Lcompare</div><div><span style="white-space:pre-wrap">     </span>movl -4(%edx), %eax<span style="white-space:pre-wrap">     # normal class plus 2 bits of header type tag, eliminate header type tag</span></div><div><span style="white-space:pre-wrap"> </span>andl $0xfffffffc, %eax</div><div>Lcompare</div><div><span style="white-space:pre-wrap">    </span>cmpl %ecx, %eax</div><div><span style="white-space:pre-wrap">  </span>jnz Lfail</div><div>noCheckEntry:</div></div><div><br></div><div></div></div><div>Here's the monomorphic cache checking sequence generated for the prolog of each method in 32-bit Spur:</div><div><br></div><div>LstackOverflow:<span style="white-space:pre-wrap">   </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># first byte of code, aligned on an 8 byte boundary</span></div><div><span style="white-space:pre-wrap">      </span>xorl %edx, %edx</div><div>Lfail:</div><div><div><span style="white-space:pre-wrap">  </span>call ceMethodAbort0Args<br></div><div><span style="white-space:pre-wrap">        </span>nop</div></div><div>Limmediate:<span style="white-space:pre-wrap">       </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># aligned on an 8 byte boundary</span></div><div><div><span style="white-space:pre-wrap">       </span>andl $1, %eax<span style="white-space:pre-wrap">   </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># map SmallInteger to 1, Character to 0</span></div><div><span style="white-space:pre-wrap">  </span>jmp Lcompare</div><div><span style="white-space:pre-wrap">     </span>nop</div><div><span style="white-space:pre-wrap">      </span>nop</div><div><span style="white-space:pre-wrap">      </span>nop</div><div>entry:<span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        # aligned on an 8 byte boundary</span></div><div><span style="white-space:pre-wrap">  </span>movl %edx, %eax</div><div><span style="white-space:pre-wrap">  </span>andl $3, %eax<span style="white-space:pre-wrap">   </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># SmallInteger is both 2r01 and 2r11, Character is 2r10</span></div><div><span style="white-space:pre-wrap">  </span>jnz Limmediate</div><div><span style="white-space:pre-wrap">   </span>movl (%edx), %eax</div><div><span style="white-space:pre-wrap">        </span>andl $0x3fffff, %eax<span style="white-space:pre-wrap">    </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># cache tag is class index field</span></div><div>Lcompare:</div><div><span style="white-space:pre-wrap"> </span>cmpl %ecx, %eax</div><div><span style="white-space:pre-wrap">  </span>jnz Lfail</div><div>noCheckEntry:</div></div><div><br></div><div>Here's the monomorphic cache checking sequence generated for the prolog of each method in 32-bit Spur:</div><div><br></div><div>LstackOverflow:<span style="white-space:pre-wrap">      </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># first byte of code, aligned on an 8 byte boundary</span></div><div><span style="white-space:pre-wrap">      </span>xorq %rdx, %rdx<br></div><div>Lfail:<br><div><span style="white-space:pre-wrap">     </span>call ceMethodAbort0Args</div><div>entry:</div><div><span style="white-space:pre-wrap">     </span>movq %rdx, %rax</div><div><span style="white-space:pre-wrap">  </span>andq $7, %rax<span style="white-space:pre-wrap">   </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># SmallInteger is 2r001, Character is 2r010, SmallFloat is 2r100</span></div><div><span style="white-space:pre-wrap"> </span>jnz Lcompare</div><div><span style="white-space:pre-wrap">     </span>movq (%rdx), %rax</div><div><span style="white-space:pre-wrap">        </span>andq $0x3fffff, %rax<span style="white-space:pre-wrap">    </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># cache tag is class index field<br></span>Lcompare:</div><div><span style="white-space:pre-wrap">      </span>cmpq %rcx, %rax</div><div><span style="white-space:pre-wrap">  </span>jnz Lfail</div><div>noCheckEntry:</div></div><div><br></div><div>The 64-bit sequence is the cleanest.  But if 32-bit Spur had 30-bit SmallIntegers alongside its 30-bit Characters then that sequence would be equally simple.</div><div><br></div><div>I suppose something like this could be quicker for 32-bit Spur with 31-bit SmallIntegers.  It would mean that sends to odd SmallIntegers were slower than sends to even ones, but would be quicker for Characters and even SmallIntegers:</div><div><br></div><div><div>LstackOverflow:<span style="white-space:pre-wrap">     </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># first byte of code, aligned on an 8 byte boundary</span></div><div><span style="white-space:pre-wrap">      </span>xorl %edx, %edx</div><span style="white-space:pre-wrap">     </span>xorl %eax, %eax<span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># necessary because %eax may have some other value than %edx bitAnd: $3 when branching to LstackOverflow</span><div>Lfail:</div><div><span style="white-space:pre-wrap">        </span>cmpl $3, %eax<br></div></div></div></div></div></blockquote><div> </div></div></div><div>Oops!! :</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"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div></div><div><span style="white-space:pre-wrap">      </span>jnz Limmediate<br></div></div></div></div></div></blockquote><div><br></div><div>I of course meant</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"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div></div><div><span style="white-space:pre-wrap">       </span>jz Limmediate</div></div></div></div></blockquote><div><div class="m_-7960500590263559118h5"><div> </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"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div></div><div><div><span style="white-space:pre-wrap">        </span>call ceMethodAbort0Args</div></div><div>Limmediate:</div><div><div><span style="white-space:pre-wrap"> </span>andl $1, %eax<span style="white-space:pre-wrap">   </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># map odd SmallInteger (2r11) to 2r01</span></div><div><span style="white-space:pre-wrap">    </span>jmp Lcompare</div><div>entry:<span style="white-space:pre-wrap">       </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        # aligned on an 8 byte boundary</span></div><div><span style="white-space:pre-wrap">  </span>movl %edx, %eax</div><div><span style="white-space:pre-wrap">  </span>andl $3, %eax<span style="white-space:pre-wrap">   </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># SmallInteger is both 2r01 and 2r11, Character is 2r10.  SmallInteger cache tag is 2r01</span></div><div><span style="white-space:pre-wrap"> </span>jnz Lcompare</div><div><span style="white-space:pre-wrap">     </span>movl (%edx), %eax</div><div><span style="white-space:pre-wrap">        </span>andl $0x3fffff, %eax<span style="white-space:pre-wrap">    </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap">        </span><span style="white-space:pre-wrap"># cache tag is class index field</span></div><div>Lcompare:</div><div><span style="white-space:pre-wrap"> </span>cmpl %ecx, %eax</div><div><span style="white-space:pre-wrap">  </span>jnz Lfail</div><div>noCheckEntry:</div></div></div><span class="m_-7960500590263559118m_2381506301062988246gmail-"><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">Second, I'm curious how Booleans are dealt with.  Boolean handling<br>
must be fairly common, and at the Image level these are two different<br>
classes, which pushes out of the monomorphic inline cache, which may<br>
be a significant impact on performance.<br>
<br>
I started wondering if under the hood the VM could treat the two<br>
booleans as one class and in the instance store "which-boolean" it<br>
actually is.  Then for example the #ifTrue:ifFalse: method of each<br>
class would be compiled into a single method conditioned at the start<br>
on "which-boolean" as to which path is executed.  How feasible would<br>
that be, and would it make much of a difference in performance of<br>
booleans ?<br></blockquote><div><br></div></span><div>You can see that the closeness in performance between monomorphic and closed polymorphic sends means that handling true and false as instances of two different classes costs relatively little in performance.</div><span class="m_-7960500590263559118m_2381506301062988246gmail-"><div> </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">Except then I realized that this situation is already bypassed by<br>
common boolean methods being inlined by the compiler.  Still curious,<br>
if there are quick answers to my questions.<br>
<br>
cheers -ben<br>
</blockquote></span></div><br><div class="m_-7960500590263559118m_2381506301062988246gmail-m_-4558539741543284722gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>
</blockquote></div></div></div><span class="m_-7960500590263559118HOEnZb"><font color="#888888"><br><br clear="all"><div><br></div>-- <br><div class="m_-7960500590263559118m_2381506301062988246gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</font></span></div></div>
</blockquote></div><br><br clear="all"><div><br></div></div></div><span class="HOEnZb"><font color="#888888">-- <br><div class="m_-7960500590263559118gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div>