2009/12/20 Igor Stasenko <[email protected]>:
> 2009/12/20 Marcus Denker <[email protected]>:
>>
>> On Dec 20, 2009, at 8:44 PM, Bart Gauquie wrote:
>>
>>> Dear all,
>>>
>>> I'm developing code which generates a method content, compiles it and adds 
>>> it to an existing class.
>>> I compile the message using #compile: message:
>>> for instance:
>>>
>> In general, everything is limited to a fairly low quantity: number of temps, 
>> number of ivars, number of
>> literals.
>>
>> Especially that the literal frame is limted to some small number (255 or 
>> something) can be easily be a problem.
>> (we ran into that already when using bytesurgeon on large existing methods 
>> when reifying all sends, for example).
>>
>
> To get around this, place all literals into one (usually array):
> #( a b c d e ..... )
>
> For instance, the above:
>  self addMMEFrom: 1...@512 to: 1...@504.
>  self addMMEFrom: 6...@559 to: 6...@579.
>
> can be easily replaced by something like:
>
> #( (1054 512 1037 504)
>    ..... put as many as you want here.... no limit!!!
>
>    (651 559 643 579) ) do: [:each |
> self addMMEFrom: (each first @ each second) to: (each third @ each fourth)
> ]
>
>>        Marcus
>> _______________________________________________
>> Pharo-project mailing list
>> [email protected]
>> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
> _______________________________________________
> Pharo-project mailing list
> [email protected]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

Hehe, when generating code for evaluating monster symbolic
expressions, I bumped into many of these limitations.
Using a literal Array was not enough because even the indices would
consume a literal slot. So i had to decompose indices into
operations...  Oh, and even some message sends had to be transformed
in #perform: sends (not shown here)...
Here is a fragment of code for allocating a literal slot (in
Objectworks, an ancestor of VW).

Nicolas

CodeStream subclass: #ExtendedCodeStream
        instanceVariableNames: 'reduceLiterals'
        classVariableNames: 'MaxLiteralIndex '
        poolDictionaries: 'OpcodePool '
        category: 'System-Compiler'

ExtendedCodeStream>>pushReducedConstant: lit
        "Handle MaxLiteralsNumber"

        | classIndex newClassArray litIndex |
        self push.
        lit == nil
                ifTrue:
                        [code nextPut: OpLoadNil.
                        ^self].
        lit == true
                ifTrue:
                        [code nextPut: OpLoadTrue.
                        ^self].
        lit == false
                ifTrue:
                        [code nextPut: OpLoadFalse.
                        ^self].
        lit isInteger
                ifTrue:
                        [(lit >= 0 and: [lit <= 2])
                                ifTrue:
                                        [code nextPut: OpLoadZero + lit.
                                        ^self].
                        (lit >= 0 and: [lit <= 255])
                                ifTrue:
                                        [code nextPut: OpLoadByte with: lit.
                                        ^self].
                        (lit >= -32768 and: [lit < 32768])
                                ifTrue:
                                        [code
                                                nextPut: OpLoadTwoBytes
                                                with: ((lit bitShift: -8)
                                                                bitAnd: 255)
                                                with: (lit bitAnd: 255).
                                        ^self]].
        ((lit isMemberOf: Character)
                and: [lit asInteger between: 0 and: 255])
                ifTrue:
                        [code nextPut: OpLoadCharacter with: lit asInteger.
                        ^self].
        classIndex := literals at: lit class
                                ifAbsent:
                                        ["Add the literal class array to the 
collection"
                                        literalCollection addLast: Array new.
                                        literals at: lit class put: 
literalCollection size - 1].
        classIndex > MaxLiteralIndex
                ifTrue:
                        [Errorscript cr; show: 'compilation failure: too many 
literal classes...'.
                        self class literalLimitSignal raiseWith: topNode body].
        classIndex <= MaxLoadLiteral
                ifTrue: [code nextPut: OpLoadLiteral + classIndex]
                ifFalse: [code nextPut: OpXLoadLiteral with: classIndex].
        newClassArray := literalCollection at: classIndex + 1.
        litIndex := newClassArray indexOf: lit ifAbsent: [0].
        litIndex = 0
                ifTrue:
                        [newClassArray := newClassArray copyWith: lit.
                        literalCollection at: classIndex + 1 put: newClassArray.
                        litIndex := newClassArray size].
        self pushBigIndex: litIndex.
        self sendNoCheck: #at: numArgs: 1

ExtendedCodeStream>>pushBigIndex: index
        "i do not want the index to figure in literalCollection
        so it must remain < 32768"

        | q r |
        index < 32768 ifTrue: [^self pushConstant: index].
        q := index // 32768.
        r := index - (q * 32768).
        self pushConstant: 32767; pushConstant: 1; sendNoCheck: #+ numArgs: 1.
        q = 1 ifFalse: [self pushBigIndex: q; sendNoCheck: #* numArgs: 1].
        r = 0 ifFalse: [self pushConstant: r; sendNoCheck: #+ numArgs: 1].

ExtendedCodeStream>>pushStatic: binding
        "Static variables do normally consume a literal slot.
        Arrange to economize this precious ressource"

        reduceLiterals
                ifTrue:
                        [self pushReducedConstant: binding.
                        self sendNoCheck: #value numArgs: 0]
                ifFalse: [super pushStatic: binding]

ExtendedCodeStream>>pushConstant: lit
        "Handle MaxLiteralsIndex"

        reduceLiterals ifTrue: [^self pushReducedConstant: lit].
        super pushConstant: lit.

ExtendedCodeStream>>testLiteralsSize
        "Restart compilation if literal limit is exceeded"

        literalCollection size > MaxLiteralIndex ifTrue: [reduceLiterals
                        ifTrue: [self class literalLimitSignal raiseWith: 
topNode body]
                        ifFalse: [self doReduceLiterals; restartCompilation]]

_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

Reply via email to