2009/12/20 Igor Stasenko <siguctua@gmail.com>:
2009/12/20 Marcus Denker <marcus.denker@inria.fr>:
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: 1054@512 to: 1037@504. Â self addMMEFrom: 651@559 to: 643@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 Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
-- Best regards, Igor Stasenko AKA sig.
_______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr 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]]