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