The Trunk: Compiler-eem.285.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: Compiler-eem.285.mcz

commits-2
Eliot Miranda uploaded a new version of Compiler to project The Trunk:
http://source.squeak.org/trunk/Compiler-eem.285.mcz

==================== Summary ====================

Name: Compiler-eem.285
Author: eem
Time: 5 August 2014, 7:52:00.572 pm
UUID: 99d40074-99f4-4e36-875e-e3f1cd61acfa
Ancestors: Compiler-eem.284

Lots more support for multiple bytecode sets.
Abstract out of InstructionStream:
        size of closure creation bytecode
        scanning for inst var reads and writes

Provide support for bytecode set specific
        callPrimitiveBytecode
        unusedBytecode

Provide support for different special literal and special
selector encodings.

Ensure bytecode sizing of backward branches use
negative distances.

Other:
Make the MessageNode transformations check for the
relevant block argument count.

=============== Diff against Compiler-eem.284 ===============

Item was added:
+ ----- Method: BlockLocalTempCounter class>>tempCountForBlockStartingAt:in: (in category 'instance creation') -----
+ tempCountForBlockStartingAt: startpc in: method
+ ^self new
+ tempCountForBlockAt: (method encoderClass pcOfBlockCreationBytecodeForBlockStartingAt: startpc in: method)
+ in: method!

Item was changed:
  ----- Method: BytecodeEncoder class>>bytecodeSize: (in category 'instruction stream support') -----
+ bytecodeSize: aByte
- bytecodeSize: bytecode
- "Answer the number of bytes in the (unextended) bytecode."
-
  self subclassResponsibility!

Item was added:
+ ----- Method: BytecodeEncoder class>>callPrimitiveCode (in category 'bytecode decoding') -----
+ callPrimitiveCode
+ "Answer the call primitive bytecode, if it exists in the encoder's byetcode set, or nil if not."
+ ^nil!

Item was added:
+ ----- Method: BytecodeEncoder class>>method:readsField: (in category 'scanning') -----
+ method: method readsField: varIndex
+ "Answer if method loads the instance variable indexed by varIndex."
+ ^self subclassResponsibility!

Item was added:
+ ----- Method: BytecodeEncoder class>>method:writesField: (in category 'scanning') -----
+ method: method writesField: varIndex
+ "Answer if method stores into the instance variable indexed by varIndex."
+ ^self subclassResponsibility!

Item was added:
+ ----- Method: BytecodeEncoder class>>pcOfBlockCreationBytecodeForBlockStartingAt:in: (in category 'bytecode decoding') -----
+ pcOfBlockCreationBytecodeForBlockStartingAt: startpc in: method
+ "Answer the pc of the push closure bytecode whose block starts at startpc in method."
+ ^self subclassResponsibility!

Item was added:
+ ----- Method: BytecodeEncoder class>>pushClosureBytecodeSize (in category 'bytecode decoding') -----
+ pushClosureBytecodeSize
+ "Answer the size of the push closure bytecode, if there is one."
+ ^self subclassResponsibility!

Item was added:
+ ----- Method: BytecodeEncoder class>>unusedBytecode (in category 'bytecode decoding') -----
+ unusedBytecode
+ "Answer the opcode of a single-byte unused bytecode, if it exists in the encoder's bytecode set, or nil if not."
+ ^nil!

Item was added:
+ ----- Method: BytecodeEncoder>>sizeCallPrimitive: (in category 'opcode sizing') -----
+ sizeCallPrimitive: primitiveIndex
+ ^self sizeOpcodeSelector: #genCallPrimitive: withArguments: {primitiveIndex}!

Item was added:
+ ----- Method: BytecodeEncoder>>sizeSendSpecial:numArgs: (in category 'opcode sizing') -----
+ sizeSendSpecial: specialSelectorIndex numArgs: nArgs
+ ^self sizeOpcodeSelector: #genSendSpecial:numArgs: withArguments: {specialSelectorIndex. nArgs}!

Item was changed:
  ----- Method: Decompiler>>decompile:in:method:using: (in category 'public access') -----
  decompile: aSelector in: aClass method: aMethod using: aConstructor
 
  | block node |
  constructor := aConstructor.
  method := aMethod.
  self initSymbols: aClass.  "create symbol tables"
  method isQuick
  ifTrue: [block := self quickMethod]
  ifFalse:
  [stack := OrderedCollection new: method frameSize.
  lastJumpIfPcStack := OrderedCollection new.
  caseExits := OrderedCollection new.
  statements := OrderedCollection new: 20.
  numLocalTemps := 0.
  super method: method pc: method initialPC.
  "skip primitive error code store if necessary"
+ (method primitive ~= 0 and: [self skipCallPrimitive; willStore]) ifTrue:
+ [pc := pc + (method encoderClass bytecodeSize: self firstByte).
- (method primitive ~= 0 and: [self willStore]) ifTrue:
- [pc := pc + 2.
  tempVars := tempVars asOrderedCollection].
  block := self blockTo: method endPC + 1.
  stack isEmpty ifFalse: [self error: 'stack not empty']].
  node := constructor
  codeMethod: aSelector
  block: block
  tempVars: tempVars
  primitive: method primitive
  class: aClass.
  method primitive > 0 ifTrue:
  [node removeAndRenameLastTempIfErrorCode].
  ^node preen!

Item was changed:
  ----- Method: Decompiler>>doClosureCopyCopiedValues:numArgs:blockSize: (in category 'control') -----
  doClosureCopyCopiedValues: blockCopiedValues numArgs: numArgs blockSize: blockSize
  | startpc savedTemps savedTempVarCount savedNumLocalTemps
   jump blockArgs blockTemps blockTempsOffset block |
  savedTemps := tempVars.
  savedTempVarCount := tempVarCount.
  savedNumLocalTemps := numLocalTemps.
  jump := blockSize + (startpc := pc).
+ numLocalTemps := BlockLocalTempCounter
+ tempCountForBlockStartingAt: pc
+ in: method.
- numLocalTemps := BlockLocalTempCounter tempCountForBlockAt: pc - 4 in: method.
  blockTempsOffset := numArgs + blockCopiedValues size.
  (blockStartsToTempVars notNil "implies we were intialized with temp names."
  and: [blockStartsToTempVars includesKey: pc])
  ifTrue:
  [tempVars := blockStartsToTempVars at: pc]
  ifFalse:
  [blockArgs := (1 to: numArgs) collect:
  [:i| (constructor
  codeTemp: i - 1
  named: 't', (tempVarCount + i) printString)
   beBlockArg].
  blockTemps := (1 to: numLocalTemps) collect:
  [:i| constructor
  codeTemp: i + blockTempsOffset - 1
  named: 't', (tempVarCount + i + numArgs) printString].
  tempVars := blockArgs, blockCopiedValues, blockTemps].
  numLocalTemps timesRepeat:
  [self interpretNextInstructionFor: self.
  stack removeLast].
  tempVarCount := tempVarCount + numArgs + numLocalTemps.
  block := self blockTo: jump.
  stack addLast: ((constructor
  codeArguments: (tempVars copyFrom: 1 to: numArgs)
  temps: (tempVars copyFrom: blockTempsOffset + 1 to: blockTempsOffset + numLocalTemps)
  block: block)
  pc: startpc;
  yourself).
  tempVars := savedTemps.
  tempVarCount := savedTempVarCount.
  numLocalTemps := savedNumLocalTemps!

Item was changed:
  ----- Method: Decompiler>>interpretNextInstructionFor: (in category 'private') -----
  interpretNextInstructionFor: client
 
  | code varNames |
 
  "Change false here will trace all state in Transcript."
+ true ifTrue: [^super interpretNextInstructionFor: client].
- true ifTrue: [^ super interpretNextInstructionFor: client].
 
  varNames := self class allInstVarNames.
  code := (self method at: pc) radix: 16.
+ Transcript cr; cr; print: pc; space; nextPutAll: '<' , code, '>'.
+ (varNames indexOf: 'stack') to: varNames size do:
+ [:i |
+ i <= 10 ifTrue: [Transcript cr] ifFalse: [Transcript space; space].
+ Transcript nextPutAll: (varNames at: i); nextPutAll: ': '; print: (self instVarAt: i)].
+ Transcript flush.
+ ^super interpretNextInstructionFor: client!
- Transcript cr; cr; print: pc; space;
- nextPutAll: '<' , code, '>'.
- 8 to: varNames size do:
- [:i | i <= 10 ifTrue: [Transcript cr]
- ifFalse: [Transcript space; space].
- Transcript nextPutAll: (varNames at: i);
- nextPutAll: ': '; print: (self instVarAt: i)].
- Transcript endEntry.
- ^ super interpretNextInstructionFor: client!

Item was changed:
  ----- Method: DecompilerConstructorForClosures>>codeMethod:block:tempVars:primitive:class: (in category 'constructor') -----
  codeMethod: selector block: block tempVars: vars primitive: primitive class: class
 
  | blockNode selectorNode visibleTemps invisibleTemps arguments temporaries properties |
  selectorNode := self codeSelector: selector code: nil.
  tempVars := vars.
  visibleTemps := OrderedCollection new.
  invisibleTemps := OrderedCollection new.
  tempVars do: [:t|
    ((t isIndirectTempVector or: [t scope >= 0])
  ifTrue: [visibleTemps]
  ifFalse: [invisibleTemps]) addLast: t].
  arguments := visibleTemps copyFrom: 1 to: nArgs.
  temporaries := visibleTemps copyFrom: nArgs + 1 to: visibleTemps size.
  block
  arguments: arguments;
  temporaries: temporaries.
  properties := method properties copy.
  (properties at: #onceCache ifAbsent: []) ifNotNil:
  [:onceCache|
  properties := properties copyWithout: (Association
  key: #onceCache
  value: onceCache)].
  blockNode := MethodNode new
  selector: selectorNode
  arguments: arguments
  precedence: selector precedence
  temporaries: temporaries
  block: block
+ encoder: (method encoderClass new initScopeAndLiteralTables
- encoder: (EncoderForV3PlusClosures new initScopeAndLiteralTables
  temps: visibleTemps, invisibleTemps
  literals: literalValues
  class: class)
  primitive: primitive
  properties: properties.
  blockNode properties method: blockNode.
  ^blockNode!

Item was added:
+ ----- Method: EncoderForV3 class>>method:readsField: (in category 'scanning') -----
+ method: method readsField: varIndex
+ "Answer if method loads the instance variable indexed by varIndex.
+ N.B. Don't assume the compiler uses the most compact encoding available.
+ 0-15 0000iiii Push Receiver Variable #iiii
+ 128 10000000 jjkkkkkk Push (Receiver Variable, Temporary Location, Literal Constant, Literal Variable) [jj] #kkkkkk
+ 132 10000100 iiijjjjj kkkkkkkk (Send, Send Super, Push Receiver Variable, Push Literal Constant, Push Literal Variable, Store Receiver Variable, Store-Pop Receiver Variable, Store Literal Variable)[iii] #kkkkkkkk jjjjj (for sends jjjjj = numArgs)"
+ | varIndexCode scanner |
+ varIndexCode := varIndex - 1.
+ method isReturnField ifTrue:
+ [^method returnField = varIndexCode].
+ ^(scanner := InstructionStream on: method) scanFor:
+ [:b|
+ b < 16
+ ifTrue: [b = varIndexCode]
+ ifFalse:
+ [b = 128
+ ifTrue: [scanner followingByte = varIndexCode and: [varIndexCode <= 63]]
+ ifFalse:
+ [b = 132
+ and: [(scanner followingByte between: 64 and: 95)
+ and: [scanner thirdByte = varIndexCode]]]]]!

Item was added:
+ ----- Method: EncoderForV3 class>>method:writesField: (in category 'scanning') -----
+ method: method writesField: varIndex
+ "Answer if method stores into the instance variable indexed by varIndex.
+ N.B. Don't assume the compiler uses the most compact encoding available.
+ 96-103 01100iii Pop and Store Receiver Variable #iii
+ 129 10000001 jjkkkkkk Store (Receiver Variable, Temporary Location, Illegal, Literal Variable) [jj] #kkkkkk
+ 130 10000010 jjkkkkkk Pop and Store (Receiver Variable, Temporary Location, Illegal, Literal Variable) [jj] #kkkkkk
+ 132 10000100 iiijjjjj kkkkkkkk (Send, Send Super, Push Receiver Variable, Push Literal Constant, Push Literal Variable, Store Receiver Variable, Store-Pop Receiver Variable, Store Literal Variable)[iii] #kkkkkkkk jjjjj (for sends jjjjj = numArgs)"
+ | varIndexCode scanner |
+ method isQuick ifTrue: [^false].
+ varIndexCode := varIndex - 1.
+ ^(scanner := InstructionStream on: method) scanFor:
+ [:b|
+ b >= 96
+ and: [b <= 103
+ ifTrue: [b - 96 = varIndexCode]
+ ifFalse:
+ [(b = 129 or: [b = 130])
+ ifTrue: [scanner followingByte = varIndexCode and: [varIndexCode <= 63]]
+ ifFalse:
+ [b = 132
+ and: [(scanner followingByte between: 160 and: 223)
+ and: [scanner thirdByte = varIndexCode]]]]]]!

Item was added:
+ ----- Method: EncoderForV3 class>>unusedBytecode (in category 'bytecode decoding') -----
+ unusedBytecode
+ "Answer the opcode of a single-byte unused bytecode, if it exists in the encoder's bytecode set, or nil if not."
+ ^126!

Item was added:
+ ----- Method: EncoderForV3>>genSendSpecial:numArgs: (in category 'bytecode generation') -----
+ genSendSpecial: specialSelectorIndex numArgs: nArgs
+ "See BlueBook page 596"
+ self assert: (specialSelectorIndex between: 1 and: Smalltalk specialSelectorSize).
+ self assert: nArgs = (Smalltalk specialNargsAt: specialSelectorIndex).
+ "Special selector sends.
+ 176-191 1011iiii Send Arithmetic Message #iiii
+ 192-207 1100iiii Send Special Message #iiii"
+ stream nextPut: specialSelectorIndex + 175!

Item was changed:
  ----- Method: EncoderForV3PlusClosures class>>bytecodeSize: (in category 'instruction stream support') -----
  bytecodeSize: bytecode
  "Answer the number of bytes in the bytecode."
  bytecode <= 125 ifTrue:
  [^1].
  bytecode >= 176 ifTrue:
  [^1].
  bytecode >= 160 ifTrue: "long jumps"
  [^2].
  bytecode >= 144 ifTrue: "short jumps"
  [^1].
  "extensions"
  bytecode >= 128 ifTrue:
  [^#(2 2 2 2 3 2 2 1 1 1 2 nil 3 3 3 4) at: bytecode - 127].
  ^nil!

Item was added:
+ ----- Method: EncoderForV3PlusClosures class>>pcOfBlockCreationBytecodeForBlockStartingAt:in: (in category 'bytecode decoding') -----
+ pcOfBlockCreationBytecodeForBlockStartingAt: startpc in: method
+ "Answer the pc of the push closure bytecode whose block starts at startpc in method.
+ 143   10001111 llllkkkk jjjjjjjj iiiiiiii Push Closure Num Copied llll Num Args kkkk BlockSize jjjjjjjjiiiiiiii"
+ ^startpc - 4!

Item was added:
+ ----- Method: EncoderForV3PlusClosures class>>pushClosureBytecodeSize (in category 'bytecode decoding') -----
+ pushClosureBytecodeSize
+ "Answer the size of the push closure bytecode.
+ 143   10001111 llllkkkk jjjjjjjj iiiiiiii Push Closure Num Copied llll Num Args kkkk BlockSize jjjjjjjjiiiiiiii"
+ ^4!

Item was removed:
- ----- Method: MessageNode>>checkBlock:as:from: (in category 'private') -----
- checkBlock: node as: nodeName from: encoder
-
- ^self checkBlock: node as: nodeName from: encoder maxArgs: 0!

Item was changed:
  ----- Method: MessageNode>>sizeCodeForRepeat:value: (in category 'code generation') -----
  sizeCodeForRepeat: encoder value: forValue
  "L1: ... Jmp(L1) nil (nil for value only);"
  | loopSize |
+ "We assume long backward branches are always maximal size branches."
+ loopSize := (receiver sizeCodeForEvaluatedEffect: encoder) + (encoder sizeJumpLong: -1).
- loopSize := (receiver sizeCodeForEvaluatedEffect: encoder) + (encoder sizeJumpLong: 1).
  sizes := Array with: loopSize.
  ^loopSize + (forValue ifTrue: [encoder sizePushSpecialLiteral: nil] ifFalse: [0])!

Item was changed:
  ----- Method: MessageNode>>sizeCodeForWhile:value: (in category 'code generation') -----
  sizeCodeForWhile: encoder value: forValue
  "L1: ... Bfp(L2) ... Jmp(L1) L2: nil (nil for value only);
  justStmt, wholeLoop, justJump."
  | cond stmt stmtSize loopSize branchSize |
  cond := receiver.
  stmt := arguments at: 1.
+ "We assume long backward branches are always maximal size branches."
+ stmtSize := (stmt sizeCodeForEvaluatedEffect: encoder) + (encoder sizeJumpLong: -1).
- stmtSize := (stmt sizeCodeForEvaluatedEffect: encoder) + (encoder sizeJumpLong: 1).
  branchSize := self
  sizeCode: encoder
  forBranchOn: selector key == #whileFalse:  "Btp for whileFalse"
  dist: stmtSize.
  loopSize := (cond sizeCodeForEvaluatedValue: encoder) + branchSize + stmtSize.
  sizes := Array with: stmtSize with: loopSize.
  ^loopSize + (forValue ifTrue: [encoder sizePushSpecialLiteral: nil] ifFalse: [0])!

Item was changed:
  ----- Method: MessageNode>>transformBoolean: (in category 'macro transformations') -----
  transformBoolean: encoder
  ^self
  checkBlock: (arguments at: 1)
  as: 'argument'
+ from: encoder
+ maxArgs: 0!
- from: encoder!

Item was changed:
  ----- Method: MessageNode>>transformCase: (in category 'macro transformations') -----
  transformCase: encoder
 
  | caseNode |
  caseNode := arguments first.
+ (caseNode isMemberOf: BraceNode) ifFalse: [^false].
+ (caseNode blockAssociationCheck: encoder) ifFalse: [^false].
+ (arguments size = 1
+ or: [self checkBlock: arguments last as: 'otherwise arg' from: encoder maxArgs: 0]) ifFalse:
+ [^false].
+ caseNode elements do:
+ [:messageNode |
- (caseNode isMemberOf: BraceNode) ifFalse: [ ^false ].
- (caseNode blockAssociationCheck: encoder) ifFalse: [ ^false ].
- (arguments size = 1 or: [
- self checkBlock: arguments last as: 'otherwise arg' from: encoder ]) ifFalse: [
- ^false ].
- caseNode elements do: [ :messageNode |
  messageNode receiver noteOptimizedIn: self.
+ messageNode arguments first noteOptimizedIn: self].
+ arguments size = 2 ifTrue:
+ [arguments last noteOptimizedIn: self].
- messageNode arguments first noteOptimizedIn: self ].
- arguments size = 2 ifTrue: [ arguments last noteOptimizedIn: self ].
  ^true!

Item was changed:
  ----- Method: MessageNode>>transformIfFalseIfTrue: (in category 'macro transformations') -----
  transformIfFalseIfTrue: encoder
+ ^(self checkBlock: (arguments at: 1) as: 'False arg' from: encoder maxArgs: 0)
+   and: [(self checkBlock: (arguments at: 2) as: 'True arg' from: encoder maxArgs: 0)
- ^(self checkBlock: (arguments at: 1) as: 'False arg' from: encoder)
-   and: [(self checkBlock: (arguments at: 2) as: 'True arg' from: encoder)
    and: [selector := SelectorNode new key: #ifTrue:ifFalse: code: #macro.
  arguments swap: 1 with: 2.
  arguments do: [:arg| arg noteOptimizedIn: self].
  true]]!

Item was changed:
  ----- Method: MessageNode>>transformIfTrueIfFalse: (in category 'macro transformations') -----
  transformIfTrueIfFalse: encoder
+ ^(self checkBlock: (arguments at: 1) as: 'True arg' from: encoder maxArgs: 0)
+   and: [(self checkBlock: (arguments at: 2) as: 'False arg' from: encoder maxArgs: 0)
- ^(self checkBlock: (arguments at: 1) as: 'True arg' from: encoder)
-   and: [(self checkBlock: (arguments at: 2) as: 'False arg' from: encoder)
    and: [arguments do: [:arg| arg noteOptimizedIn: self].
  true]]!

Item was changed:
  ----- Method: MessageNode>>transformRepeat: (in category 'macro transformations') -----
  transformRepeat: encoder
  "answer true if this #repeat message can be optimized"
 
+ ^(self checkBlock: receiver as: 'receiver' from: encoder maxArgs: 0)
- ^(self checkBlock: receiver as: 'receiver' from: encoder)
    and: [receiver noteOptimizedIn: self.
  true]!

Item was changed:
  ----- Method: MessageNode>>transformWhile: (in category 'macro transformations') -----
  transformWhile: encoder
+ (self checkBlock: receiver as: 'receiver' from: encoder maxArgs: 0) ifFalse:
- (self checkBlock: receiver as: 'receiver' from: encoder) ifFalse:
  [^false].
  arguments size = 0 ifTrue:  "transform bodyless form to body form"
  [selector := SelectorNode new
  key: (special = 10 ifTrue: [#whileTrue:] ifFalse: [#whileFalse:])
  code: #macro.
  arguments := Array with: ((BlockNode withJust: NodeNil) noteOptimizedIn: self).
  receiver noteOptimizedIn: self.
  ^true].
  ^(self transformBoolean: encoder)
    and: [receiver noteOptimizedIn: self.
  arguments first noteOptimizedIn: self.
  true]!

Item was added:
+ LiteralNode subclass: #SpecialLiteralNode
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Compiler-ParseNodes'!

Item was added:
+ ----- Method: SpecialLiteralNode>>emitCodeForValue:encoder: (in category 'code generation (closures)') -----
+ emitCodeForValue: stack encoder: encoder
+ stack push: 1.
+ encoder genPushSpecialLiteral: key!

Item was added:
+ ----- Method: SpecialLiteralNode>>sizeCodeForValue: (in category 'code generation (closures)') -----
+ sizeCodeForValue: encoder
+ ^encoder sizePushSpecialLiteral: key!

Item was added:
+ SelectorNode subclass: #SpecialSelectorNode
+ instanceVariableNames: ''
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'Compiler-ParseNodes'!

Item was added:
+ ----- Method: SpecialSelectorNode>>emitCode:args:encoder:super: (in category 'code generation') -----
+ emitCode: stack args: nArgs encoder: encoder super: supered
+ "Generate a special selector send.
+ A super send of a special selector must be handled like a normal send."
+ supered
+ ifTrue:
+ [super emitCode: stack args: nArgs encoder: encoder super: supered]
+ ifFalse:
+ [stack pop: nArgs.
+ encoder genSendSpecial: code numArgs: nArgs]!

Item was added:
+ ----- Method: SpecialSelectorNode>>sizeCode:args:super: (in category 'code generation') -----
+ sizeCode: encoder args: nArgs super: supered
+ "Size a special selector send.
+ A super send of a special selector must be handled like a normal send."
+ ^supered
+ ifTrue: [super sizeCode: encoder args: nArgs super: supered]
+ ifFalse: [encoder sizeSendSpecial: code numArgs: nArgs]!

Item was changed:
  ----- Method: VariableNode class>>initialize (in category 'class initialization') -----
  initialize    "VariableNode initialize.  Decompiler initialize"
  | encoder |
  encoder := Encoder new.
  StdVariables := Dictionary new: 16.
  encoder
  fillDict: StdVariables
  with: VariableNode
  mapping: #('self' 'thisContext' 'super' 'nil' 'false' 'true' )
  to: (Array with: LdSelf with: LdThisContext with: LdSuper)
  , (Array with: LdNil with: LdFalse with: LdTrue).
  StdSelectors := Dictionary new: 64.
  encoder
  fillDict: StdSelectors
+ with: SpecialSelectorNode
- with: SelectorNode
  mapping: ((1 to: Smalltalk specialSelectorSize) collect:
  [:i | Smalltalk specialSelectorAt: i])
+ to: (1 to: Smalltalk specialSelectorSize) asArray.
- to: (SendPlus to: SendPlus + 31).
  StdLiterals := PluggableDictionary new equalBlock: [ :x :y | x literalEqual: y ].
  encoder
  fillDict: StdLiterals
  with: LiteralNode
  mapping: #(-1 0 1 2 )
  to: (LdMinus1 to: LdMinus1 + 3).
  encoder initScopeAndLiteralTables.
 
  NodeNil := encoder encodeVariable: 'nil'.
  NodeTrue := encoder encodeVariable: 'true'.
  NodeFalse := encoder encodeVariable: 'false'.
  NodeSelf := encoder encodeVariable: 'self'.
  NodeThisContext := encoder encodeVariable: 'thisContext'.
  NodeSuper := encoder encodeVariable: 'super'!