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! |
Free forum by Nabble | Edit this page |