Hi Igor,

    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:

sizeBitsOf: oop
"Answer the number of bytes in the given object, including its base header, rounded up to an integral number of words."
"Note: byte indexable objects need to have low bits subtracted from this size."
<inline: true>
| header |
1. header := self baseHeader: oop.
2. ^(header bitAnd: TypeMask) = HeaderTypeSizeAndClass
ifTrue: [(self sizeHeader: oop) bitAnd: LongSizeMask]
ifFalse: [header bitAnd: SizeMask]

Here's StackInterpreter>printNameOfClass:count:, with the occurrence of sizeBitsOf: in an expression context:

printNameOfClass: classOop count: cnt
"Details: The count argument is used to avoid a possible infinite recursion if classOop is a corrupted object."
<inline: false>
(classOop = 0 or: [cnt <= 0]) ifTrue: [^self print: 'bad class'].
e: ((objectMemory sizeBitsOf: classOop) = metaclassSizeBytes
 and: [metaclassSizeBytes > (thisClassIndex * BytesPerWord)]) "(Metaclass instSize * 4)"
ifTrue: [self printNameOfClass: (objectMemory fetchPointer: thisClassIndex ofObject: classOop) count: cnt - 1.
self print: ' class']
ifFalse: [self printStringOf: (objectMemory fetchPointer: classNameIndex ofObject: classOop)]

With sizeBitsOf: defined as above this translates to:

static void
printNameOfClasscount(sqInt classOop, sqInt cnt)
{
if ((classOop == 0)
|| (cnt <= 0)) {
print("bad class"); return;
}
if (((sizeBitsOf(classOop)) == GIV(metaclassSizeBytes))
&& (GIV(metaclassSizeBytes) > (GIV(thisClassIndex) * BytesPerWord))) {
printNameOfClasscount(longAt((classOop + BaseHeaderSize) + (GIV(thisClassIndex) << ShiftForWord)), cnt - 1);
print(" class");
}
else {
printStringOf(longAt((classOop + BaseHeaderSize) + (GIV(classNameIndex) << ShiftForWord)));
}
}

But if one changes the definition of sizeBitsOf: to an expression, necessitating two references through oop, to:

sizeBitsOf: oop
"Answer the number of bytes in the given object, including its base header, rounded up to an integral number of words."
"Note: byte indexable objects need to have low bits subtracted from this size."
<inline: true>
^((self baseHeader: oop) bitAnd: TypeMask) = HeaderTypeSizeAndClass
ifTrue: [(self sizeHeader: oop) bitAnd: LongSizeMask]
ifFalse: [(self baseHeader: oop) bitAnd: SizeMask]

then StackInterpreter>printNameOfClass:count: translates to

static void
printNameOfClasscount(sqInt classOop, sqInt cnt)
{
if ((classOop == 0)
|| (cnt <= 0)) {
print("bad class"); return;
}
if ((((((longAt(classOop)) & TypeMask) == HeaderTypeSizeAndClass
? (longAt(classOop - (BytesPerWord * 2))) & LongSizeMask
: (longAt(classOop)) & SizeMask)) == GIV(metaclassSizeBytes))
&& (GIV(metaclassSizeBytes) > (GIV(thisClassIndex) * BytesPerWord))) {
printNameOfClasscount(longAt((classOop + BaseHeaderSize) + (GIV(thisClassIndex) << ShiftForWord)), cnt - 1);
print(" class");
}
else {
printStringOf(longAt((classOop + BaseHeaderSize) + (GIV(classNameIndex) << ShiftForWord)));
}
}


So (David) this isn't so much a bug as a limitation of the inliner.

Of course in an expression context it could be translated as

static void
printNameOfClasscount(sqInt classOop, sqInt cnt)
{
| header |
if ((classOop == 0)
|| (cnt <= 0)) {
print("bad class"); return;
}
if (((header = longAt(classOop),
((header & TypeMask) == HeaderTypeSizeAndClass
? (longAt(classOop - (BytesPerWord * 2))) & LongSizeMask
: header & SizeMask)) == GIV(metaclassSizeBytes))
&& (GIV(metaclassSizeBytes) > (GIV(thisClassIndex) * BytesPerWord))) {
printNameOfClasscount(longAt((classOop + BaseHeaderSize) + (GIV(thisClassIndex) << ShiftForWord)), cnt - 1);
print(" class");
}
else {
printStringOf(longAt((classOop + BaseHeaderSize) + (GIV(classNameIndex) << ShiftForWord)));
}
}

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.


HTH
Eliot

On Sat, Jul 30, 2011 at 8:53 PM, Igor Stasenko <siguctua@gmail.com> wrote:

if instead i do like that:

size := self sizeBitsOf: op1.
sz2 := self sizeBitsOf: op2.
size = sz2 ifFalse: [   ^ false ].


then it inlines both calls.

On 31 July 2011 05:49, Igor Stasenko <siguctua@gmail.com> wrote:
> Here the slang code:
>
>        size := self sizeBitsOf: op1.
>        size = (self sizeBitsOf: op2) ifFalse: [
>                ^ false ].
>
> And here translated code:
>
>        /* begin sizeBitsOf: */
>        header = longAt(op1);
>        size = ((header & TypeMask) == HeaderTypeSizeAndClass
>                ? (longAt(op1 - (BytesPerWord * 2))) & LongSizeMask
>                : header & SizeMask);
>        if (!(size == (sizeBitsOf(op2)))) {
>                return 0;
>        }
>
> as you can see it inlining first, but refuses to inline second one.
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>



--
Best regards,
Igor Stasenko AKA sig.



--
best,
Eliot