Cogit trampolines

cePICMissTrampoline

ceCallCogCodePopReceiverAndClassRegs

ceCallCogCodePopReceiverReg

ceCannotResumeTrampoline

ceCaptureCStackPointers

ceCheckFeaturesFunction

ceCheckForInterruptTrampoline

ceEnclosingObjectTrampoline

ceEnterCogCodePopReceiverReg

ceFetchContextInstVarTrampoline

ceFlushICache

ceFreeTrampoline

ceGetFP

ceGetSP

ceMallocTrampoline

ceMethodAbortTrampoline

ceNonLocalReturnTrampoline

cePICAbortTrampoline

cePrimReturnEnterCogCode

cePrimReturnEnterCogCodeProfiling

ceReapAndResetErrorCodeTrampoline

ceReturnToInterpreterTrampoline

ceSendMustBeBooleanAddFalseTrampoline

ceSendMustBeBooleanAddTrueTrampoline

ceStoreContextInstVarTrampoline

ceTraceBlockActivationTrampoline

ceTraceLinkedSendTrampoline

ceTraceStoreTrampoline

ceTryLockVMOwner

ceUnlockVMOwner

SimpleStackBasedCogit trampolines

ceCPICMissTrampoline

ceCheckForInterruptTrampoline

ceEnclosingObjectTrampoline

ceFetchContextInstVarTrampoline

ceMethodAbortTrampoline

ceNonLocalReturnTrampoline

cePICAbortTrampoline

cePrimReturnEnterCogCode

cePrimReturnEnterCogCodeProfiling

ceReapAndResetErrorCodeTrampoline

ceStoreContextInstVarTrampoline

ceTraceBlockActivationTrampoline

ceTraceLinkedSendTrampoline

ceTraceStoreTrampoline

StackToRegisterMappingCogit trampolines

ceEnclosingObjectTrampoline

ceFetchContextInstVarTrampoline

ceNonLocalReturnTrampoline

ceReapAndResetErrorCodeTrampoline

ceStoreContextInstVarTrampoline

ceTraceBlockActivationTrampoline

ceTraceLinkedSendTrampoline

ceTraceStoreTrampoline

RegisterAllocatingCogit trampolines

ceCheckForInterruptTrampoline

ceSendMustBeBooleanAddFalseTrampoline

ceSendMustBeBooleanAddTrueTrampoline

Trampoline generation

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.
	hasYoungReferent := false.

	self
		enableCodeZoneWriteDuring: [ 	
			objectRepresentation maybeGenerateSelectorIndexDereferenceRoutine.
			self generateSendTrampolines.                        "Send variations"
			self generateMissAbortTrampolines.                   "PIC Miss/Abort"
			objectRepresentation generateObjectRepresentationTrampolines.
			self generateRunTimeTrampolines.                     "Runtime"
			self generateEnilopmarts.                            "Enilopmarts (machine code to C)"
			self generateTracingTrampolines.                     "Tracing methods"
			self recordGeneratedRunTime: 'methodZoneBase' address: methodZoneBase]
		flushingCacheWith: [ self flushICacheFrom: methodZoneStart asUnsignedInteger to: methodZoneBase asUnsignedInteger ].

Selector Dereference

0x6a03000: ceGetFP
0x6a03008: ceGetSP
0x6a03010: ceCaptureCStackPointers
0x6a03080: ceDereferenceSelectorIndex

Send trampolines

generateSendTrampolines
	0 to: NumSendTrampolines - 1 do:
		[:numArgs|
		ordinarySendTrampolines
			at: numArgs
			put: (self genTrampolineFor: #ceSend:super:to:numArgs:
					  called: (self trampolineName: 'ceSend' numArgs: numArgs)
					  arg: ClassReg
					  arg: (self trampolineArgConstant: false)
					  arg: ReceiverResultReg
					  arg: (self numArgsOrSendNumArgsReg: numArgs))].

	"Generate these in the middle so they are within [firstSend, lastSend]."
	BytecodeSetHasDirectedSuperSend ifTrue:
		[0 to: NumSendTrampolines - 1 do:
			[:numArgs|
			directedSuperSendTrampolines
				at: numArgs
				put: (self genTrampolineFor: #ceSend:above:to:numArgs:
						  called: (self trampolineName: 'ceDirectedSuperSend' numArgs: numArgs)
						  arg: ClassReg
						  arg: TempReg
						  arg: ReceiverResultReg
						  arg: (self numArgsOrSendNumArgsReg: numArgs)).
			directedSuperBindingSendTrampolines
				at: numArgs
				put: (self genTrampolineFor: #ceSend:aboveClassBinding:to:numArgs:
						  called: (self trampolineName: 'ceDirectedSuperBindingSend' numArgs: numArgs)
						  arg: ClassReg
						  arg: TempReg
						  arg: ReceiverResultReg
						  arg: (self numArgsOrSendNumArgsReg: numArgs))]].

	0 to: NumSendTrampolines - 1 do:
		[:numArgs|
		superSendTrampolines
			at: numArgs
			put: (self genTrampolineFor: #ceSend:super:to:numArgs:
					  called: (self trampolineName: 'ceSuperSend' numArgs: numArgs)
					  arg: ClassReg
					  arg: (self trampolineArgConstant: true)
					  arg: ReceiverResultReg
					  arg: (self numArgsOrSendNumArgsReg: numArgs))].
	firstSend := ordinarySendTrampolines at: 0.
	lastSend := superSendTrampolines at: NumSendTrampolines - 1
0x6a031c0: ceSend0Args
0x6a03250: ceSend1Args
0x6a032e8: ceSend2Args
0x6a03388: ceSendNArgs
0x6a03410: ceDirectedSuperSend0Args
0x6a034a0: ceDirectedSuperBindingSend0Args
0x6a03530: ceDirectedSuperSend1Args
0x6a035c8: ceDirectedSuperBindingSend1Args
0x6a03660: ceDirectedSuperSend2Args
0x6a03700: ceDirectedSuperBindingSend2Args
0x6a037a0: ceDirectedSuperSendNArgs
0x6a03828: ceDirectedSuperBindingSendNArgs
0x6a038b0: ceSuperSend0Args
0x6a03940: ceSuperSend1Args
0x6a039d8: ceSuperSend2Args
0x6a03a78: ceSuperSendNArgs

PIC Miss/Abort trampolines

generateMissAbortTrampolines
	"Generate the run-time entries for the various method and PIC entry misses and aborts.
	 Read the class-side method trampolines for documentation on the various trampolines"
	0 to: self numRegArgs + 1 do:
		[:numArgs|
		methodAbortTrampolines
			at: numArgs
			put: (self genMethodAbortTrampolineFor: numArgs)].
	0 to: self numRegArgs + 1 do:
		[:numArgs|
		picAbortTrampolines
			at: numArgs
			put: (self genPICAbortTrampolineFor: numArgs)].
	0 to: self numRegArgs + 1 do:
		[:numArgs|
		picMissTrampolines
			at: numArgs
			put: (self genPICMissTrampolineFor: numArgs)].
	ceReapAndResetErrorCodeTrampoline := self genTrampolineFor: #ceReapAndResetErrorCodeFor:
												called: 'ceReapAndResetErrorCodeTrampoline'
												arg: ClassReg
0x6a03b00: ceMethodAbort0Args
0x6a03be0: ceMethodAbort1Args
0x6a03cc8: ceMethodAbort2Args
0x6a03db8: ceMethodAbortNArgs
0x6a03e88: cePICAbort0Args
0x6a03f68: cePICAbort1Args
0x6a04050: cePICAbort2Args
0x6a04140: cePICAbortNArgs
0x6a04210: cePICMiss0Args
0x6a04280: cePICMiss1Args
0x6a042f8: cePICMiss2Args
0x6a04378: cePICMissNArgs
0x6a043e0: ceReapAndResetErrorCodeTrampoline

Object Representation trampolines

generateObjectRepresentationTrampolines
	"Do the store check.  Answer the argument for the benefit of the code generator;
	 ReceiverResultReg may be caller-saved and hence smashed by this call.  Answering
	 it allows the code generator to reload ReceiverResultReg cheaply.
	 In Spur the only thing we leave to the run-time is adding the receiver to the
	 remembered set and setting its isRemembered bit."
	self
		cppIf: IMMUTABILITY
		ifTrue:
			[self cCode: [] inSmalltalk:
				[ceStoreTrampolines := CArrayAccessor on: (Array new: NumStoreTrampolines)].
			 0 to: NumStoreTrampolines - 1 do:
				[:instVarIndex |
				 ceStoreTrampolines
					at: instVarIndex
					put: (self
							genStoreTrampolineCalled: (cogit
								trampolineName: 'ceStoreTrampoline'
								numArgs: instVarIndex
								limit: NumStoreTrampolines - 2)
							instVarIndex: instVarIndex)]].
	ceNewHashTrampoline := self genNewHashTrampoline: false called: 'ceNewHash'.
	SistaVM ifTrue: [ceInlineNewHashTrampoline := self genNewHashTrampoline: true  called: 'ceInlineNewHash'].
	ceStoreCheckTrampoline := self genStoreCheckTrampoline.
	ceStoreCheckContextReceiverTrampoline := self genStoreCheckContextReceiverTrampoline.
	ceScheduleScavengeTrampoline := cogit
		genTrampolineFor: #ceScheduleScavenge
		called: 'ceScheduleScavengeTrampoline'
		regsToSave: CallerSavedRegisterMask.
	ceSmallActiveContextInMethodTrampoline := self
    	genActiveContextTrampolineLarge: false
        inBlock: 0
        called: 'ceSmallMethodContext'.
	ceSmallActiveContextInBlockTrampoline := self
    	genActiveContextTrampolineLarge: false
        inBlock: InVanillaBlock
        called: 'ceSmallBlockContext'.
	SistaV1BytecodeSet ifTrue:
		[ceSmallActiveContextInFullBlockTrampoline := self
        	genActiveContextTrampolineLarge: false
            inBlock: InFullBlock
            called: 'ceSmallFullBlockContext'].
	ceLargeActiveContextInMethodTrampoline := self
    	genActiveContextTrampolineLarge: true
        inBlock: 0
        called: 'ceLargeMethodContext'.
	ceLargeActiveContextInBlockTrampoline := self
    	genActiveContextTrampolineLarge: true
        inBlock: InVanillaBlock
        called: 'ceLargeBlockContext'.
	SistaV1BytecodeSet ifTrue:
		[ceLargeActiveContextInFullBlockTrampoline := self
        	genActiveContextTrampolineLarge: true
            inBlock: InFullBlock
            called: 'ceLargeFullBlockContext'].
0x6a04448: ceStoreTrampoline0Args
0x6a04538: ceStoreTrampoline1Args
0x6a04628: ceStoreTrampoline2Args
0x6a04718: ceStoreTrampoline3Args
0x6a04808: ceStoreTrampolineNArgs
0x6a048f8: ceNewHash
0x6a04960: ceStoreCheckTrampoline
0x6a049e8: ceStoreCheckContextReceiver
0x6a04a90: ceScheduleScavengeTrampoline
0x6a04b10: ceSmallMethodContext
0x6a04ec8: ceSmallBlockContext
0x6a052d0: ceSmallFullBlockContext
0x6a056b0: ceLargeMethodContext
0x6a05a68: ceLargeBlockContext
0x6a05e70: ceLargeFullBlockContext

Runtime trampolines

generateRunTimeTrampolines
	"Generate the run-time entries at the base of the native code zone and update the base."

	ceSendMustBeBooleanAddFalseTrampoline := self genMustBeBooleanTrampolineFor: objectMemory falseObject
												  called: 'ceSendMustBeBooleanAddFalseTrampoline'.
	ceSendMustBeBooleanAddTrueTrampoline := self genMustBeBooleanTrampolineFor: objectMemory trueObject
												 called: 'ceSendMustBeBooleanAddTrueTrampoline'.
	ceNonLocalReturnTrampoline := self genNonLocalReturnTrampoline.
	ceCheckForInterruptTrampoline := self genCheckForInterruptsTrampoline.
	"Neither of the context inst var access trampolines save registers.  Their operation could cause
	 arbitrary update of stack frames, so the assumption is that callers flush the stack before calling
	 the context inst var access trampolines, and that everything except the result is dead afterwards."
	ceFetchContextInstVarTrampoline := self genTrampolineFor: #ceContext:instVar:
											called: 'ceFetchContextInstVarTrampoline'
											arg: ReceiverResultReg
											arg: SendNumArgsReg
											result: SendNumArgsReg.
	ceStoreContextInstVarTrampoline := self genTrampolineFor: #ceContext:instVar:value:
											called: 'ceStoreContextInstVarTrampoline'
											arg: ReceiverResultReg
											arg: SendNumArgsReg
											arg: ClassReg
											result: ReceiverResultReg. "to keep ReceiverResultReg live.".
	ceCannotResumeTrampoline := self genTrampolineFor: #ceCannotResume
									 called: 'ceCannotResumeTrampoline'.
	"These two are unusual; they are reached by return instructions."
	ceBaseFrameReturnTrampoline := self genReturnTrampolineFor: #ceBaseFrameReturn:
										called: 'ceBaseFrameReturnTrampoline'
										arg: ReceiverResultReg.
	ceReturnToInterpreterTrampoline := self genReturnTrampolineFor: #ceReturnToInterpreter:
											called: 'ceReturnToInterpreterTrampoline'
											arg: ReceiverResultReg.
	ceMallocTrampoline := self genTrampolineFor: #ceMalloc:
							   called: 'ceMallocTrampoline'
							   arg: ReceiverResultReg
						       result: TempReg.
	ceFreeTrampoline := self genTrampolineFor: #ceFree:
						 	 called: 'ceFreeTrampoline'
							 arg: ReceiverResultReg.
0x6a06250: ceSendMustBeBooleanAddFalseTrampoline
0x6a062e8: ceSendMustBeBooleanAddTrueTrampoline
0x6a06380: ceNonLocalReturnTrampoline
0x6a063d8: ceCheckForInterruptsTrampoline
0x6a06430: ceFetchContextInstVarTrampoline
0x6a064a0: ceStoreContextInstVarTrampoline
0x6a06510: ceCannotResumeTrampoline
0x6a06570: ceBaseFrameReturnTrampoline
0x6a065c8: ceReturnToInterpreterTrampoline
0x6a06620: ceMallocTrampoline
0x6a06688: ceFreeTrampoline
Enilopmarts (reverse trampolines)
generateEnilopmarts
	"Enilopmarts transfer control from C into machine code (backwards trampolines).
	 Override to add version for generic and PIC-specific entry with reg args."
	super generateEnilopmarts.

	self cppIf: Debug
		ifTrue:
			[realCECallCogCodePopReceiverArg0Regs :=
				self genEnilopmartFor: ReceiverResultReg
					and: Arg0Reg
					forCall: true
					called: 'realCECallCogCodePopReceiverArg0Regs'.
			 ceCallCogCodePopReceiverArg0Regs := #callCogCodePopReceiverArg0Regs.
			 realCECallCogCodePopReceiverArg1Arg0Regs :=
				self genEnilopmartFor: ReceiverResultReg
					and: Arg0Reg
					and: Arg1Reg
					forCall: true
					called: 'realCECallCogCodePopReceiverArg1Arg0Regs'.
			 ceCallCogCodePopReceiverArg1Arg0Regs := #callCogCodePopReceiverArg1Arg0Regs]
		ifFalse:
			[ceCallCogCodePopReceiverArg0Regs :=
				self genEnilopmartFor: ReceiverResultReg
					and: Arg0Reg
					forCall: true
					called: 'ceCallCogCodePopReceiverArg0Regs'.
			 ceCallCogCodePopReceiverArg1Arg0Regs :=
				self genEnilopmartFor: ReceiverResultReg
					and: Arg0Reg
					and: Arg1Reg
					forCall: true
					called: 'ceCallCogCodePopReceiverArg1Arg0Regs'].

	"These are special versions of the ceCallCogCodePopReceiverAndClassRegs enilopmart that also
	 pop register args from the stack to undo the pushing of register args in the abort/miss trampolines."
	ceCall0ArgsPIC := self genCallPICEnilopmartNumArgs: 0.
	self numRegArgs >= 1 ifTrue:
		[ceCall1ArgsPIC := self genCallPICEnilopmartNumArgs: 1.
		 self numRegArgs >= 2 ifTrue:
			[ceCall2ArgsPIC := self genCallPICEnilopmartNumArgs: 2.
			 self assert: self numRegArgs = 2]]
0x6a066f0: ceEnterCogCodePopReceiverReg
0x6a06720: ceCallCogCodePopReceiverReg
0x6a06758: ceCallCogCodePopReceiverAndClassRegs
0x6a06798: cePrimReturnEnterCogCode
0x6a06838: cePrimReturnEnterCogCodeProfiling
0x6a06928: ceCallCogCodePopReceiverArg0Regs
0x6a06968: ceCallCogCodePopReceiverArg1Arg0Regs
0x6a069b0: ceCallPIC0Args
0x6a069f0: ceCallPIC1Args
0x6a06a38: ceCallPIC2Args

Tracing trampolines

generateTracingTrampolines
	"Generate trampolines for tracing.  In the simulator we can save a lot of time
	 and avoid noise instructions in the lastNInstructions log by short-cutting these
	 trampolines, but we need them in the real vm."
	ceTraceLinkedSendTrampoline :=
		self genTrampolineFor: #ceTraceLinkedSend:
			called: 'ceTraceLinkedSendTrampoline'
			arg: ReceiverResultReg
			regsToSave: CallerSavedRegisterMask.
	ceTraceBlockActivationTrampoline :=
		self genTrampolineFor: #ceTraceBlockActivation
			called: 'ceTraceBlockActivationTrampoline'
			regsToSave: CallerSavedRegisterMask..
	ceTraceStoreTrampoline :=
		self genTrampolineFor: #ceTraceStoreOf:into:
			called: 'ceTraceStoreTrampoline'
			arg: ClassReg
			arg: ReceiverResultReg
			regsToSave: CallerSavedRegisterMask..
	self cCode: [] inSmalltalk:
		[ceTraceLinkedSendTrampoline := self simulatedTrampolineFor: #ceShortCutTraceLinkedSend:.
		 ceTraceBlockActivationTrampoline := self simulatedTrampolineFor: #ceShortCutTraceBlockActivation:.
		 ceTraceStoreTrampoline := self simulatedTrampolineFor: #ceShortCutTraceStore:]
0x6a06a88: ceTraceLinkedSendTrampoline
0x6a06b10: ceTraceBlockActivationTrampoline
0x6a06b90: ceTraceStoreTrampoline