[Vm-dev] VM Maker: VMMaker.oscog-eem.1317.mcz

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Thu May 21 20:17:19 UTC 2015


2015-05-21 6:56 GMT+02:00 <commits at source.squeak.org>:

>
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.1317.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.1317
> Author: eem
> Time: 20 May 2015, 9:56:04.05 pm
> UUID: a7e082b5-1ad8-42ef-84cc-0079605c8440
> Ancestors: VMMaker.oscog-eem.1316
>
> Cogit:
> Fix the performance regression on x86 in r3308
> VMMaker.oscog-eem.1178 through the use of the XCHG
> instruction in CogIA32Compiler>>genPushRegisterArgsForNumArgs:.
> Since SendNumArgsReg is not live with small arity sends
> it can be used instead of TempReg.
>
> Replace uses of the magic constant 2 with
> NumSendTrampolines - 2 (actually <= 2 =>
> < (NumSendTrampolines - 1)) where appropriate. Hence
> NumSendTrampolines moved to CogCompilationConstants.
>
> Fix bug on ARM with pc-relative addressing. pc-relative
> addressing can only be used within a method because of relocation.
> The old code would use pc-relative addressing to access
> trampolines for methods close to the trampolines and then
> not for methods further away, causing changes in the code
> generated by compileInterpreterPrimitive:.
>
> To support this, rationalize the PIC compilation code, being sure
> to initialize and concretize methodLabel at the start of each PIC.
> Don't bother to pass PIC size as a parameter given we have
> PIC-specific header-filling routines now.
>
> Spur:
> Firm up the checkTraversableSortedFreeList assert routine to
> check that the list is traversable from lastFreeChunk, not just
> firstFreeChunk.
>
> Slang:
> Make promoteArithmeticTypes:and: obey C99's promotion rules
> more closely in an effort to generate more stable sources.
> Types were flipping between sqInt & usqInt for variables that
> were assigned both types, so that one generation would produce
> one type and a subsequent one another (Set/Dictionary hashing?).
>
> Simulation/In-image Compilation:
> Fix varBaseAddress calculations for in-image compilation so that
> it jives with real compilation.
>
> Allow setting of recordPrimTrace through initializationOptions.
>
> =============== Diff against VMMaker.oscog-eem.1316 ===============
>
> Item was changed:
>   ----- Method: CCodeGenerator>>promoteArithmeticTypes:and: (in category
> 'type inference') -----
>   promoteArithmeticTypes: firstType and: secondType
> +       "Answer the return type for an arithmetic send.  This is so that
> the inliner can still inline
> +        simple expressions.  Deal with pointer arithmetic, floating point
> arithmetic and promotion."
> +       | firstSize secondSize |
> -       "Answer the return type for an arithmetic sendThis is so that the
> inliner can still
> -        inline simple expressions.  Deal with pointer arithmetic,
> floating point arithmetic
> -        and promotion."
>         ((#(#double float) includes: firstType)
>          or: [#(#double float) includes: secondType]) ifTrue:
>                 [^(firstType = #float and: [secondType = #float])
>                         ifTrue: [#float]
>                         ifFalse: [#double]].
>         "deal with unknowns, answering nil."
>         (firstType isNil or: [secondType isNil]) ifTrue:
>                 [^nil].
> +       "Deal with promotion; answer the longest type, defaulting to the
> recever if they're the same.
> +        See e.g. section 6.3.1.8 Usual arithmetic conversions, from the
> C99 standard:
> +               Otherwise, the integer promotions are performed on both
> operands
> +               Then the following rules are applied to the promoted
> operands:
> +
> +                       If both operands have the same type, then no
> further conversion is needed.
> +
> +                       Otherwise, if both operands have signed integer
> types or both have unsigned integer
> +                       types, the operand with the type of lesser integer
> conversion rank is converted to the
> +                       type of the operand with greater rank.
> +
> +                       Otherwise, if the operand that has unsigned
> integer type has rank greater or equal to
> +                       the rank of the type of the other operand, then
> the operand with signed integer type
> +                       is converted to the type of the operand with
> unsigned integer type.
> +
> +                       Otherwise, if the type of the operand with signed
> integer type can represent all of the
> +                       values of the type of the operand with unsigned
> integer type, then the operand with
> +                       unsigned integer type is converted to the type of
> the operand with signed integer type.
> +
> +                       Otherwise, both operands are converted to the
> unsigned integer type corresponding to
> +                       the type of the operand with signed integer type.
> +
> +       It is important to choose deterministically to get stable source
> generation.  So if the types have
> +       the same size but differ in signedness we choose the unsigned
> type, which is in partial agreement
> +       with the above"
> +       ^(firstSize := self sizeOfIntegralCType: firstType) = (secondSize
> := self sizeOfIntegralCType: secondType)
> +               ifTrue:
> +                       [(firstType first = $u)
> +                               ifTrue: [firstType]
> +                               ifFalse: [(secondType first = $u) ifTrue:
> [secondType] ifFalse: [firstType]]]
> +               ifFalse:
> +                       [firstSize > secondSize ifTrue: [firstType]
> ifFalse: [secondType]]!
> -       "deal with promotion; answer the longest type, defaulting to the
> recever if they're the same"
> -       ^(self sizeOfIntegralCType: firstType) >= (self
> sizeOfIntegralCType: secondType)
> -               ifTrue: [firstType]
> -               ifFalse: [secondType]!
>
>
+1

That's how I wrote it a few weeks ago in my experimental branch:
http://smalltalkhub.com/mc/nice/NiceVMExperiments/main

promoteIntegerArithmeticTypes: firstType and: secondType
    "Answer the return type for an arithmetic send. This is so that the
inliner can still
     inline simple expressions.  Deal with integer arithmetic and
promotion."
    | length1 length2 |
    length1 := self sizeOfIntegralCType: firstType.
    length2 := self sizeOfIntegralCType: secondType.
    length1 > length2 ifTrue: [^firstType].
    length2 > length1 ifTrue: [^secondType].
    firstType first = $u ifTrue: [^firstType].
    secondType first = $u ifTrue: [^secondType].
    ^firstType



> Item was changed:
>   ----- Method: CoInterpreter>>varBaseAddress (in category 'cog jit
> support') -----
>   varBaseAddress
>         <api>
>         <returnTypeC: #usqInt>
> +       ^self cCode: [(self addressOf: stackPointer) asUnsignedInteger -
> 16r42]
> +               inSmalltalk: [cogit fakeVarBaseAddress]!
> -       ^(self addressOf: stackPointer) asUnsignedInteger - 16r42!
>
> Item was changed:
>   ----- Method: CogARMCompiler>>loadCwInto: (in category 'generate machine
> code - support') -----
>   loadCwInto: destReg
>         "Load the operand into the destination register, answering
>          the size of the instructions generated to do so."
>         | operand distance |
>         operand := operands at: 0.
>         "First try and encode as a pc-relative reference..."
> +       (cogit addressIsInCurrentCompilation: operand) ifTrue:
> +               [distance := operand - (address + 8).
> -       (cogit addressIsInCodeZone: operand) ifTrue:
> -               [distance := operand  - (address + 8).
>                  self rotateable8bitImmediate: distance
>                         ifTrue: [ :rot :immediate |
>                                 self machineCodeAt: 0 put: (self add:
> destReg rn: PC imm: immediate ror: rot).
>                                 ^4]
>                         ifFalse:
>                                 [self rotateable8bitImmediate: distance
> negated
>                                         ifTrue: [ :rot :immediate |
>                                                 self machineCodeAt: 0 put:
> (self sub: destReg rn: PC imm: immediate ror: rot).
>                                                 ^4]
>                                         ifFalse: []]].
>         "If this fails, use the conventional and painfully long 4
> instruction sequence."
>         ^self at: 0 moveCw: operand intoR: destReg!
>
> Item was changed:
>   VMStructType subclass: #CogAbstractInstruction
>         instanceVariableNames: 'opcode machineCodeSize maxSize machineCode
> operands address dependent cogit objectMemory bcpc'
>         classVariableNames: 'NumOperands'
> +       poolDictionaries: 'CogCompilationConstants CogRTLOpcodes'
> -       poolDictionaries: 'CogRTLOpcodes'
>         category: 'VMMaker-JIT'!
>
>   !CogAbstractInstruction commentStamp: 'eem 4/21/2015 09:12' prior: 0!
>   I am an abstract instruction generated by the Cogit.  I am subsequently
> concretized to machine code for the current processor.  A sequence of
> concretized CogAbstractInstructions are concatenated to form the code for a
> CogMethod.  I am an abstract class.  My concrete subclasses concretize to
> the machine code of a specific processor.
>
>   Instance Variables
>         address:                        <Integer>
>         bcpc:                           <Integer>
>         cogit:                          <Cogit>
>         dependent:                      <AbstractInstruction|nil>
>         machineCode:            <CArray on: (ByteArray|Array)>
>         machineCodeSize:        <Integer>
>         maxSize:                        <Integer>
>         objectMemory:           <NewCoObjectMemory|SpurCoMemoryManager etc>
>         opcode:                 <Integer>
>         operands:                       <CArray on: Array>
>
>   address
>         - the address at which the instruction will be generated
>
>   bcpc
>         - the bytecode pc for which the instruction was generated;
> simulation only
>
>   cogit
>         - the Cogit assembling the receiver; simulation only
>
>   dependent
>         - a reference to another instruction which depends on the
> receiver, if any; in C this is a pointer
>
>   machineCode
>         - the array of machine code the receiver generates when concretized
>
>   machineCodeSize
>         - the size of machineCode in bytes
>
>   maxSize
>         - the maximum size of machine code that the current instruction
> will generate, in bytes
>
>   objectMemory
>         - the memory manager for the system; simulation only
>
>   opcode
>         - the opcode for the receiver which defines which abstract opcode
> it represents; see CogRTLOpcodes class>>initialize and
> CogAbstractInstruction subclass initialize methods
>
>   operands
>         - the array containing any operands the instruction may have; the
> opcode defines implicitly how many operands are consdered!
>
> Item was changed:
>   SharedPool subclass: #CogCompilationConstants
>         instanceVariableNames: ''
> +       classVariableNames: 'BadRegisterSet NumSendTrampolines
> SSBaseOffset SSConstant SSIllegal SSRegister SSSpill'
> -       classVariableNames: 'BadRegisterSet SSBaseOffset SSConstant
> SSIllegal SSRegister SSSpill'
>         poolDictionaries: ''
>         category: 'VMMaker-JIT'!
>
> Item was changed:
>   ----- Method: CogIA32Compiler>>genPushRegisterArgsForNumArgs: (in
> category 'smalltalk calling convention') -----
>   genPushRegisterArgsForNumArgs: numArgs
> +       "Ensure that the register args are pushed before the retpc for
> arity <= self numRegArgs.  This
> +        won't be as clumsy on a RISC.  But putting the receiver and args
> above the return address
> +        means the CoInterpreter has a single machine-code frame format
> which saves us a lot of work.
> +        N.B. Take great care to /not/ smash TempReg, which is used in
> directed send marshalling.
> +        We could use XCHG to swap the ReceiverResultReg and top-of-stack
> return address, pushing the
> +        the ret pc (now in ReceiverResultReg) later, but XCHG is very
> slow.  We can use SendNumArgsReg
> +        because it is only live in sends of arity >= (NumSendTrampolines
> - 1)."
> +       self assert: cogit numRegArgs < (NumSendTrampolines - 1).
> -       "Ensure that the register args are pushed before the retpc for
> arity <= self numRegArgs."
> -       "This won't be as clumsy on a RISC.  But putting the receiver and
> -        args above the return address means the CoInterpreter has a
> -        single machine-code frame format which saves us a lot of work."
>         numArgs <= cogit numRegArgs ifTrue:
>                 [self assert: cogit numRegArgs <= 2.
> +                false "these two variants show the same performance on
> Intel Core i7, but the second one may be shorter."
> +                       ifTrue:
> +                               [cogit MoveMw: 0 r: SPReg R:
> SendNumArgsReg. "Save return pc"
> +                                numArgs > 0 ifTrue:
> +                                       [cogit PushR: Arg0Reg.
> +                                        numArgs > 1 ifTrue:
> +                                               [cogit PushR: Arg1Reg]].
> +                                cogit PushR: SendNumArgsReg.
> +                                cogit MoveR: ReceiverResultReg Mw:
> objectMemory wordSize * (1 + numArgs) r: SPReg]
> +                       ifFalse:
> +                               ["a.k.a.
> +                                       cogit gen: XCHGMwrR operand: 0
> operand: SPReg operand: ReceiverResultReg.
> +                                 but XCHG is slow."
> +                                cogit MoveMw: 0 r: SPReg R:
> SendNumArgsReg. "Save return pc"
> +                                cogit MoveR: ReceiverResultReg Mw: 0 r:
> SPReg.
> +                                numArgs > 0 ifTrue:
> +                                       [cogit PushR: Arg0Reg.
> +                                        numArgs > 1 ifTrue:
> +                                               [cogit PushR: Arg1Reg]].
> +                                cogit PushR: SendNumArgsReg]] "Restore
> return address"!
> -                "N.B. Take great care to /not/ smash TempReg, which is
> used in directed send marshalling."
> -                "Swap the return address with ReceiverResultReg"
> -                cogit gen: XCHGMwrR operand: 0 operand: SPReg operand:
> ReceiverResultReg. "Save return address; replace with receiver"
> -                numArgs > 0 ifTrue:
> -                       [cogit PushR: Arg0Reg.
> -                        numArgs > 1 ifTrue:
> -                               [cogit PushR: Arg1Reg]].
> -               cogit PushR: ReceiverResultReg.
> -               "Reload ReceiverResultReg"
> -               cogit MoveMw: numArgs + 1 * objectMemory wordSize r: SPReg
> R: ReceiverResultReg]!
>
> Item was changed:
>   CogClass subclass: #Cogit
>         instanceVariableNames: 'coInterpreter objectMemory
> objectRepresentation processor threadManager methodZone methodZoneBase
> codeBase minValidCallAddress lastNInstructions simulatedAddresses
> simulatedTrampolines simulatedVariableGetters simulatedVariableSetters
> printRegisters printInstructions compilationTrace clickConfirm breakPC
> breakBlock singleStep guardPageSize traceFlags traceStores breakMethod
> methodObj initialPC endPC methodOrBlockNumArgs inBlock needsFrame
> hasYoungReferent primitiveIndex backEnd callerSavedRegMask postCompileHook
> primInvokeLabel methodLabel stackCheckLabel blockEntryLabel
> blockEntryNoContextSwitch blockNoContextSwitchOffset stackOverflowCall
> sendMiss missOffset entryPointMask checkedEntryAlignment
> uncheckedEntryAlignment cmEntryOffset entry cmNoCheckEntryOffset
> noCheckEntry picMNUAbort picInterpretAbort endCPICCase0 endCPICCase1
> numPICCases firstCPICCaseOffset cPICCaseSize cPICEndSize closedPICSize
> openPICSize fixups abstractOpcodes annotations generatorTable
> primitiveGeneratorTable byte0 byte1 byte2 byte3 bytecodePC
> bytecodeSetOffset opcodeIndex numAbstractOpcodes annotationIndex
> blockStarts blockCount labelCounter cStackAlignment expectedSPAlignment
> expectedFPAlignment codeModified maxLitIndex ceMethodAbortTrampoline
> cePICAbortTrampoline ceCheckForInterruptTrampoline ceCPICMissTrampoline
> ceReturnToInterpreterTrampoline ceBaseFrameReturnTrampoline
> ceSendMustBeBooleanAddTrueTrampoline ceSendMustBeBooleanAddFalseTrampoline
> ceCannotResumeTrampoline ceEnterCogCodePopReceiverReg
> ceCallCogCodePopReceiverReg ceCallCogCodePopReceiverAndClassRegs
> cePrimReturnEnterCogCode cePrimReturnEnterCogCodeProfiling
> ceNonLocalReturnTrampoline ceFetchContextInstVarTrampoline
> ceStoreContextInstVarTrampoline ceEnclosingObjectTrampoline
> ceCaptureCStackPointers ceFlushICache ceCheckFeaturesFunction
> ceTraceLinkedSendTrampoline ceTraceBlockActivationTrampoline
> ceTraceStoreTrampoline ceGetSP ordinarySendTrampolines superSendTrampolines
> directedSuperSendTrampolines dynamicSuperSendTrampolines
> outerSendTrampolines selfSendTrampolines firstSend lastSend
> realCEEnterCogCodePopReceiverReg realCECallCogCodePopReceiverReg
> realCECallCogCodePopReceiverAndClassRegs trampolineTableIndex
> trampolineAddresses objectReferencesInRuntime runtimeObjectRefIndex
> cFramePointerInUse debugPrimCallStackOffset ceTryLockVMOwner
> ceUnlockVMOwner cogMethodSurrogateClass cogBlockMethodSurrogateClass extA
> extB numIRCs indexOfIRC theIRCs implicitReceiverSendTrampolines
> nsSendCacheSurrogateClass tempOop'
> +       classVariableNames: 'AltBlockCreationBytecodeSize
> AltFirstSpecialSelector AltNSSendIsPCAnnotated AnnotationConstantNames
> AnnotationShift AnnotationsWithBytecodePCs BlockCreationBytecodeSize Debug
> DisplacementMask DisplacementX2N EagerInstructionDecoration FirstAnnotation
> FirstSpecialSelector HasBytecodePC IsAbsPCReference IsAnnotationExtension
> IsDirectedSuperSend IsDisplacementX2N IsNSDynamicSuperSend
> IsNSImplicitReceiverSend IsNSSelfSend IsNSSendCall IsObjectReference
> IsRelativeCall IsSendCall IsSuperSend MapEnd MaxCompiledPrimitiveIndex
> MaxStackAllocSize MaxX2NDisplacement NSCClassTagIndex
> NSCEnclosingObjectIndex NSCNumArgsIndex NSCSelectorIndex NSCTargetIndex
> NSSendIsPCAnnotated NumObjRefsInRuntime NumOopsPerNSC NumTrampolines
> ProcessorClass'
> -       classVariableNames: 'AltBlockCreationBytecodeSize
> AltFirstSpecialSelector AltNSSendIsPCAnnotated AnnotationConstantNames
> AnnotationShift AnnotationsWithBytecodePCs BlockCreationBytecodeSize Debug
> DisplacementMask DisplacementX2N EagerInstructionDecoration FirstAnnotation
> FirstSpecialSelector HasBytecodePC IsAbsPCReference IsAnnotationExtension
> IsDirectedSuperSend IsDisplacementX2N IsNSDynamicSuperSend
> IsNSImplicitReceiverSend IsNSSelfSend IsNSSendCall IsObjectReference
> IsRelativeCall IsSendCall IsSuperSend MapEnd MaxCompiledPrimitiveIndex
> MaxStackAllocSize MaxX2NDisplacement NSCClassTagIndex
> NSCEnclosingObjectIndex NSCNumArgsIndex NSCSelectorIndex NSCTargetIndex
> NSSendIsPCAnnotated NumObjRefsInRuntime NumOopsPerNSC NumSendTrampolines
> NumTrampolines ProcessorClass'
>         poolDictionaries: 'CogCompilationConstants CogMethodConstants
> CogRTLOpcodes VMBasicConstants VMBytecodeConstants VMObjectIndices
> VMStackFrameOffsets'
>         category: 'VMMaker-JIT'!
>   Cogit class
>         instanceVariableNames: 'generatorTable primitiveTable'!
>
>   !Cogit commentStamp: 'eem 4/6/2015 15:56' prior: 0!
>   I am the code generator for the Cog VM.  My job is to produce machine
> code versions of methods for faster execution and to manage inline caches
> for faster send performance.  I can be tested in the current image using my
> class-side in-image compilation facilities.  e.g. try
>
>         StackToRegisterMappingCogit genAndDis: (Integer >> #benchFib)
>
>   I have concrete subclasses that implement different levels of
> optimization:
>         SimpleStackBasedCogit is the simplest code generator.
>
>         StackToRegisterMappingCogit is the current production code
> generator  It defers pushing operands
>         to the stack until necessary and implements a register-based
> calling convention for low-arity sends.
>
>         StackToRegisterMappingCogit is an experimental code generator with
> support for counting
>         conditional branches, intended to support adaptive optimization.
>
>   coInterpreter <CoInterpreterSimulator>
>         the VM's interpreter with which I cooperate
>   methodZoneManager <CogMethodZoneManager>
>         the manager of the machine code zone
>   objectRepresentation <CogObjectRepresentation>
>         the object used to generate object accesses
>   processor <BochsIA32Alien|?>
>         the simulator that executes the IA32/x86 machine code I generate
> when simulating execution in Smalltalk
>   simulatedTrampolines <Dictionary of Integer -> MessageSend>
>         the dictionary mapping trap jump addresses to run-time routines
> used to warp from simulated machine code in to the Smalltalk run-time.
>   simulatedVariableGetters <Dictionary of Integer -> MessageSend>
>         the dictionary mapping trap read addresses to variables in
> run-time objects used to allow simulated machine code to read variables in
> the Smalltalk run-time.
>   simulatedVariableSetters <Dictionary of Integer -> MessageSend>
>         the dictionary mapping trap write addresses to variables in
> run-time objects used to allow simulated machine code to write variables in
> the Smalltalk run-time.
>   printRegisters printInstructions clickConfirm <Boolean>
>         flags controlling debug printing and code simulation
>   breakPC <Integer>
>         machine code pc breakpoint
>   cFramePointer cStackPointer <Integer>
>         the variables representing the C stack & frame pointers, which
> must change on FFI callback and return
>   selectorOop <sqInt>
>         the oop of the methodObj being compiled
>   methodObj <sqInt>
>         the bytecode method being compiled
>   initialPC endPC <Integer>
>         the start and end pcs of the methodObj being compiled
>   methodOrBlockNumArgs <Integer>
>         argument count of current method or block being compiled
>   needsFrame <Boolean>
>         whether methodObj or block needs a frame to execute
>   primitiveIndex <Integer>
>         primitive index of current method being compiled
>   methodLabel <CogAbstractOpcode>
>         label for the method header
>   blockEntryLabel <CogAbstractOpcode>
>         label for the start of the block dispatch code
>   stackOverflowCall <CogAbstractOpcode>
>         label for the call of ceStackOverflow in the method prolog
>   sendMissCall <CogAbstractOpcode>
>         label for the call of ceSICMiss in the method prolog
>   entryOffset <Integer>
>         offset of method entry code from start (header) of method
>   entry <CogAbstractOpcode>
>         label for the first instruction of the method entry code
>   noCheckEntryOffset <Integer>
>         offset of the start of a method proper (after the method entry
> code) from start (header) of method
>   noCheckEntry <CogAbstractOpcode>
>         label for the first instruction of start of a method proper
>   fixups <Array of <AbstractOpcode Label | nil>>
>         the labels for forward jumps that will be fixed up when reaching
> the relevant bytecode.  fixup shas one element per byte in methodObj's
> bytecode
>   abstractOpcodes <Array of <AbstractOpcode>>
>         the code generated when compiling methodObj
>   byte0 byte1 byte2 byte3 <Integer>
>         individual bytes of current bytecode being compiled in methodObj
>   bytecodePointer <Integer>
>         bytecode pc (same as Smalltalk) of the current bytecode being
> compiled
>   opcodeIndex <Integer>
>         the index of the next free entry in abstractOpcodes (this code is
> translated into C where OrderedCollection et al do not exist)
>   numAbstractOpcodes <Integer>
>         the number of elements in abstractOpcocdes
>   blockStarts <Array of <BlockStart>>
>         the starts of blocks in the current method
>   blockCount
>         the index into blockStarts as they are being noted, and hence
> eventually the total number of blocks in the current method
>   labelCounter <Integer>
>         a nicety for numbering labels not needed in the production system
> but probably not expensive enough to worry about
>   ceStackOverflowTrampoline <Integer>
>   ceSend0ArgsTrampoline <Integer>
>   ceSend1ArgsTrampoline <Integer>
>   ceSend2ArgsTrampoline <Integer>
>   ceSendNArgsTrampoline <Integer>
>   ceSendSuper0ArgsTrampoline <Integer>
>   ceSendSuper1ArgsTrampoline <Integer>
>   ceSendSuper2ArgsTrampoline <Integer>
>   ceSendSuperNArgsTrampoline <Integer>
>   ceSICMissTrampoline <Integer>
>   ceCPICMissTrampoline <Integer>
>   ceStoreCheckTrampoline <Integer>
>   ceReturnToInterpreterTrampoline <Integer>
>   ceBaseFrameReturnTrampoline <Integer>
>   ceSendMustBeBooleanTrampoline <Integer>
>   ceClosureCopyTrampoline <Integer>
>         the various trampolines (system-call-like jumps from machine code
> to the run-time).
>         See Cogit>>generateTrampolines for the mapping from trampoline to
> run-time
>         routine and then read the run-time routine for a funcitonal
> description.
>   ceEnterCogCodePopReceiverReg <Integer>
>         the enilopmart (jump from run-time to machine-code)
>   methodZoneBase <Integer>
>   !
>   Cogit class
>         instanceVariableNames: 'generatorTable primitiveTable'!
>
> Item was added:
> + ----- Method: Cogit>>addressIsInCurrentCompilation: (in category
> 'testing') -----
> + addressIsInCurrentCompilation: address
> +       ^address asUnsignedInteger >= methodLabel address
> +         and: [address < (methodLabel address + (1 << 16))]!
>
> Item was changed:
>   ----- Method: Cogit>>codeRangesFor: (in category 'disassembly') -----
>   codeRangesFor: cogMethod
>         "Answer a sequence of ranges of code for the main method and all
> of the blocks in a CogMethod.
>          N.B.  These are in order of block dispatch, _not_ necessarily
> address order in the method."
>         <doNotGenerate>
>         | pc end blockEntry starts |
>         cogMethod cmType = CMClosedPIC ifTrue:
>                 [end := (self addressOfEndOfCase: cogMethod cPICNumCases -
> 1 inCPIC: cogMethod) + cPICEndSize.
>                  ^{ CogCodeRange
>                                 from: cogMethod asInteger + (self sizeof:
> CogMethod)
>                                 to: end
>                                 cogMethod: cogMethod
>                                 startpc: nil }].
>         end := (self mapEndFor: cogMethod) - 1.
>         cogMethod blockEntryOffset = 0 ifTrue:
>                 [^{ CogCodeRange
>                                 from: cogMethod asInteger + (self sizeof:
> CogMethod)
>                                 to: end
>                                 cogMethod: cogMethod
> +                               startpc: (cogMethod cmType ~= CMOpenPIC
> ifTrue:
> +                                                       [coInterpreter
> startPCOfMethodHeader: cogMethod methodHeader]) }].
> -                               startpc: (coInterpreter
> startPCOfMethodHeader: cogMethod methodHeader) }].
>         pc := blockEntry := cogMethod blockEntryOffset + cogMethod
> asInteger.
>         starts := OrderedCollection with: cogMethod.
>         [pc < end] whileTrue:
>                 [| targetpc |
>                  targetpc := blockEntry.
>                  (backEnd isJumpAt: pc) ifTrue:
>                         [targetpc := backEnd jumpTargetPCAt: pc.
>                          targetpc < blockEntry ifTrue:
>                                 [starts add: (self cCoerceSimple: targetpc
> - (self sizeof: CogBlockMethod) to: #'CogBlockMethod *')]].
>                  pc := pc + (backEnd instructionSizeAt: pc)].
>         starts := starts asSortedCollection.
>         ^(1 to: starts size + 1) collect:
>                 [:i| | cogSubMethod nextpc |
>                 i <= starts size
>                         ifTrue:
>                                 [cogSubMethod := starts at: i.
>                                  nextpc := i < starts size ifTrue:
> [(starts at: i + 1) address] ifFalse: [blockEntry].
>                                  CogCodeRange
>                                         from: cogSubMethod address + (self
> sizeof: cogSubMethod)
>                                         to: nextpc - 1
>                                         cogMethod: cogSubMethod
>                                         startpc: (i = 1
>                                                                 ifTrue:
> [coInterpreter startPCOfMethodHeader: cogMethod methodHeader]
>                                                                 ifFalse:
> [cogSubMethod startpc])]
>                         ifFalse:
>                                 [CogCodeRange
>                                         from: blockEntry
>                                         to: end]]!
>
> Item was changed:
>   ----- Method: Cogit>>cogMNUPICSelector:receiver:methodOperand:numArgs:
> (in category 'in-line cacheing') -----
>   cogMNUPICSelector: selector receiver: rcvr methodOperand: methodOperand
> numArgs: numArgs
>         <api>
>         "Attempt to create a one-case PIC for an MNU.
>          The tag for the case is at the send site and so doesn't need to
> be generated."
>         <returnTypeC: #'CogMethod *'>
> +       | startAddress size end |
> -       | startAddress headerSize size end |
>         ((objectMemory isYoung: selector)
>          or: [(objectRepresentation inlineCacheTagForInstance: rcvr) =
> self picAbortDiscriminatorValue]) ifTrue:
>                 [^0].
>         coInterpreter
>                 compilationBreak: selector
>                 point: (objectMemory numBytesOf: selector)
>                 isMNUCase: true.
>         self assert: endCPICCase0 notNil.
>         startAddress := methodZone allocate: closedPICSize.
>         startAddress = 0 ifTrue:
>                 [coInterpreter callForCogCompiledCodeCompaction.
>                  ^0].
>         methodLabel
>                 address: startAddress;
>                 dependent: nil.
>         "stack allocate the various collections so that they
>          are effectively garbage collected on return."
>         self allocateOpcodes: numPICCases * 7 bytecodes: 0.
>         self compileMNUCPIC: (self cCoerceSimple: startAddress to:
> #'CogMethod *')
>                 methodOperand: methodOperand
>                 numArgs: numArgs.
>         self computeMaximumSizes.
> +       methodLabel concretizeAt: startAddress.
> +       size := self generateInstructionsAt: startAddress + (self sizeof:
> CogMethod).
> +       end := self outputInstructionsAt: startAddress + (self sizeof:
> CogMethod).
> -       headerSize := self sizeof: CogMethod.
> -       size := self generateInstructionsAt: startAddress + headerSize.
> -       end := self outputInstructionsAt: startAddress + headerSize.
>         "The missOffset is the same as the interpretOffset. On RISCs it
> includes an additional instruction."
>         self assert: missOffset = ((backEnd hasLinkRegister ifTrue:
> [backEnd callInstructionByteSize] ifFalse: [0])
>                                                                 +
> picInterpretAbort address + picInterpretAbort machineCodeSize -
> startAddress).
>         self assert: startAddress + cmEntryOffset = entry address.
>         ^self
>                 fillInCPICHeader: (self cCoerceSimple: startAddress to:
> #'CogMethod *')
> -               size: closedPICSize
>                 numArgs: numArgs
>                 numCases: 1
>                 hasMNUCase: true
>                 selector: selector !
>
> Item was changed:
>   ----- Method: Cogit>>cogOpenPICSelector:numArgs: (in category 'in-line
> cacheing') -----
>   cogOpenPICSelector: selector numArgs: numArgs
>         "Create an Open PIC.  Temporarily create a direct call of
> ceSendFromOpenPIC:.
>          Should become a probe of the first-level method lookup cache
> followed by a
>          call of ceSendFromOpenPIC: if the probe fails."
>         <returnTypeC: #'CogMethod *'>
> +       | startAddress codeSize mapSize end |
> -       | startAddress headerSize codeSize mapSize end |
>         coInterpreter
>                 compilationBreak: selector
>                 point: (objectMemory numBytesOf: selector)
>                 isMNUCase: false.
>         startAddress := methodZone allocate: openPICSize.
>         startAddress = 0 ifTrue:
>                 [^self cCoerceSimple: InsufficientCodeSpace to:
> #'CogMethod *'].
>         methodLabel
>                 address: startAddress;
>                 dependent: nil.
>         "stack allocate the various collections so that they
>          are effectively garbage collected on return."
>         self allocateOpcodes: 100 bytecodes: 0.
>         self compileOpenPIC: selector numArgs: numArgs.
>         self computeMaximumSizes.
>         methodLabel concretizeAt: startAddress.
> +       codeSize := self generateInstructionsAt: startAddress + (self
> sizeof: CogMethod).
> -       headerSize := self sizeof: CogMethod.
> -       codeSize := self generateInstructionsAt: startAddress + headerSize.
>         mapSize := self generateMapAt: startAddress + openPICSize - 1
> start: startAddress + cmNoCheckEntryOffset.
>         self assert: entry address - startAddress = cmEntryOffset.
> +       self assert: (methodZone roundUpLength: (self sizeof: CogMethod) +
> codeSize) + (methodZone roundUpLength: mapSize) <= openPICSize.
> +       end := self outputInstructionsAt: startAddress + (self sizeof:
> CogMethod).
> -       self assert: headerSize + codeSize + mapSize <= openPICSize.
> -       end := self outputInstructionsAt: startAddress + headerSize.
>         ^self
>                 fillInOPICHeader: (self cCoerceSimple: startAddress to:
> #'CogMethod *')
> -               size: openPICSize
>                 numArgs: numArgs
>                 selector: selector !
>
> Item was changed:
>   ----- Method:
> Cogit>>cogPICSelector:numArgs:Case0Method:Case1Method:tag:isMNUCase: (in
> category 'in-line cacheing') -----
>   cogPICSelector: selector numArgs: numArgs Case0Method: case0CogMethod
> Case1Method: case1MethodOrNil tag: case1Tag isMNUCase: isMNUCase
>         "Attempt to create a two-case PIC for case0CogMethod and
> case1Method,case1Tag.
>          The tag for case0CogMethod is at the send site and so doesn't
> need to be generated.
>          case1Method may be any of
>                 - a Cog method; link to its unchecked entry-point
>                 - a CompiledMethod; link to ceInterpretMethodFromPIC:
>                 - a CompiledMethod; link to
> ceMNUFromPICMNUMethod:receiver:"
>         <var: #case0CogMethod type: #'CogMethod *'>
>         <returnTypeC: #'CogMethod *'>
> +       | startAddress size end |
> -       | startAddress headerSize size end |
>         (objectMemory isYoung: selector) ifTrue:
>                 [^self cCoerceSimple: YoungSelectorInPIC to: #'CogMethod
> *'].
>         coInterpreter
>                 compilationBreak: selector
>                 point: (objectMemory numBytesOf: selector)
>                 isMNUCase: isMNUCase.
>         startAddress := methodZone allocate: closedPICSize.
>         startAddress = 0 ifTrue:
>                 [^self cCoerceSimple: InsufficientCodeSpace to:
> #'CogMethod *'].
>         methodLabel
>                 address: startAddress;
>                 dependent: nil.
>         "stack allocate the various collections so that they
>          are effectively garbage collected on return."
>         self allocateOpcodes: numPICCases * 7 bytecodes: 0.
>         self compileCPIC: (self cCoerceSimple: startAddress to:
> #'CogMethod *')
>                 Case0: case0CogMethod
>                 Case1Method: case1MethodOrNil
>                 tag: case1Tag
>                 isMNUCase: isMNUCase
>                 numArgs: numArgs.
>         self computeMaximumSizes.
> +       methodLabel concretizeAt: startAddress.
> +       size := self generateInstructionsAt: startAddress + (self sizeof:
> CogMethod).
> +       end := self outputInstructionsAt: startAddress + (self sizeof:
> CogMethod).
> -       headerSize := self sizeof: CogMethod.
> -       size := self generateInstructionsAt: startAddress + headerSize.
> -       end := self outputInstructionsAt: startAddress + headerSize.
>         "The missOffset is the same as the interpretOffset. On RISCs it
> includes an additional instruction."
>         self assert: missOffset = ((backEnd hasLinkRegister ifTrue:
> [backEnd callInstructionByteSize] ifFalse: [0])
>                                                                 +
> picInterpretAbort address + picInterpretAbort machineCodeSize -
> startAddress).
>         self assert: startAddress + cmEntryOffset = entry address.
>         self assert: endCPICCase0 address = (startAddress +
> firstCPICCaseOffset).
>         self assert: endCPICCase1 address = (startAddress +
> firstCPICCaseOffset + cPICCaseSize).
>         ^self
>                 fillInCPICHeader: (self cCoerceSimple: startAddress to:
> #'CogMethod *')
> -               size: closedPICSize
>                 numArgs: numArgs
>                 numCases: 2
>                 hasMNUCase: isMNUCase
>                 selector: selector !
>
> Item was added:
> + ----- Method: Cogit>>fakeVarBaseAddress (in category 'accessing') -----
> + fakeVarBaseAddress
> +       "We expect simulatedAddresses to have around 40 entries.  48 is
> hopefully a good maximum."
> +       <doNotGenerate>
> +       ^self fakeAddressFor: nil index: 48!
>
> Item was added:
> + ----- Method:
> Cogit>>fillInCPICHeader:numArgs:numCases:hasMNUCase:selector: (in category
> 'generate machine code') -----
> + fillInCPICHeader: pic numArgs: numArgs numCases: numCases hasMNUCase:
> hasMNUCase selector: selector
> +       <returnTypeC: #'CogMethod *'>
> +       <var: #pic type: #'CogMethod *'>
> +       <inline: true>
> +       self assert: (objectMemory isYoung: selector) not.
> +       pic cmType: CMClosedPIC.
> +       pic objectHeader: 0.
> +       pic blockSize: closedPICSize.
> +       pic methodObject: 0.
> +       pic methodHeader: 0.
> +       pic selector: selector.
> +       pic cmNumArgs: numArgs.
> +       pic cmRefersToYoung: false.
> +       pic cmUsageCount: self initialClosedPICUsageCount.
> +       pic cpicHasMNUCase: hasMNUCase.
> +       pic cPICNumCases: numCases.
> +       pic blockEntryOffset: 0.
> +       self assert: pic cmType = CMClosedPIC.
> +       self assert: pic selector = selector.
> +       self assert: pic cmNumArgs = numArgs.
> +       self assert: pic cPICNumCases = numCases.
> +       self assert: (backEnd callTargetFromReturnAddress: pic asInteger +
> missOffset) = (self picAbortTrampolineFor: numArgs).
> +       self assert: closedPICSize = (methodZone roundUpLength:
> closedPICSize).
> +       processor flushICacheFrom: pic asUnsignedInteger to: pic
> asUnsignedInteger + closedPICSize.
> +       ^pic!
>
> Item was removed:
> - ----- Method:
> Cogit>>fillInCPICHeader:size:numArgs:numCases:hasMNUCase:selector: (in
> category 'generate machine code') -----
> - fillInCPICHeader: pic size: size numArgs: numArgs numCases: numCases
> hasMNUCase: hasMNUCase selector: selector
> -       <returnTypeC: #'CogMethod *'>
> -       <var: #pic type: #'CogMethod *'>
> -       self assert: (objectMemory isYoung: selector) not.
> -       pic cmType: CMClosedPIC.
> -       pic objectHeader: 0.
> -       pic blockSize: size.
> -       pic methodObject: 0.
> -       pic methodHeader: 0.
> -       pic selector: selector.
> -       pic cmNumArgs: numArgs.
> -       pic cmRefersToYoung: false.
> -       pic cmUsageCount: self initialClosedPICUsageCount.
> -       pic cpicHasMNUCase: hasMNUCase.
> -       pic cPICNumCases: numCases.
> -       pic blockEntryOffset: 0.
> -       self assert: pic cmType = CMClosedPIC.
> -       self assert: pic selector = selector.
> -       self assert: pic cmNumArgs = numArgs.
> -       self assert: pic cPICNumCases = numCases.
> -       self assert: (backEnd callTargetFromReturnAddress: pic asInteger +
> missOffset) = (self picAbortTrampolineFor: numArgs).
> -       self assert: size = (methodZone roundUpLength: size).
> -       processor flushICacheFrom: pic asUnsignedInteger to: pic
> asUnsignedInteger + size.
> -       ^pic!
>
> Item was added:
> + ----- Method: Cogit>>fillInOPICHeader:numArgs:selector: (in category
> 'generate machine code') -----
> + fillInOPICHeader: pic numArgs: numArgs selector: selector
> +       <returnTypeC: #'CogMethod *'>
> +       <var: #pic type: #'CogMethod *'>
> +       <inline: true>
> +       pic cmType: CMOpenPIC.
> +       pic objectHeader: 0.
> +       pic blockSize: openPICSize.
> +       "pic methodObject: 0.""This is also the nextOpenPIC link so don't
> initialize it"
> +       methodZone addToOpenPICList: pic.
> +       pic methodHeader: 0.
> +       pic selector: selector.
> +       pic cmNumArgs: numArgs.
> +       (pic cmRefersToYoung: (objectMemory isYoung: selector)) ifTrue:
> +               [methodZone addToYoungReferrers: pic].
> +       pic cmUsageCount: self initialOpenPICUsageCount.
> +       pic cpicHasMNUCase: false.
> +       pic cPICNumCases: 0.
> +       pic blockEntryOffset: 0.
> +       self assert: pic cmType = CMOpenPIC.
> +       self assert: pic selector = selector.
> +       self assert: pic cmNumArgs = numArgs.
> +       self assert: (backEnd callTargetFromReturnAddress: pic asInteger +
> missOffset) = (self picAbortTrampolineFor: numArgs).
> +       self assert: openPICSize = (methodZone roundUpLength: openPICSize).
> +       processor flushICacheFrom: pic asUnsignedInteger to: pic
> asUnsignedInteger + openPICSize.
> +       ^pic!
>
> Item was removed:
> - ----- Method: Cogit>>fillInOPICHeader:size:numArgs:selector: (in
> category 'generate machine code') -----
> - fillInOPICHeader: pic size: size numArgs: numArgs selector: selector
> -       <returnTypeC: #'CogMethod *'>
> -       <var: #pic type: #'CogMethod *'>
> -       pic cmType: CMOpenPIC.
> -       pic objectHeader: 0.
> -       pic blockSize: size.
> -       "pic methodObject: 0.""This is also the nextOpenPIC link so don't
> initialize it"
> -       methodZone addToOpenPICList: pic.
> -       pic methodHeader: 0.
> -       pic selector: selector.
> -       pic cmNumArgs: numArgs.
> -       (pic cmRefersToYoung: (objectMemory isYoung: selector)) ifTrue:
> -               [methodZone addToYoungReferrers: pic].
> -       pic cmUsageCount: self initialOpenPICUsageCount.
> -       pic cpicHasMNUCase: false.
> -       pic cPICNumCases: 0.
> -       pic blockEntryOffset: 0.
> -       self assert: pic cmType = CMOpenPIC.
> -       self assert: pic selector = selector.
> -       self assert: pic cmNumArgs = numArgs.
> -       self assert: (backEnd callTargetFromReturnAddress: pic asInteger +
> missOffset) = (self picAbortTrampolineFor: numArgs).
> -       self assert: size = (methodZone roundUpLength: size).
> -       processor flushICacheFrom: pic asUnsignedInteger to: pic
> asUnsignedInteger + size.
> -       ^pic!
>
> Item was changed:
>   ----- Method: Cogit>>generateClosedPICPrototype (in category
> 'initialization') -----
>   generateClosedPICPrototype
>         "Generate the prototype ClosedPIC to determine how much space as
> full PIC takes.
>          When we first allocate a closed PIC it only has one or two cases
> and we want to grow it.
>          So we have to determine how big a full one is before hand."
> -       | headerSize |
>         numPICCases := 6.
>         "stack allocate the various collections so that they
>          are effectively garbage collected on return."
>         self allocateOpcodes: numPICCases * 7 bytecodes: 0.
>         self compileClosedPICPrototype.
>         self computeMaximumSizes.
> +       methodLabel concretizeAt: methodZoneBase.
> +       closedPICSize := (self sizeof: CogMethod) + (self
> generateInstructionsAt: methodZoneBase + (self sizeof: CogMethod)).
> -       headerSize := self sizeof: CogMethod.
> -       closedPICSize := headerSize + (self generateInstructionsAt:
> methodZoneBase + headerSize).
>         firstCPICCaseOffset := endCPICCase0 address - methodZoneBase.
>         cPICCaseSize := endCPICCase1 address - endCPICCase0 address.
>         cPICEndSize := closedPICSize - (numPICCases - 1 * cPICCaseSize +
> firstCPICCaseOffset).
>         closedPICSize := methodZone roundUpLength: closedPICSize
>         "self cCode: ''
>                 inSmalltalk:
>                         [| end |
>                          end := self outputInstructionsAt: methodZoneBase
> + headerSize.
>                          self disassembleFrom: methodZoneBase + headerSize
> to: end - 1.
>                          self halt]"!
>
> Item was changed:
>   ----- Method: Cogit>>generateOpenPICPrototype (in category
> 'initialization') -----
>   generateOpenPICPrototype
>         "Generate the prototype ClosedPIC to determine how much space as
> full PIC takes.
>          When we first allocate a closed PIC it only has one or two cases
> and we want to grow it.
>          So we have to determine how big a full one is before hand."
> +       | codeSize mapSize |
> -       | headerSize codeSize mapSize |
>         "stack allocate the various collections so that they
>          are effectively garbage collected on return."
>         self allocateOpcodes: 100 bytecodes: 0.
> +       methodLabel
> +               address: methodZoneBase;
> +               dependent: nil.
> +       "Need a real selector here so that the map accomodates the
> annotations for the selector.
> +        Use self numRegArgs to generate the longest possible code
> sequence due to
> +        genPushRegisterArgsForNumArgs:"
> -       "Ned a real selector here so that the map accomodates the
> annotations for the selector."
>         self compileOpenPIC: (coInterpreter specialSelector: 0) numArgs:
> self numRegArgs.
>         self computeMaximumSizes.
> -       headerSize := self sizeof: CogMethod.
>         methodLabel concretizeAt: methodZoneBase.
> +       codeSize := self generateInstructionsAt: methodZoneBase + (self
> sizeof: CogMethod).
> -       codeSize := self generateInstructionsAt: methodZoneBase +
> headerSize.
>         mapSize := self generateMapAt: nil start: methodZoneBase +
> cmNoCheckEntryOffset.
> +       openPICSize := (methodZone roundUpLength: (self sizeof: CogMethod)
> + codeSize) + (methodZone roundUpLength: mapSize).
> -       openPICSize := (methodZone roundUpLength: headerSize + codeSize) +
> (methodZone roundUpLength: mapSize).
>         "self cCode: ''
>                 inSmalltalk:
>                         [| end |
>                          end := self outputInstructionsAt: methodZoneBase
> + headerSize.
> +                        self disassembleFrom: methodZoneBase + (self
> sizeof: CogMethod) to: end - 1.
> -                        self disassembleFrom: methodZoneBase + headerSize
> to: end - 1.
>                          self halt]"!
>
> Item was changed:
>   ----- Method: Cogit>>generateTrampolines (in category 'initialization')
> -----
>   generateTrampolines
>         "Generate the run-time entries and exits at the base of the native
> code zone and update the base.
>          Read the class-side method trampolines for documentation on the
> various trampolines"
>         | methodZoneStart |
>         methodZoneStart := methodZoneBase.
> +       methodLabel address: methodZoneStart.
>         self allocateOpcodes: 80 bytecodes: 0.
>         initialPC := 0.
>         endPC := numAbstractOpcodes - 1.
>         hasYoungReferent := false.
>         self generateSendTrampolines.
>         self generateMissAbortTrampolines.
>         objectRepresentation generateObjectRepresentationTrampolines.
>         self generateRunTimeTrampolines.
>         self cppIf: NewspeakVM ifTrue:  [self generateNewspeakRuntime].
>         self cppIf: SistaVM ifTrue: [self generateSistaRuntime].
>         self generateEnilopmarts.
>         self generateTracingTrampolines.
>
>         "finish up"
>         self recordGeneratedRunTime: 'methodZoneBase' address:
> methodZoneBase.
>         processor flushICacheFrom: methodZoneStart to: methodZoneBase!
>
> Item was added:
> + ----- Method: Cogit>>methodLabel (in category 'accessing') -----
> + methodLabel
> +       <cmacro: '() methodLabel'>
> +       ^methodLabel!
>
> Item was changed:
>   ----- Method: Cogit>>setInterpreter: (in category 'initialization') -----
>   setInterpreter: aCoInterpreter
>         "Initialization of the code generator in the simulator.
>          These objects already exist in the generated C VM
>          or are used only in the simulation."
>         <doNotGenerate>
>         coInterpreter := aCoInterpreter.
>         objectMemory := aCoInterpreter objectMemory.
>         threadManager := aCoInterpreter threadManager. "N.B. may be nil"
>         methodZone := CogMethodZone new.
>         objectRepresentation := objectMemory objectRepresentationClass
>                                                                 forCogit:
> self methodZone: methodZone.
>         methodZone setInterpreter: aCoInterpreter
>                                 objectRepresentation: objectRepresentation
>                                 cogit: self.
>         generatorTable := self class generatorTable.
>         primitiveGeneratorTable := self class primitiveTable.
>         processor := ProcessorClass new.
>         simulatedAddresses := Dictionary new.
>         simulatedTrampolines := Dictionary new.
>         simulatedVariableGetters := Dictionary new.
>         simulatedVariableSetters := Dictionary new.
>         traceStores := 0.
> +       traceFlags := (self class initializationOptions at:
> #recordPrimTrace ifAbsent: [true])
> +                                       ifTrue: [8] "record prim trace on
> by default (see Cogit class>>decareCVarsIn:)"
> +                                       ifFalse: [0].
> -       traceFlags := 8. "record prim trace on by default (see Cogit
> class>>decareCVarsIn:)"
>         debugPrimCallStackOffset := 0.
>         singleStep := printRegisters := printInstructions := clickConfirm
> := false.
>         breakBlock ifNil: [self breakPC: breakPC].
>         (backEnd := processor abstractInstructionCompilerClass new) cogit:
> self.
>         (methodLabel := processor abstractInstructionCompilerClass new)
> cogit: self.
>         ordinarySendTrampolines := CArrayAccessor on: (Array new:
> NumSendTrampolines).
>         superSendTrampolines := CArrayAccessor on: (Array new:
> NumSendTrampolines).
>         BytecodeSetHasDirectedSuperSend ifTrue:
>                 [directedSuperSendTrampolines := CArrayAccessor on: (Array
> new: NumSendTrampolines)].
>         NewspeakVM ifTrue:
>                 [selfSendTrampolines := CArrayAccessor on: (Array new:
> NumSendTrampolines).
>                 dynamicSuperSendTrampolines := CArrayAccessor on: (Array
> new: NumSendTrampolines).
>                 implicitReceiverSendTrampolines := CArrayAccessor on:
> (Array new: NumSendTrampolines).
>                 outerSendTrampolines := CArrayAccessor on: (Array new:
> NumSendTrampolines)].
>         "debug metadata"
>         objectReferencesInRuntime := CArrayAccessor on: (Array new:
> NumObjRefsInRuntime).
>         runtimeObjectRefIndex := 0.
>         "debug metadata"
>         trampolineAddresses := CArrayAccessor on: (Array new:
> NumTrampolines * 2).
>         trampolineTableIndex := 0.
>
>         compilationTrace ifNil: [compilationTrace := self class
> initializationOptions at: #compilationTrace ifAbsent: [0]].
>         extA := extB := 0!
>
> Item was changed:
>   ----- Method: Cogit>>varBaseAddress (in category 'accessing') -----
>   varBaseAddress
>         "We expect simulatedAddresses to have around 40 entries.  48 is
> hopefully a good maximum."
>         <doNotGenerate>
> +       ^coInterpreter varBaseAddress!
> -       ^self cCode: [coInterpreter varBaseAddress]
> -               inSmalltalk: [self fakeAddressFor: nil index: 48]!
>
> Item was changed:
>   ----- Method: CurrentImageCoInterpreterFacade>>addressForLabel: (in
> category 'labels') -----
>   addressForLabel: l
> +       ^variables at: l ifAbsentPut: [variables size * 4 + self
> variablesBase]!
> -       ^variables
> -               at: l
> -               ifAbsentPut:
> -                       [(self isLabelRelativeToCogitVarBaseReg: l)
> -                               ifTrue: [cogit fakeAddressFor: l index:
> variables size + 48]
> -                               ifFalse: [variables size * 4 + self
> variablesBase]]!
>
> Item was added:
> + ----- Method: CurrentImageCoInterpreterFacade>>varBaseAddress (in
> category 'accessing') -----
> + varBaseAddress
> +       "This value is chosen for ARM, which has the ability to do 12-bit
> relative addresses from the var base register."
> +       ^(variables at: 'stackLimit') - (1 << 11)!
>
> Item was changed:
>   ----- Method: SimpleStackBasedCogit>>genSend:numArgs:sendTable: (in
> category 'bytecode generator support') -----
>   genSend: selector numArgs: numArgs sendTable: sendTable
>         <inline: false>
>         <var: #sendTable type: #'sqInt *'>
>         | annotation |
>         (objectMemory isYoung: selector) ifTrue:
>                 [hasYoungReferent := true].
>         self assert: needsFrame.
>         annotation := self annotationForSendTable: sendTable.
>         self assert: (numArgs between: 0 and: 255). "say"
>         self assert: (objectMemory addressCouldBeOop: selector).
>         self MoveMw: numArgs * objectMemory wordSize r: SPReg R:
> ReceiverResultReg.
>         "Deal with stale super sends; see SpurMemoryManager's class
> comment."
>         (self annotationIsForUncheckedEntryPoint: annotation) ifTrue:
>                 [objectRepresentation genEnsureOopInRegNotForwarded:
> ReceiverResultReg scratchReg: TempReg].
> +       "0 through (NumSendTrampolines - 2) numArgs sends have the arg
> count implciti in the trampoline.
> +        The last send trampoline (NumSendTrampolines - 1) passes numArgs
> in SendNumArgsReg."
> +       numArgs >= (NumSendTrampolines - 1) ifTrue:
> -       numArgs > 2 ifTrue:
>                 [self MoveCq: numArgs R: SendNumArgsReg].
>         (BytecodeSetHasDirectedSuperSend
>          and: [annotation = IsDirectedSuperSend]) ifTrue:
>                 [self genMoveConstant: tempOop R: TempReg].
>         self MoveCw: selector R: ClassReg.
>         self annotate: (self Call: (sendTable at: (numArgs min:
> NumSendTrampolines - 1)))
>                 with: annotation.
>         self PushR: ReceiverResultReg.
>         ^0!
>
> Item was added:
> + ----- Method:
> SistaStackToRegisterMappingCogit>>fillInCPICHeader:numArgs:numCases:hasMNUCase:selector:
> (in category 'generate machine code') -----
> + fillInCPICHeader: pic numArgs: numArgs numCases: numCases hasMNUCase:
> hasMNUCase selector: selector
> +       pic counters: 0.
> +       ^super fillInCPICHeader: pic numArgs: numArgs numCases: numCases
> hasMNUCase: hasMNUCase selector: selector!
>
> Item was removed:
> - ----- Method:
> SistaStackToRegisterMappingCogit>>fillInCPICHeader:size:numArgs:numCases:hasMNUCase:selector:
> (in category 'generate machine code') -----
> - fillInCPICHeader: pic size: size numArgs: numArgs numCases: numCases
> hasMNUCase: hasMNUCase selector: selector
> -       pic counters: 0.
> -       ^super fillInCPICHeader: pic size: size numArgs: numArgs numCases:
> numCases hasMNUCase: hasMNUCase selector: selector!
>
> Item was added:
> + ----- Method:
> SistaStackToRegisterMappingCogit>>fillInOPICHeader:numArgs:selector: (in
> category 'generate machine code') -----
> + fillInOPICHeader: pic numArgs: numArgs selector: selector
> +       pic counters: 0.
> +       ^super fillInOPICHeader: pic numArgs: numArgs selector: selector!
>
> Item was removed:
> - ----- Method:
> SistaStackToRegisterMappingCogit>>fillInOPICHeader:size:numArgs:selector:
> (in category 'generate machine code') -----
> - fillInOPICHeader: pic size: size numArgs: numArgs selector: selector
> -       pic counters: 0.
> -       ^super fillInOPICHeader: pic size: size numArgs: numArgs selector:
> selector!
>
> Item was changed:
>   ----- Method: SpurMemoryManager>>checkTraversableSortedFreeList (in
> category 'simulation only') -----
>   checkTraversableSortedFreeList
> +       | prevFree prevPrevFree freeChunk |
> -       | prevFree freeChunk |
>         <api>
>         <inline: false>
> +       prevFree := prevPrevFree := 0.
> -       prevFree := 0.
>         freeChunk := firstFreeChunk.
>         self allOldSpaceEntitiesDo:
>                 [:o| | objOop next limit |
>                 (self isFreeObject: o) ifTrue:
>                         [self assert: o = freeChunk.
>                          next := self nextInSortedFreeListLink: freeChunk
> given: prevFree.
>                          limit := next = 0 ifTrue: [endOfMemory] ifFalse:
> [next].
>                          "coInterpreter transcript cr; print: freeChunk;
> tab; print: o; tab; print: prevFree; nextPutAll: '<->'; print: next; flush."
>                          objOop := freeChunk.
>                          [self oop: (objOop := self objectAfter: objOop)
> isLessThan: limit] whileTrue:
>                                 [self assert: (self isFreeObject: objOop)
> not].
> +                        prevPrevFree := prevFree.
>                          prevFree := freeChunk.
>                          freeChunk := next]].
>         self assert: prevFree = lastFreeChunk.
> +       self assert: (self nextInSortedFreeListLink: lastFreeChunk given:
> 0) = prevPrevFree.
>         self assert: freeChunk = 0.
>         ^true!
>
> Item was changed:
>   ----- Method:
> StackToRegisterMappingCogit>>genMarshalledSend:numArgs:sendTable: (in
> category 'bytecode generator support') -----
>   genMarshalledSend: selector numArgs: numArgs sendTable: sendTable
>         <inline: false>
>         <var: #sendTable type: #'sqInt *'>
>         | annotation |
>         (objectMemory isYoung: selector) ifTrue:
>                 [hasYoungReferent := true].
>         self assert: needsFrame.
>         annotation := self annotationForSendTable: sendTable.
>         "Deal with stale super sends; see SpurMemoryManager's class
> comment."
>         (self annotationIsForUncheckedEntryPoint: annotation) ifTrue:
>                 [objectRepresentation genEnsureOopInRegNotForwarded:
> ReceiverResultReg scratchReg: TempReg].
> +       "0 through (NumSendTrampolines - 2) numArgs sends have the arg
> count implciti in the trampoline.
> +        The last send trampoline (NumSendTrampolines - 1) passes numArgs
> in SendNumArgsReg."
> +       numArgs >= (NumSendTrampolines - 1) ifTrue:
> -       numArgs > 2 ifTrue:
>                 [self MoveCq: numArgs R: SendNumArgsReg].
>         (BytecodeSetHasDirectedSuperSend
>          and: [annotation = IsDirectedSuperSend]) ifTrue:
>                 [self genMoveConstant: tempOop R: TempReg].
>         self MoveCw: selector R: ClassReg.
>         self annotate: (self Call: (sendTable at: (numArgs min:
> NumSendTrampolines - 1)))
>                 with: annotation.
>         optStatus isReceiverResultRegLive: false.
>         ^self ssPushRegister: ReceiverResultReg!
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20150521/13bb6e2c/attachment-0001.htm


More information about the Vm-dev mailing list