Hi Igor,<div><br></div><div> this is simply because the inliner can only inline an expression in an expression context. Since sizeBitsOf: is written as multiple statements it can only be inlined in a statement context. Here's NewObjectMemory>sizeBitsOf: with the statements numbered:</div>
<div><br></div><div><div>sizeBitsOf: oop</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>"Answer the number of bytes in the given object, including its base header, rounded up to an integral number of words."</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>"Note: byte indexable objects need to have low bits subtracted from this size."</div><div><span class="Apple-tab-span" style="white-space:pre">        </span><inline: true></div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>| header |</div><div>1.<span class="Apple-tab-span" style="white-space:pre">        </span>header := self baseHeader: oop.</div><div>2.<span class="Apple-tab-span" style="white-space:pre">        </span>^(header bitAnd: TypeMask) = HeaderTypeSizeAndClass</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [(self sizeHeader: oop) bitAnd: LongSizeMask]</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [header bitAnd: SizeMask]</div>
<div><br></div><div>Here's StackInterpreter>printNameOfClass:count:, with the occurrence of sizeBitsOf: in an expression context:</div><div><br></div><div><div>printNameOfClass: classOop count: cnt</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>"Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object."</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span><inline: false></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>(classOop = 0 or: [cnt <= 0]) ifTrue: [^self print: 'bad class'].</div>
<div>e:<span class="Apple-tab-span" style="white-space:pre">        </span>((objectMemory sizeBitsOf: classOop) = metaclassSizeBytes</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> and: [metaclassSizeBytes > (thisClassIndex * BytesPerWord)])<span class="Apple-tab-span" style="white-space:pre">        </span>"(Metaclass instSize * 4)"</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [self printNameOfClass: (objectMemory fetchPointer: thisClassIndex ofObject: classOop) count: cnt - 1.</div><div><span class="Apple-tab-span" style="white-space:pre">                                </span>self print: ' class']</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [self printStringOf: (objectMemory fetchPointer: classNameIndex ofObject: classOop)]</div></div><div><br></div>With sizeBitsOf: defined as above this translates to:</div>
<div><br></div><div><div>static void</div><div>printNameOfClasscount(sqInt classOop, sqInt cnt)</div><div>{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>if ((classOop == 0)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> || (cnt <= 0)) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>print("bad class"); return;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>if (((sizeBitsOf(classOop)) == GIV(metaclassSizeBytes))</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> && (GIV(metaclassSizeBytes) > (GIV(thisClassIndex) * BytesPerWord))) {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>printNameOfClasscount(longAt((classOop + BaseHeaderSize) + (GIV(thisClassIndex) << ShiftForWord)), cnt - 1);</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>print(" class");</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>else {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>printStringOf(longAt((classOop + BaseHeaderSize) + (GIV(classNameIndex) << ShiftForWord)));</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div>
<div>}</div><div><br></div><div>But if one changes the definition of sizeBitsOf: to an expression, necessitating two references through oop, to:</div><div><br></div><div><div>sizeBitsOf: oop</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>"Answer the number of bytes in the given object, including its base header, rounded up to an integral number of words."</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>"Note: byte indexable objects need to have low bits subtracted from this size."</div><div><span class="Apple-tab-span" style="white-space:pre">        </span><inline: true></div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>^((self baseHeader: oop) bitAnd: TypeMask) = HeaderTypeSizeAndClass</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>ifTrue: [(self sizeHeader: oop) bitAnd: LongSizeMask]</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>ifFalse: [(self baseHeader: oop) bitAnd: SizeMask]</div></div><div><br></div><div>then StackInterpreter>printNameOfClass:count: translates to</div><div>
<br></div><div><div>static void</div><div>printNameOfClasscount(sqInt classOop, sqInt cnt)</div><div>{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>if ((classOop == 0)</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> || (cnt <= 0)) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>print("bad class"); return;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>if ((((((longAt(classOop)) & TypeMask) == HeaderTypeSizeAndClass</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>? (longAt(classOop - (BytesPerWord * 2))) & LongSizeMask</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>: (longAt(classOop)) & SizeMask)) == GIV(metaclassSizeBytes))</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> && (GIV(metaclassSizeBytes) > (GIV(thisClassIndex) * BytesPerWord))) {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>printNameOfClasscount(longAt((classOop + BaseHeaderSize) + (GIV(thisClassIndex) << ShiftForWord)), cnt - 1);</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>print(" class");</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>else {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>printStringOf(longAt((classOop + BaseHeaderSize) + (GIV(classNameIndex) << ShiftForWord)));</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div>
<div>}</div></div><div><br></div><div><br></div><div>So (David) this isn't so much a bug as a limitation of the inliner.</div><div><br></div><div>Of course in an expression context it could be translated as</div><div>
<br></div><div><div>static void</div><div>printNameOfClasscount(sqInt classOop, sqInt cnt)</div><div>{</div><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>| header |</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>if ((classOop == 0)</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> || (cnt <= 0)) {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>print("bad class"); return;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>if (((header = longAt(classOop),</div><div><span class="Apple-tab-span" style="white-space:pre">        </span> ((header & TypeMask) == HeaderTypeSizeAndClass</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span>? (longAt(classOop - (BytesPerWord * 2))) & LongSizeMask</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>: header & SizeMask)) == GIV(metaclassSizeBytes))</div>
<div><span class="Apple-tab-span" style="white-space:pre">        </span> && (GIV(metaclassSizeBytes) > (GIV(thisClassIndex) * BytesPerWord))) {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>printNameOfClasscount(longAt((classOop + BaseHeaderSize) + (GIV(thisClassIndex) << ShiftForWord)), cnt - 1);</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>print(" class");</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>else {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>printStringOf(longAt((classOop + BaseHeaderSize) + (GIV(classNameIndex) << ShiftForWord)));</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div>
<div>}</div></div><div><br></div><div>and I think the changes I made recently to TStmtListNode>emitCCodeAsArgumentOn:level:generator: are what's required. You simply have to track down where in the inliner it makes the determination as to whether the expression can be inlined.</div>
<div><br></div><div><br></div><div>HTH</div><div>Eliot</div><div><br></div><div class="gmail_quote">On Sat, Jul 30, 2011 at 8:53 PM, Igor Stasenko <span dir="ltr"><<a href="mailto:siguctua@gmail.com">siguctua@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
if instead i do like that:<br>
<br>
size := self sizeBitsOf: op1.<br>
sz2 := self sizeBitsOf: op2.<br>
size = sz2 ifFalse: [ ^ false ].<br>
<br>
<br>
then it inlines both calls.<br>
<div><div></div><div class="h5"><br>
On 31 July 2011 05:49, Igor Stasenko <<a href="mailto:siguctua@gmail.com">siguctua@gmail.com</a>> wrote:<br>
> Here the slang code:<br>
><br>
> size := self sizeBitsOf: op1.<br>
> size = (self sizeBitsOf: op2) ifFalse: [<br>
> ^ false ].<br>
><br>
> And here translated code:<br>
><br>
> /* begin sizeBitsOf: */<br>
> header = longAt(op1);<br>
> size = ((header & TypeMask) == HeaderTypeSizeAndClass<br>
> ? (longAt(op1 - (BytesPerWord * 2))) & LongSizeMask<br>
> : header & SizeMask);<br>
> if (!(size == (sizeBitsOf(op2)))) {<br>
> return 0;<br>
> }<br>
><br>
> as you can see it inlining first, but refuses to inline second one.<br>
><br>
><br>
> --<br>
> Best regards,<br>
> Igor Stasenko AKA sig.<br>
><br>
<br>
<br>
<br>
--<br>
Best regards,<br>
Igor Stasenko AKA sig.<br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>best,<div>Eliot</div><br>
</div>