VM Maker: VMMaker.oscog-eem.2864.mcz

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

VM Maker: VMMaker.oscog-eem.2864.mcz

commits-2
 
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2864.mcz

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

Name: VMMaker.oscog-eem.2864
Author: eem
Time: 30 October 2020, 6:06:55.276851 am
UUID: fe5cd24b-69ca-436c-80fb-04bb4f330099
Ancestors: VMMaker.oscog-eem.2863

Sionara ceCheckFeatures.  Cache cpuid result(s) in variable(s). Do throw-away compilation(s) to get at the CPUID result(s) needed.  Refactor abiMarshalArg0:... to accomodate IA32.  To allow leaf functions to take arguments passed on the stack (as is needed for IA32) move marshaling to after the (questionable) switch to the C stack.

=============== Diff against VMMaker.oscog-eem.2863 ===============

Item was added:
+ ----- Method: CogAbstractInstruction>>detectFeatures (in category 'initialization') -----
+ detectFeatures
+ "This is a null default for code to detect features specific to the processor
+ which may not be present on all versions of the processor and hence must
+ be checked at runtime. Subclasses override if necessary."
+ <inline: #always>!

Item was changed:
  ----- Method: CogClass>>cCoerceSimple:to: (in category 'translation support') -----
  cCoerceSimple: value to: cTypeString
  <doNotGenerate>
  "Type coercion for translation and simulation.
  For simulation answer a suitable surrogate for the struct types"
  ^cTypeString caseOf:
    { [#'unsigned long'] -> [value].
  [#'unsigned int'] -> [value].
  [#'unsigned short'] -> [value].
  [#sqInt] -> [value].
  [#'sqIntptr_t'] -> [value].
  [#'usqIntptr_t'] -> [value].
  [#usqInt] -> [value].
  [#sqLong] -> [value].
  [#usqLong] -> [value].
  [#'AbstractInstruction *'] -> [value].
  [#'SpurSegmentInfo *'] -> [value].
  [#'BytecodeFixup *'] -> [value].
  [#'CogMethod *'] -> [value].
  [#'char *'] -> [value].
  [#'sqInt *'] -> [value].
  [#'void *'] -> [value].
  [#void] -> [value].
  [#'void (*)()'] -> [value].
  [#'void (*)(void)'] -> [value].
  [#'usqIntptr_t (*)(void)'] -> [value].
+ [#'void (*)(usqIntptr_t,usqIntptr_t)'] -> [value].
+ [#'uintptr_t (*)(uintptr_t)'] -> [value].
+ [#'uintptr_t (*)(void)'] -> [value] }!
- [#'void (*)(usqIntptr_t,usqIntptr_t)'] -> [value] }!

Item was changed:
  CogAbstractInstruction subclass: #CogIA32Compiler
  instanceVariableNames: ''
  classVariableNames: 'BSR CDQ CLD CMPXCHGRAw CPUID EAX EBP EBX ECX EDI EDX ESI ESP FSTPD FSTPS IDIVR IMULRR LFENCE LOCK MFENCE MOVSB MOVSD ModReg ModRegInd ModRegIndDisp32 ModRegIndSIB ModRegRegDisp32 ModRegRegDisp8 REP SETE SFENCE SIB1 SIB2 SIB4 SIB8 XCHGRR XMM0L XMM1L XMM2L XMM3L XMM4L XMM5L XMM6L XMM7L'
  poolDictionaries: ''
  category: 'VMMaker-JIT'!
+ CogIA32Compiler class
+ instanceVariableNames: 'cpuidWord0 cpuidWord1'!
 
  !CogIA32Compiler commentStamp: 'eem 9/14/2015 17:13' prior: 0!
  I generate IA32 (x86) instructions from CogAbstractInstructions.  For reference see
  1. IA-32 Intel® Architecture Software Developer's Manual Volume 2A: Instruction Set Reference, A-M
  2. IA-32 Intel® Architecture Software Developer's Manual Volume 2A: Instruction Set Reference, N-Z
  http://www.intel.com/products/processor/manuals/
  (® is supposed to be the Unicode "registered  sign".
 
  This class does not take any special action to flush the instruction cache on instruction-modification, trusting that Intel and AMD processors correctly invalidate the instruction cache via snooping.  According to the manuals, this will work on systems where code and data have the same virtual address.  The CogICacheFlushingIA32Compiler subclass exists to use the CPUID instruction to serialize instruction-modification for systems with code and data at different virtual addresses.!
+ CogIA32Compiler class
+ instanceVariableNames: 'cpuidWord0 cpuidWord1'!

Item was added:
+ ----- Method: CogIA32Compiler class>>cpuidWord0 (in category 'accessing') -----
+ cpuidWord0
+ ^cpuidWord0!

Item was added:
+ ----- Method: CogIA32Compiler class>>cpuidWord1 (in category 'accessing') -----
+ cpuidWord1
+ ^cpuidWord1!

Item was added:
+ ----- Method: CogIA32Compiler class>>declareCVarsIn: (in category 'translation') -----
+ declareCVarsIn: aCCodeGenerator
+ aCCodeGenerator
+ declareVar: 'cpuidWord0' type: #uintptr_t;
+ declareVar: 'cpuidWord1' type: #uintptr_t!

Item was removed:
- ----- Method: CogIA32Compiler class>>numTrampolines (in category 'trampoline support') -----
- numTrampolines
- ^2 "ceCheckFeatures and ceCheckLZCNTFunction"!

Item was added:
+ ----- Method: CogIA32Compiler>>cpuid: (in category 'feature detection') -----
+ cpuid: n
+ <doNotGenerate>
+ "This is simulation only invocation of the throw-away CPUID function generated to initialize cpuidWord0 and cpuidWord1"
+ ^cogit
+ simulateLeafCallOf: cogit methodZoneBase
+ marshaling: [cogit processor abiMarshalArg0: n in: objectMemory memory]!

Item was added:
+ ----- Method: CogIA32Compiler>>cpuidWord0 (in category 'feature detection') -----
+ cpuidWord0
+ <cmacro: '(ign) cpuidWord0'>
+ "For want of somewhere to put the variable..."
+ ^self class cpuidWord0!

Item was added:
+ ----- Method: CogIA32Compiler>>cpuidWord1 (in category 'feature detection') -----
+ cpuidWord1
+ <cmacro: '(ign) cpuidWord1'>
+ "For want of somewhere to put the variable..."
+ ^self class cpuidWord1!

Item was added:
+ ----- Method: CogIA32Compiler>>detectFeatures (in category 'feature detection') -----
+ detectFeatures
+ "Do a throw-away compilation to get at the cpuid info and initialize cpuidWord0 and cpuidWord1.
+ N.B. All of MSVC, gcc & clang have intrinsics for this, so if you have the energy by all means
+ reimplement as an #if _MSC_VER...#elif __GNUC__ #else ... saga."
+ | startAddress cpuid |
+ <var: 'cpuid' declareC: 'uintptr_t (*cpuid)(uintptr_t arg)'>
+ startAddress := cogit methodZoneBase.
+ cogit allocateOpcodes: 10 bytecodes: 0.
+ cpuid := cogit cCoerceSimple: cogit methodZoneBase to: #'uintptr_t (*)(uintptr_t)'.
+ cogit
+ PushR: EDX;
+ PushR: ECX;
+ PushR: EBX;
+ MoveMw: 16 "3 saved registers plus return pc" r: ESP R: EAX;
+ gen: CPUID;
+ MoveR: EDX R: EAX;
+ PopR: EBX;
+ PopR: ECX;
+ PopR: EDX;
+ RetN: 0.
+ cogit outputInstructionsForGeneratedRuntimeAt: startAddress.
+ cogit resetMethodZoneBase: startAddress.
+ self setCpuidWord0: (self cCode: 'cpuid(1)' inSmalltalk: [self cpuid: 1]).
+ cogit zeroOpcodeIndexForNewOpcodes.
+ cogit
+ PushR: EDX;
+ PushR: ECX;
+ PushR: EBX;
+ MoveMw: 16 "3 saved registers plus return pc" r: ESP R: EAX;
+ gen: CPUID;
+ MoveR: ECX R: EAX;
+ PopR: EBX;
+ PopR: ECX;
+ PopR: EDX;
+ RetN: 0.
+ cogit outputInstructionsForGeneratedRuntimeAt: startAddress.
+ cogit resetMethodZoneBase: startAddress.
+ self setCpuidWord1: (self cCode: 'cpuid(0x80000001)' inSmalltalk: [self cpuid: 16r80000001])!

Item was removed:
- ----- Method: CogIA32Compiler>>generateCheckFeatures (in category 'feature detection') -----
- generateCheckFeatures
- <inline: true>
- cogit
- PushR: EDX;
- PushR: ECX;
- PushR: EBX;
- MoveCq: 1 R: EAX;
- gen: CPUID;
- MoveR: EDX R: EAX;
- PopR: EBX;
- PopR: ECX;
- PopR: EDX;
- RetN: 0!

Item was removed:
- ----- Method: CogIA32Compiler>>generateCheckLZCNT (in category 'feature detection') -----
- generateCheckLZCNT
- "to check is Leading Zero Count operation is present
- cf. MSVC builtin __lzcnt documentation
- The result will be in bit 5 of return value (in EAX)"
- <inline: true>
- cogit
- PushR: EDX;
- PushR: ECX;
- PushR: EBX;
- MoveCq: 16r80000001 R: EAX;
- gen: CPUID;
- MoveR: ECX R: EAX;
- PopR: EBX;
- PopR: ECX;
- PopR: EDX;
- RetN: 0!

Item was changed:
  ----- Method: CogIA32Compiler>>hasLZCNTInstructions (in category 'testing') -----
  hasLZCNTInstructions
  "Answer if we support LZCNT"
  <inline: true>
+ ^self cpuidWord1 anyMask: 1 << 5!
- ^(cogit ceCheckLZCNT bitAnd: (1 << 5)) ~= 0!

Item was changed:
  ----- Method: CogIA32Compiler>>hasSSE2Instructions (in category 'testing') -----
  hasSSE2Instructions
  "Answer if we support SSE2"
+ ^self cpuidWord0 anyMask: 1 << 26!
- ^(cogit ceCheckFeatures bitAnd: (1 << 26)) ~= 0!

Item was changed:
  ----- Method: CogIA32Compiler>>hasSSEInstructions (in category 'testing') -----
  hasSSEInstructions
  "Answer if we support SSE"
+ ^self cpuidWord0 anyMask: 1 << 25!
- ^(cogit ceCheckFeatures bitAnd: (1 << 25)) ~= 0!

Item was removed:
- ----- Method: CogIA32Compiler>>numCheckFeaturesOpcodes (in category 'feature detection') -----
- numCheckFeaturesOpcodes
- "Answer the number of opcodes required to compile the CPUID call to extract the extended features information."
- ^11!

Item was removed:
- ----- Method: CogIA32Compiler>>numCheckLZCNTOpcodes (in category 'feature detection') -----
- numCheckLZCNTOpcodes
- "Answer the number of opcodes required to compile the CPUID call to extract the extended features information."
- ^11!

Item was added:
+ ----- Method: CogIA32Compiler>>setCpuidWord0: (in category 'feature detection') -----
+ setCpuidWord0: word
+ <cmacro: '(ign,word) cpuidWord0 = word'>
+ "For want of somewhere to put the variable..."
+ self class instVarNamed: 'cpuidWord0' put: word!

Item was added:
+ ----- Method: CogIA32Compiler>>setCpuidWord1: (in category 'feature detection') -----
+ setCpuidWord1: word
+ <cmacro: '(ign,word) cpuidWord1 = word'>
+ "For want of somewhere to put the variable..."
+ self class instVarNamed: 'cpuidWord1' put: word!

Item was changed:
  CogAbstractInstruction subclass: #CogX64Compiler
  instanceVariableNames: ''
  classVariableNames: 'BSR CArg0Reg CArg1Reg CArg2Reg CArg3Reg CDQ CLD CMPXCHGRMr CPUID IDIVR IMULRR LFENCE LOCK MFENCE MOVSB MOVSQ ModReg ModRegInd ModRegIndDisp32 ModRegIndSIB ModRegRegDisp32 ModRegRegDisp8 MoveRAwNoVBR R10 R11 R12 R13 R14 R15 R8 R9 RAX RBP RBX RCX RDI RDX REP RSI RSP SETE SFENCE SIB1 SIB2 SIB4 SIB8 SysV XCHGRR XMM0L XMM10L XMM11L XMM12L XMM13L XMM14L XMM15L XMM1L XMM2L XMM3L XMM4L XMM5L XMM6L XMM7L XMM8L XMM9L'
  poolDictionaries: ''
  category: 'VMMaker-JIT'!
+ CogX64Compiler class
+ instanceVariableNames: 'cpuidWord1'!
 
  !CogX64Compiler commentStamp: 'eem 9/14/2015 17:12' prior: 0!
  I generate x64 (x86-64) instructions from CogAbstractInstructions.  For reference see
  1. IA-32 Intel® Architecture Software Developer's Manual Volume 2A: Instruction Set Reference, A-M
  2. IA-32 Intel® Architecture Software Developer's Manual Volume 2A: Instruction Set Reference, N-Z
  http://www.intel.com/products/processor/manuals/
  or
  AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions
  AMD64 Architecture Programmer's Manual Volume 4: 128-bit Media Instructions
  AMD64 Architecture Programmer's Manual Volume 5: 64-bit Media and x87 Floating Point Instructions
  http://developer.amd.com/resources/documentation-articles/developer-guides-manuals/
  (® is supposed to be the Unicode "registered  sign").!
+ CogX64Compiler class
+ instanceVariableNames: 'cpuidWord1'!

Item was added:
+ ----- Method: CogX64Compiler class>>cpuidWord1 (in category 'accessing') -----
+ cpuidWord1
+ ^cpuidWord1!

Item was added:
+ ----- Method: CogX64Compiler class>>declareCVarsIn: (in category 'translation') -----
+ declareCVarsIn: aCCodeGenerator
+ aCCodeGenerator
+ declareVar: 'cpuidWord1' type: #uintptr_t!

Item was removed:
- ----- Method: CogX64Compiler class>>numTrampolines (in category 'trampoline support') -----
- numTrampolines
- ^1 "ceCheckLZCNTFunction"!

Item was added:
+ ----- Method: CogX64Compiler>>cpuidWord1 (in category 'feature detection') -----
+ cpuidWord1
+ <cmacro: '(ign) cpuidWord1'>
+ "For want of somewhere to put the variable..."
+ ^self class cpuidWord1!

Item was added:
+ ----- Method: CogX64Compiler>>detectFeatures (in category 'feature detection') -----
+ detectFeatures
+ "Do a throw-away compilation to get at the cpuid info and initialize cpuidWord1
+ N.B. All of MSVC, gcc & clang have intrinsics for this, so if you have the energy
+ by all means reimplement as an #if _MSC_VER...#elif __GNUC__ #else ... saga."
+ | startAddress cpuid |
+ <var: 'cpuid' declareC: 'uintptr_t (*cpuid)(void)'>
+ startAddress := cogit methodZoneBase.
+ cogit allocateOpcodes: 10 bytecodes: 0.
+ cpuid := cogit cCoerceSimple: startAddress to: #'uintptr_t (*)(void)'.
+ cogit
+ PushR: RDX;
+ PushR: RCX;
+ PushR: RBX;
+ MoveCq: 16r80000001 R: RAX;
+ gen: CPUID;
+ MoveR: RCX R: RAX;
+ PopR: RBX;
+ PopR: RCX;
+ PopR: RDX;
+ RetN: 0.
+ cogit outputInstructionsForGeneratedRuntimeAt: startAddress.
+ cogit resetMethodZoneBase: startAddress.
+ self setCpuidWord1: (self cCode: 'cpuid()' inSmalltalk: [cogit simulateLeafCallOf: startAddress marshaling: []])!

Item was removed:
- ----- Method: CogX64Compiler>>generateCheckLZCNT (in category 'feature detection') -----
- generateCheckLZCNT
- "to check is Leading Zero Count operation is present
- cf. MSVC builtin __lzcnt documentation
- The result will be in bit 5 of return value (in RAX)"
- <inline: true>
- cogit
- PushR: RDX;
- PushR: RCX;
- PushR: RBX;
- MoveCq: 16r80000001 R: RAX;
- gen: CPUID;
- MoveR: RCX R: RAX;
- PopR: RBX;
- PopR: RCX;
- PopR: RDX;
- RetN: 0!

Item was changed:
  ----- Method: CogX64Compiler>>hasLZCNTInstructions (in category 'testing') -----
  hasLZCNTInstructions
  "Answer if we support LZCNT"
  <inline: true>
+ ^self cpuidWord1 anyMask: 1 << 5!
- ^(cogit ceCheckLZCNT bitAnd: (1 << 5)) ~= 0!

Item was removed:
- ----- Method: CogX64Compiler>>numCheckLZCNTOpcodes (in category 'feature detection') -----
- numCheckLZCNTOpcodes
- "Answer the number of opcodes required to compile the CPUID call to extract the extended features information."
- ^11!

Item was added:
+ ----- Method: CogX64Compiler>>setCpuidWord1: (in category 'feature detection') -----
+ setCpuidWord1: word
+ <cmacro: '(ign,word) cpuidWord1 = word'>
+ "For want of somewhere to put the variable..."
+ self class instVarNamed: 'cpuidWord1' put: word!

Item was changed:
  CogClass subclass: #Cogit
(excessive size, no diff calculated)

Item was changed:
  ----- Method: Cogit class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: aCCodeGenerator
  | backEnd |
  backEnd := CogCompilerClass basicNew.
  #( 'coInterpreter' 'objectMemory' 'methodZone' 'objectRepresentation'
  'cogBlockMethodSurrogateClass' 'cogMethodSurrogateClass' 'nsSendCacheSurrogateClass'
  'threadManager' 'processor' 'lastNInstructions' 'simulatedAddresses'
  'simulatedTrampolines' 'simulatedVariableGetters' 'simulatedVariableSetters'
  'processorFrameValid' 'printRegisters' 'printInstructions' 'clickConfirm' 'singleStep') do:
  [:simulationVariableNotNeededForRealVM|
  aCCodeGenerator removeVariable: simulationVariableNotNeededForRealVM].
  NewspeakVM ifFalse:
  [#( 'selfSendTrampolines' 'dynamicSuperSendTrampolines'
  'implicitReceiverSendTrampolines' 'outerSendTrampolines'
  'ceEnclosingObjectTrampoline' 'numIRCs' 'indexOfIRC' 'theIRCs') do:
  [:variableNotNeededInNormalVM|
  aCCodeGenerator removeVariable: variableNotNeededInNormalVM]].
  aCCodeGenerator removeConstant: #COGMTVM. "this should be defined at compile time"
  aCCodeGenerator
  addHeaderFile:'<stddef.h>'; "for e.g. offsetof"
  addHeaderFile:'"sqCogStackAlignment.h"';
  addHeaderFile:'"dispdbg.h"'; "must precede cointerp.h & cogit.h otherwise NoDbgRegParms gets screwed up"
  addHeaderFile:'"cogmethod.h"'.
  NewspeakVM ifTrue:
  [aCCodeGenerator addHeaderFile:'"nssendcache.h"'].
  aCCodeGenerator
  addHeaderFile:'#if COGMTVM';
  addHeaderFile:'"cointerpmt.h"';
  addHeaderFile:'#else';
  addHeaderFile:'"cointerp.h"';
  addHeaderFile:'#endif';
  addHeaderFile:'"cogit.h"'.
  aCCodeGenerator
  var: #ceGetFP
  declareC: 'usqIntptr_t (*ceGetFP)(void)';
  var: #ceGetSP
  declareC: 'usqIntptr_t (*ceGetSP)(void)';
  var: #ceCaptureCStackPointers
  declareC: 'void (*ceCaptureCStackPointers)(void)';
  var: #ceInvokeInterpret
  declareC: 'void (*ceInvokeInterpret)(void)';
  var: #ceEnterCogCodePopReceiverReg
  declareC: 'void (*ceEnterCogCodePopReceiverReg)(void)';
  var: #realCEEnterCogCodePopReceiverReg
  declareC: 'void (*realCEEnterCogCodePopReceiverReg)(void)';
  var: #ceCallCogCodePopReceiverReg
  declareC: 'void (*ceCallCogCodePopReceiverReg)(void)';
  var: #realCECallCogCodePopReceiverReg
  declareC: 'void (*realCECallCogCodePopReceiverReg)(void)';
  var: #ceCallCogCodePopReceiverAndClassRegs
  declareC: 'void (*ceCallCogCodePopReceiverAndClassRegs)(void)';
  var: #realCECallCogCodePopReceiverAndClassRegs
  declareC: 'void (*realCECallCogCodePopReceiverAndClassRegs)(void)';
  var: #postCompileHook
  declareC: 'void (*postCompileHook)(CogMethod *)';
  var: #openPICList declareC: 'CogMethod *openPICList = 0';
  var: #maxMethodBefore type: #'CogBlockMethod *';
  var: 'enumeratingCogMethod' type: #'CogMethod *'.
 
  aCCodeGenerator
  var: #ceTryLockVMOwner
  declareC: '#if COGMTVM\usqIntptr_t (*ceTryLockVMOwner)(void)';
  var: #ceUnlockVMOwner
  declareC: 'void (*ceUnlockVMOwner)(void)\#endif /* COGMTVM */'.
 
- backEnd numCheckLZCNTOpcodes > 0 ifTrue:
- [aCCodeGenerator
- var: #ceCheckLZCNTFunction
- declareC: 'static usqIntptr_t (*ceCheckLZCNTFunction)(void)'].
- backEnd numCheckFeaturesOpcodes > 0 ifTrue:
- [aCCodeGenerator
- var: #ceCheckFeaturesFunction
- declareC: 'static usqIntptr_t (*ceCheckFeaturesFunction)(void)'].
  backEnd numICacheFlushOpcodes > 0 ifTrue:
  [aCCodeGenerator
  var: #ceFlushICache
  declareC: 'static void (*ceFlushICache)(usqIntptr_t from, usqIntptr_t to)'].
  aCCodeGenerator
  var: #ceFlushDCache
  declareC: '#if DUAL_MAPPED_CODE_ZONE\static void (*ceFlushDCache)(usqIntptr_t from, usqIntptr_t to)\#endif';
  var: #codeToDataDelta
  declareC: '#if DUAL_MAPPED_CODE_ZONE\static sqInt codeToDataDelta\#else\# define codeToDataDelta 0\#endif'.
 
  aCCodeGenerator
  declareVar: 'aMethodLabel' type: #'AbstractInstruction'; "Has to come lexicographically before backEnd & methodLabel"
  var: #backEnd declareC: 'AbstractInstruction * const backEnd = &aMethodLabel';
  var: #methodLabel declareC: 'AbstractInstruction * const methodLabel = &aMethodLabel'.
  self declareC: #(abstractOpcodes stackCheckLabel
  blockEntryLabel blockEntryNoContextSwitch
  stackOverflowCall sendMiss
  entry noCheckEntry selfSendEntry dynSuperEntry
  fullBlockNoContextSwitchEntry fullBlockEntry
  picMNUAbort picInterpretAbort  endCPICCase0 endCPICCase1 cPICEndOfCodeLabel)
  as: #'AbstractInstruction *'
  in: aCCodeGenerator.
  aCCodeGenerator
  declareVar: #cPICPrototype type: #'CogMethod *';
  declareVar: #blockStarts type: #'BlockStart *';
  declareVar: #fixups type: #'BytecodeFixup *';
  declareVar: #methodZoneBase type: #usqInt.
  aCCodeGenerator
  var: #ordinarySendTrampolines
  declareC: 'sqInt ordinarySendTrampolines[NumSendTrampolines]';
  var: #superSendTrampolines
  declareC: 'sqInt superSendTrampolines[NumSendTrampolines]'.
  BytecodeSetHasDirectedSuperSend ifTrue:
  [aCCodeGenerator
  var: #directedSuperSendTrampolines
  declareC: 'sqInt directedSuperSendTrampolines[NumSendTrampolines]';
  var: #directedSuperBindingSendTrampolines
  declareC: 'sqInt directedSuperBindingSendTrampolines[NumSendTrampolines]'].
  NewspeakVM ifTrue:
  [aCCodeGenerator
  var: #selfSendTrampolines
  declareC: 'sqInt selfSendTrampolines[NumSendTrampolines]';
  var: #dynamicSuperSendTrampolines
  declareC: 'sqInt dynamicSuperSendTrampolines[NumSendTrampolines]';
  var: #implicitReceiverSendTrampolines
  declareC: 'sqInt implicitReceiverSendTrampolines[NumSendTrampolines]';
  var: #outerSendTrampolines
  declareC: 'sqInt outerSendTrampolines[NumSendTrampolines]'].
  aCCodeGenerator
  var: #trampolineAddresses
  declareC: 'static char *trampolineAddresses[NumTrampolines*2]';
  var: #objectReferencesInRuntime
  declareC: 'static usqInt objectReferencesInRuntime[NumObjRefsInRuntime+1]';
  var: #labelCounter
  type: #int;
  var: #traceFlags
  declareC: 'int traceFlags = 8 /* prim trace log on by default */';
  var: #cStackAlignment
  declareC: 'const int cStackAlignment = STACK_ALIGN_BYTES'.
  aCCodeGenerator
  declareVar: #minValidCallAddress type: #'usqIntptr_t'.
  aCCodeGenerator vmClass generatorTable ifNotNil:
  [:bytecodeGenTable|
  aCCodeGenerator
  var: #generatorTable
  declareC: 'static BytecodeDescriptor generatorTable[', bytecodeGenTable size printString, ']',
  (self tableInitializerFor: bytecodeGenTable
  in: aCCodeGenerator)].
  "In C the abstract opcode names clash with the Smalltalk generator syntactic sugar.
  Most of the syntactic sugar is inlined, but alas some remains.  Rename the syntactic
  sugar to avoid the clash."
  (self organization listAtCategoryNamed: #'abstract instructions') do:
  [:s|
  aCCodeGenerator addSelectorTranslation: s to: 'g', (aCCodeGenerator cFunctionNameFor: s)].
  aCCodeGenerator addSelectorTranslation: #halt: to: 'haltmsg'.
  self declareFlagVarsAsByteIn: aCCodeGenerator!

Item was changed:
  ----- Method: Cogit>>ceCaptureCStackPointers (in category 'jit - api') -----
  ceCaptureCStackPointers
  <api: 'extern void (*ceCaptureCStackPointers)()'>
  <doNotGenerate>
  | range |
  coInterpreter isCurrentImageFacade ifTrue:
  [^self].
  coInterpreter isThreadedVM ifFalse:
+ [^self simulateLeafCallOf: ceCaptureCStackPointers marshaling: []].
- [^self simulateLeafCallOf: ceCaptureCStackPointers].
  thisContext sender selector == #generateStackPointerCapture ifTrue:
  [^self].
  range := coInterpreter cStackRangeForThreadIndex: coInterpreter threadManager getVMOwner.
  self assert: (range notNil "VM is owned"
  and: [(range includes: processor sp)
  and: [range includes: processor fp]]).
  coInterpreter setCFramePointer: processor fp setCStackPointer: processor sp!

Item was removed:
- ----- Method: Cogit>>ceCheckFeatures (in category 'testing') -----
- ceCheckFeatures
- <cmacro: '() ceCheckFeaturesFunction()'>
- ^self simulateLeafCallOf: ceCheckFeaturesFunction!

Item was removed:
- ----- Method: Cogit>>ceCheckLZCNT (in category 'testing') -----
- ceCheckLZCNT
- <cmacro: '() ceCheckLZCNTFunction()'>
- ^self simulateLeafCallOf: ceCheckLZCNTFunction!

Item was changed:
  ----- Method: Cogit>>initializeCodeZoneFrom:upTo: (in category 'initialization') -----
  initializeCodeZoneFrom: startAddress upTo: endAddress
  <api>
  self initializeBackend.
  self sqMakeMemoryExecutableFrom: startAddress
  To: endAddress
  CodeToDataDelta: (self cppIf: #DUAL_MAPPED_CODE_ZONE
  ifTrue: [self addressOf: codeToDataDelta put: [:v| codeToDataDelta := v]]
  ifFalse: [nil]).
  backEnd stopsFrom: startAddress to: endAddress - 1.
  self cCode: '' inSmalltalk:
  [self initializeProcessor.
  backEnd stopsFrom: 0 to: guardPageSize - 1].
  codeBase := methodZoneBase := startAddress.
  minValidCallAddress := (codeBase min: coInterpreter interpretAddress)
  min: coInterpreter primitiveFailAddress.
  methodZone manageFrom: methodZoneBase to: endAddress.
  self assertValidDualZone.
+ backEnd detectFeatures.
- self maybeGenerateCheckFeatures.
  self maybeGenerateCacheFlush.
- self maybeGenerateCheckLZCNT.
  self generateVMOwnerLockFunctions.
  self genGetLeafCallStackPointers.
  self generateStackPointerCapture.
  self generateTrampolines.
  self computeEntryOffsets.
  self computeFullBlockEntryOffsets.
  self generateClosedPICPrototype.
  self alignMethodZoneBase.
 
  "None of the above is executed beyond ceCheckFeatures, so a bulk flush now is the leanest thing to do."
  backEnd flushICacheFrom: startAddress to: methodZoneBase asUnsignedInteger.
  self maybeFlushWritableZoneFrom: startAddress to: methodZoneBase asUnsignedInteger.
  "Repeat so that now the methodZone ignores the generated run-time."
  methodZone manageFrom: methodZoneBase to: endAddress.
  "N.B. this is assumed to be the last thing done in initialization; see Cogit>>initialized.
  This is done only to compute openPICSize; the generated code is discarded."
  self generateOpenPICPrototype!

Item was removed:
- ----- Method: Cogit>>maybeGenerateCheckFeatures (in category 'initialization') -----
- maybeGenerateCheckFeatures
- | startAddress |
- <inline: true>
- backEnd numCheckFeaturesOpcodes > 0 ifTrue:
- [self allocateOpcodes: backEnd numCheckFeaturesOpcodes bytecodes: 0.
- startAddress := methodZoneBase.
- backEnd generateCheckFeatures.
- self outputInstructionsForGeneratedRuntimeAt: startAddress.
- self recordGeneratedRunTime: 'ceCheckFeaturesFunction' address: startAddress.
- ceCheckFeaturesFunction := self cCoerceSimple: startAddress to: #'usqIntptr_t (*)(void)'.
- backEnd initialFlushICacheFrom: startAddress to: methodZoneBase]!

Item was removed:
- ----- Method: Cogit>>maybeGenerateCheckLZCNT (in category 'initialization') -----
- maybeGenerateCheckLZCNT
- | startAddress |
- <inline: true>
- backEnd numCheckLZCNTOpcodes > 0 ifTrue:
- [self allocateOpcodes: backEnd numCheckLZCNTOpcodes bytecodes: 0.
- startAddress := methodZoneBase.
- methodLabel address: startAddress. "for pc-relative MoveCq: 16r80000001 R: RAX;"
- backEnd generateCheckLZCNT.
- self outputInstructionsForGeneratedRuntimeAt: startAddress.
- self recordGeneratedRunTime: 'ceCheckLZCNTFunction' address: startAddress.
- ceCheckLZCNTFunction := self cCoerceSimple: startAddress to: #'usqIntptr_t (*)(void)']!

Item was added:
+ ----- Method: Cogit>>resetMethodZoneBase: (in category 'initialization') -----
+ resetMethodZoneBase: address
+ "For throw-away/one-off compilations"
+ <inline: #always>
+ methodZoneBase := address!

Item was changed:
  ----- Method: Cogit>>simulateCeFlushDCacheFrom:to: (in category 'simulation only') -----
  simulateCeFlushDCacheFrom: start to: finish
  <doNotGenerate>
+ self simulateLeafCallOf: ceFlushDCache
+ marshaling: [processor abiMarshalArg0: start arg1: finish in: objectMemory memory]!
- processor abiMarshallArg0: start arg1: finish.
- self simulateLeafCallOf: ceFlushDCache!

Item was changed:
  ----- Method: Cogit>>simulateCeFlushICacheFrom:to: (in category 'simulation only') -----
  simulateCeFlushICacheFrom: start to: finish
  <doNotGenerate>
+ self simulateLeafCallOf: ceFlushICache
+ marshaling: [processor abiMarshalArg0: start arg1: finish in: objectMemory memory]!
- processor abiMarshallArg0: start arg1: finish.
- self simulateLeafCallOf: ceFlushICache!

Item was removed:
- ----- Method: Cogit>>simulateLeafCallOf: (in category 'simulation only') -----
- simulateLeafCallOf: someFunction
- "Simulate execution of machine code that leaf-calls someFunction,
- answering the result returned by someFunction."
- "CogProcessorAlienInspector openFor: coInterpreter"
- <doNotGenerate>
- | priorSP priorPC priorLR spOnEntry bogusRetPC |
- self recordRegisters.
- priorSP := processor sp.
- priorPC := processor pc.
- priorLR := backEnd hasLinkRegister ifTrue: [processor lr].
- processor
- setFramePointer: coInterpreter getCFramePointer stackPointer: coInterpreter getCStackPointer;
- simulateLeafCallOf: someFunction
- nextpc: (bogusRetPC := 16rBADF00D5 roundTo: backEnd codeGranularity)
- memory: coInterpreter memory.
- spOnEntry := processor sp.
- self recordInstruction: {'(simulated call of '. someFunction. ')'}.
- ^[[processor pc between: self class guardPageSize and: methodZone zoneEnd] whileTrue:
- [[singleStep
- ifTrue: [self recordProcessing.
- self maybeBreakAt: processor pc.
- processor
- singleStepIn: coInterpreter memory
- minimumAddress: guardPageSize
- readOnlyBelow: methodZone zoneEnd]
- ifFalse: [processor
- runInMemory: coInterpreter memory
- minimumAddress: guardPageSize
- readOnlyBelow: methodZone zoneEnd]]
- on: ProcessorSimulationTrap, Error
- do: [:ex|
- "Again this is a hack for the processor simulators not properly simulating returns to bogus addresses.
- In this case BochsX64Alien doesn't do the right thing."
- processor pc = bogusRetPC ifTrue:
- [self recordInstruction: {'(simulated (real) return to '. processor pc. ')'}.
- ^processor cResultRegister].
- ex isProcessorSimulationTrap ifFalse:
- [ex pass].
- ex applyTo: self.
- ex type == #return ifTrue:
- [^processor cResultRegister]]].
- processor pc = bogusRetPC ifTrue:
- [self recordInstruction: {'(simulated (real) return to '. processor pc. ')'}].
- processor cResultRegister]
- ensure:
- [processor sp: priorSP.
- processor pc: priorPC.
- priorLR ifNotNil: [:lr| processor lr: lr]]!

Item was added:
+ ----- Method: Cogit>>simulateLeafCallOf:marshaling: (in category 'simulation only') -----
+ simulateLeafCallOf: someFunction marshaling: marshallingBlock
+ "Simulate execution of machine code that leaf-calls someFunction,
+ answering the result returned by someFunction."
+ "CogProcessorAlienInspector openFor: coInterpreter"
+ <doNotGenerate>
+ | priorSP priorPC priorLR spOnEntry bogusRetPC |
+ self recordRegisters.
+ priorSP := processor sp.
+ priorPC := processor pc.
+ priorLR := backEnd hasLinkRegister ifTrue: [processor lr].
+ processor
+ setFramePointer: coInterpreter getCFramePointer
+ stackPointer: coInterpreter getCStackPointer.
+ marshallingBlock value.
+ processor
+ simulateLeafCallOf: someFunction
+ nextpc: (bogusRetPC := 16rBADF00D5 roundTo: backEnd codeGranularity)
+ memory: coInterpreter memory.
+ spOnEntry := processor sp.
+ self recordInstruction: {'(simulated call of '. someFunction. ')'}.
+ ^[[processor pc between: self class guardPageSize and: methodZone zoneEnd] whileTrue:
+ [[singleStep
+ ifTrue: [self recordProcessing.
+ self maybeBreakAt: processor pc.
+ processor
+ singleStepIn: coInterpreter memory
+ minimumAddress: guardPageSize
+ readOnlyBelow: methodZone zoneEnd]
+ ifFalse: [processor
+ runInMemory: coInterpreter memory
+ minimumAddress: guardPageSize
+ readOnlyBelow: methodZone zoneEnd]]
+ on: ProcessorSimulationTrap, Error
+ do: [:ex|
+ "Again this is a hack for the processor simulators not properly simulating returns to bogus addresses.
+ In this case BochsX64Alien doesn't do the right thing."
+ processor pc = bogusRetPC ifTrue:
+ [self recordInstruction: {'(simulated (real) return to '. processor pc. ')'}.
+ ^processor cResultRegister].
+ ex isProcessorSimulationTrap ifFalse:
+ [ex pass].
+ ex applyTo: self.
+ ex type == #return ifTrue:
+ [^processor cResultRegister]]].
+ processor pc = bogusRetPC ifTrue:
+ [self recordInstruction: {'(simulated (real) return to '. processor pc. ')'}].
+ processor cResultRegister]
+ ensure:
+ [processor sp: priorSP.
+ processor pc: priorPC.
+ priorLR ifNotNil: [:lr| processor lr: lr]]!

Item was changed:
  ----- Method: Cogit>>tryLockVMOwner: (in category 'multi-threading') -----
  tryLockVMOwner: value
  <api>
  "ceTryLockVMOwner does an atomic compare-and-swap of the lock
  with the argument and zero, setting the lock to value if it was zero.
  It answers non-zero if the lock was zero."
  <cmacro: '(value) ceTryLockVMOwner(value)'>
+ ^0 ~= (self
+ simulateLeafCallOf: ceTryLockVMOwner
+ marshaling: [processor abiMarshalArg0: value in: objectMemory memory])!
- processor abiMarshallArg0: value.
- ^(self simulateLeafCallOf: ceTryLockVMOwner) ~= 0!

Item was changed:
  ----- Method: Cogit>>unlockVMOwner (in category 'multi-threading') -----
  unlockVMOwner
  <api>
  <cmacro: '() ceUnlockVMOwner()'>
+ ^self simulateLeafCallOf: ceUnlockVMOwner marshaling: []!
- ^self simulateLeafCallOf: ceUnlockVMOwner!