2009/12/21 Lukas Renggli <[email protected]>: > You might want to have a look at SmaCC and how it generates the > scanner code: a huge state machine implemented in a single method that > consumes the source code of a programming language. To compile the > method SmaCC repeatedly applies the "extract method" refactoring to > reduce the code into nicely sized (but still efficient) methods. > > Lukas >
Of course, that would have been a nice option too (more general). Above code is from 1994, not sure what was the status of SmaCC at that time... In case of symbolic expressions, more agressive transformation could occur, like common subexpression elimination... (run on symbolic expression tree rather than AST, because knowing there would be no side effect). Nicolas > 2009/12/21 Nicolas Cellier <[email protected]>: >> 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 >> > > > > -- > Lukas Renggli > http://www.lukas-renggli.ch > > _______________________________________________ > Pharo-project mailing list > [email protected] > http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project > _______________________________________________ Pharo-project mailing list [email protected] http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
