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

commits at source.squeak.org commits at source.squeak.org
Sat Dec 21 03:36:37 UTC 2019


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

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

Name: VMMaker.oscog-eem.2623
Author: eem
Time: 20 December 2019, 7:36:17.393248 pm
UUID: aa831407-e9c0-4df9-9d8c-57ee755c1440
Ancestors: VMMaker.oscog-eem.2622

Cogit:
Now that a processor is allowed to refuse to do CmpR: SPReg R: ?Reg, rewrite genGetActiveContextLarge:inBlock: to do its SPReg comparison the other way around.
Fix a bug in an assert now that method alignment can be > 8.

AbstractInstructionTests:
Refactor common code into convenience methods. Implement runSubRR:on:.  Two down.  Quite a few to go.

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

Item was added:
+ ----- Method: AbstractInstructionTests>>assertValidRunResult:ofAtLeast: (in category 'private') -----
+ assertValidRunResult: result "{ numSubTests. numPassingSubTests }" ofAtLeast: minimumExpectedNumberOfSubTests
+ 	self assert: result isArray.
+ 	self assert: result size >= 2.
+ 	self assert: (result first isInteger and: [result second isInteger]).
+ 	self assert: result first >= minimumExpectedNumberOfSubTests.
+ 	self assert: result first = result second "All sub-tests pass"!

Item was added:
+ ----- Method: AbstractInstructionTests>>cogitForTests (in category 'accessing') -----
+ cogitForTests
+ 	"Answer a new CogitForTests, with initialization performed for the current ISA."
+ 	VMClass initializationOptions at: #ISA put: self isaName.
+ 	^CogitForTests new!

Item was added:
+ ----- Method: AbstractInstructionTests>>defaultCodeStart (in category 'private') -----
+ defaultCodeStart
+ 	^1024!

Item was added:
+ ----- Method: AbstractInstructionTests>>generatedCodeFrom: (in category 'private') -----
+ generatedCodeFrom: aCogit
+ 	| instructions memory |
+ 	instructions := aCogit generatedMachineCodeAt: self defaultCodeStart. "Avoid any guard page effects in the simulators, i.e. Gdb's ARM32 requires pc >= 16"
+ 	"self processor disassembleFrom: 1024 to: instructions size - 1 in: instructions"
+ 	(memory := ByteArray new: self defaultCodeStart + 1024) replaceFrom: 1 to: instructions size with: instructions startingAt: 1.
+ 	aCogit stopsFrom: instructions size to: memory size - 1 in: memory.
+ 	^memory!

Item was changed:
  ----- Method: AbstractInstructionTests>>runCmpRRJumpCond:on: (in category 'running') -----
  runCmpRRJumpCond: assertPrintBar on: aStream
+ 	"Compile and evaluate as many combinations of CmpR:R: JumpCond: as possible, checking that they produce the
- 	"Compile and evaluate as many combinations of CmpR;R: JumpCond: as possible, checking that they produce the
  	 expected result.  Answer an array of the number of comparisons and the number of them that succeeded."
  	"self defaultTester runCmpRRJumpCond: false"
  	| cogit nTests nGood |
+ 	cogit := self cogitForTests.
- 	VMClass initializationOptions at: #ISA put: self isaName.
- 	cogit := CogitForTests new.
  	nTests := nGood := 0.
  	self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do:
  		[:sreg :srgetter :srsetter|
  		self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do:
  			[:dreg :drgetter :drsetter| 
  			(sreg ~= dreg "N.B. We do not expect the backEnd to provide CmpR: SPReg R: reg, only CmpR: reg R: SPReg"
  			 and: [drgetter ~= #sp]) ifTrue:
  				[#(	= ~=
  					> > >= >=
  					< < <= <=)
  					with: #(JumpZero: JumpNonZero:
  							JumpGreater: JumpAbove: JumpGreaterOrEqual: JumpAboveOrEqual:
  							JumpLess: JumpBelow: JumpLessOrEqual: JumpBelowOrEqual:)
+ 					do: [:comparison :instruction| | unsigned jmp memory |
- 					do: [:comparison :instruction| | unsigned jmp instructions memory |
  						unsigned := (instruction includesSubstring: 'Above')
  									or: [instruction includesSubstring: 'Below'].
  						"(drgetter = #sp or: [srgetter = #sp]) ifTrue: [self halt]."
  						cogit resetGen.
  						cogit CmpR: dreg R: sreg.
  						jmp := cogit perform: instruction with: 0.
  						cogit
  							MoveCq: 0 R: cogit backEnd cResultRegister;
  							Jump: 1536.
  						jmp jmpTarget: (cogit MoveCq: 1 R: cogit backEnd cResultRegister).
  						cogit Jump: 1536.
+ 						memory := self generatedCodeFrom: cogit.
+ 						"self processor disassembleFrom: 1024 to: cogit codeSize - 1024 * 2 + 1024 in: memory ''"
+ 						self pairs: { -1 << 30. "-1 << 16." -1 << 8. 0. 1 << 8. "1 << 16." 1 << 30 } do:
- 						instructions := cogit generatedMachineCodeAt: 1024. "Avoid any guard page effects in the simulators, i.e. Gdb's ARM32 requires pc >= 16"
- 						"self processor disassembleFrom: 1024 to: instructions size - 1 in: instructions"
- 						(memory := ByteArray new: 2048) replaceFrom: 1 to: instructions size with: instructions startingAt: 1.
- 						cogit stopsFrom: instructions size to: memory size - 1 in: memory.
- 						"self processor disassembleFrom: 1024 to: instructions size - 1024 * 2 + 1024 in: memory ''"
- 						self pairs: { "-1 << 30. -1 << 16." -1 << 8. 0. 1 << 8. "1 << 16. 1 << 30" } do:
  							[:a :b| | bogus error expected nInsts |
  							nTests := nTests + 1.
  							error := false.
  							nInsts := 0.
  							self processor
  								reset;
+ 								pc: self defaultCodeStart;
- 								pc: 1024;
  								perform: srsetter with: (processor convertIntegerToInternal: a);
  								perform: drsetter with: (processor convertIntegerToInternal: b).
  							[[processor pc ~= 1536 and: [nInsts < 16]] whileTrue:
  								[processor singleStepIn: memory. nInsts := nInsts + 1]]
  								on: Error
  								do: [:ex| error := true].
  							nInsts >= 16 ifTrue: [error := true].
+ 							"self processor disassembleInstructionAt: 0 In: memory"
- 							"self processor printRegistersOn: Transcript.
- 							 Transcript show: (self processor disassembleInstructionAt: 0 In: memory); cr"
  							bogus := (processor pc = 1536 and: [#[0 1] includes: processor cResultRegister]) not.
  							assertPrintBar ifTrue: [self deny: bogus].
  							expected := unsigned
  												ifTrue: [(a bitAnd: 1 << 32 - 1) perform: comparison with: (b bitAnd: 1 << 32 - 1)]
  												ifFalse: [a perform: comparison with: b].
  							(bogus or: [error or: [self processor cResultRegister = 1 ~= expected]]) ifFalse: [nGood := nGood + 1].
  							assertPrintBar
  								ifTrue: [self assert: self processor cResultRegister = 1 equals: expected]
  								ifFalse:
  									[self processor cResultRegister = 1 ~= expected ifTrue:
  										[aStream nextPutAll: srgetter; space; nextPutAll: comparison; space; nextPutAll: drgetter.
  									 unsigned ifTrue: [aStream nextPutAll: ' (unsigned)'].
  									 aStream nextPutAll: (error ifTrue: [' ERRORED'] ifFalse: [' is incorrect']); cr; flush.
  									 bogus ifTrue:
  										[self processor printRegistersOn: aStream.
  										 aStream nextPutAll: (self processor disassembleInstructionAt: 0 In: memory); cr; flush]]]]]]]].
  	assertPrintBar ifFalse:
  		[aStream print: nTests; nextPutAll: ' tests; '; print: nGood; nextPutAll: ' good'; cr].
  	^{nTests. nGood}!

Item was removed:
- ----- Method: AbstractInstructionTests>>runSubRR: (in category 'running') -----
- runSubRR: assertPrintBar
- 	"self defaultTester runSubRR: false"
- 	self concreteCompilerClass dataRegistersWithAccessorsDo:
- 		[:sreg :srgetter :srsetter|
- 		self concreteCompilerClass dataRegistersWithAccessorsDo:
- 			[:dreg :drgetter :drsetter| | inst len memory |
- 			inst := self gen: SubRR operand: sreg operand: dreg.
- 			len := inst concretizeAt: 0.
- 			memory := self memoryAsBytes: inst machineCode.
- 			self pairs: (-2 to: 2) do:
- 				[:a :b| | bogus |
- 				self processor
- 					reset;
- 					perform: srsetter with: (processor convertIntegerToInternal: a);
- 					perform: drsetter with: (processor convertIntegerToInternal: b).
- 				[[processor pc < len] whileTrue:
- 					[self processor singleStepIn: memory]]
- 					on: Error
- 					do: [:ex| ].
- 				"self processor printRegistersOn: Transcript.
- 				 Transcript show: (self processor disassembleInstructionAt: 0 In: memory); cr"
- 				assertPrintBar
- 					ifTrue: [self assert: processor pc = inst machineCodeSize]
- 					ifFalse: [bogus := processor pc ~= inst machineCodeSize].
- 				self concreteCompilerClass dataRegistersWithAccessorsDo:
- 					[:ireg :getter :setter| | expected |
- 					expected := drgetter == srgetter
- 									ifTrue: [0]
- 									ifFalse:
- 										[getter == drgetter
- 											ifTrue: [b - a]
- 											ifFalse: [getter = srgetter
- 														ifTrue: [a]
- 														ifFalse: [0]]].
- 					assertPrintBar
- 						ifTrue: [self assert: (self processor convertInternalToInteger: (self processor perform: getter)) equals: expected]
- 						ifFalse:
- 							[(self processor convertInternalToInteger: (self processor perform: getter)) ~= expected ifTrue:
- 								[bogus := true]]].
- 					assertPrintBar ifFalse:
- 						[Transcript
- 							nextPutAll: drgetter; nextPut: $(; print: b; nextPutAll: ') - ';
- 							nextPutAll: srgetter; nextPut: $(; print: a; nextPutAll: ') = ';
- 							print: (self processor convertInternalToInteger: (self processor perform: drgetter)); cr; flush.
- 						 bogus ifTrue:
- 							[self processor printRegistersOn: Transcript.
- 							 Transcript show: (self processor disassembleInstructionAt: 0 In: memory); cr]]]]]!

Item was added:
+ ----- Method: AbstractInstructionTests>>runSubRR:on: (in category 'running') -----
+ runSubRR: assertPrintBar on: aStream
+ 	"Compile and evaluate as many combinations of SubR:R: as possible, checking that they produce the
+ 	 expected result.  Answer an array of the number of comparisons and the number of them that succeeded."
+ 	"self defaultTester runSubRR: false"
+ 	| cogit nTests nGood |
+ 	cogit := self cogitForTests.
+ 	nTests := nGood := 0.
+ 	self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do:
+ 		[:sreg :srgetter :srsetter|
+ 		self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do:
+ 			[:dreg :drgetter :drsetter| | memory limit |
+ 			(drgetter == #sp						"Some processors can't do this easily; i.e. ARMv8"
+ 			 or: [drgetter == srgetter]) ifFalse:		"Some processors refuse to do this; i.e. ARMv8"
+ 				[cogit resetGen.
+ 				cogit
+ 					SubR: sreg R: dreg;
+ 					Nop.
+ 				memory := self generatedCodeFrom: cogit.
+ 				limit := cogit codeSize.
+ 				self pairs: (-2 to: 2) do:
+ 					[:a :b| | bogus error nInsts allRegistersGood |
+ 					nTests := nTests + 1.
+ 					error := false.
+ 					nInsts := 0.
+ 					self processor
+ 						reset;
+ 						pc: self defaultCodeStart;
+ 						perform: srsetter with: (processor convertIntegerToInternal: a);
+ 						perform: drsetter with: (processor convertIntegerToInternal: b).
+ 					[[processor pc < limit and: [nInsts < 16]] whileTrue:
+ 						[processor singleStepIn: memory. nInsts := nInsts + 1]]
+ 						on: Error
+ 						do: [:ex| error := true].
+ 					nInsts >= 16 ifTrue: [error := true].
+ 					"self processor disassembleInstructionAt: self defaultCodeStart In: memory"
+ 					bogus := processor pc ~= limit.
+ 					assertPrintBar ifTrue: [self assert: processor pc = limit].
+ 					allRegistersGood := (bogus or: [error]) not.
+ 					self concreteCompilerClass dataRegistersWithAccessorsGiven: self processor do:
+ 						[:ireg :getter :setter| | expected |
+ 						expected := drgetter == srgetter
+ 										ifTrue: [0]
+ 										ifFalse:
+ 											[getter == drgetter
+ 												ifTrue: [b - a]
+ 												ifFalse: [getter = srgetter
+ 															ifTrue: [a]
+ 															ifFalse: [0]]].
+ 						assertPrintBar
+ 							ifTrue: [self assert: (self processor convertInternalToInteger: (self processor perform: getter)) equals: expected]
+ 							ifFalse:
+ 								[(self processor convertInternalToInteger: (self processor perform: getter)) ~= expected ifTrue:
+ 									[bogus := true]].
+ 						(self processor convertInternalToInteger: (self processor perform: getter)) ~= expected ifTrue: [allRegistersGood := false].
+ 						assertPrintBar ifFalse:
+ 							[aStream
+ 								nextPutAll: drgetter; nextPut: $(; print: b; nextPutAll: ') - ';
+ 								nextPutAll: srgetter; nextPut: $(; print: a; nextPutAll: ') = ';
+ 								print: (self processor convertInternalToInteger: (self processor perform: drgetter)); cr; flush]].
+ 					allRegistersGood ifTrue: [nGood := nGood + 1]]]]].
+ 	assertPrintBar ifFalse:
+ 		[aStream print: nTests; nextPutAll: ' tests; '; print: nGood; nextPutAll: ' good'; cr].
+ 	^{nTests. nGood}!

Item was added:
+ ----- Method: AbstractInstructionTests>>testCogitForTests (in category 'tests') -----
+ testCogitForTests
+ 	self assert: (self cogitForTests backEnd isKindOf: self concreteCompilerClass)!

Item was added:
+ ----- Method: AbstractInstructionTests>>testRunCmpRR (in category 'tests') -----
+ testRunCmpRR
+ 	"self defaultTester testRunSubRR"
+ 	| result |
+ 	result := self runCmpRRJumpCond: true on: NullStream new.
+ 	"Assume at least 5 registers.  There are ten comparisons. and we compare 5 values"
+ 	self assertValidRunResult: result ofAtLeast: 5 squared * 10 * 5 squared!

Item was changed:
  ----- Method: AbstractInstructionTests>>testRunSubRR (in category 'tests') -----
  testRunSubRR
  	"self defaultTester testRunSubRR"
+ 	| result |
+ 	result := self runSubRR: true on: NullStream new.
+ 	"Assume at least 5 registers. We subtract 5 pairs"
+ 	self assertValidRunResult: result ofAtLeast: 5 squared * 5 squared!
- 	self runSubRR: true!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genGetActiveContextLarge:inBlock: (in category 'initialization') -----
  genGetActiveContextLarge: isLarge inBlock: isInBlock
  	"Create a trampoline to answer the active context that will
  	 answer it if a frame is already married, and create it otherwise.
  	 Assume numArgs is in SendNumArgsReg and ClassReg is free."
  	| header slotSize jumpSingle loopHead jumpNeedScavenge continuation exit |
  	<var: #jumpNeedScavenge type: #'AbstractInstruction *'>
  	<var: #continuation type: #'AbstractInstruction *'>
  	<var: #jumpSingle type: #'AbstractInstruction *'>
  	<var: #loopHead type: #'AbstractInstruction *'>
  	<var: #exit type: #'AbstractInstruction *'>
  	cogit "load the flag; stash it in both TempReg & ClassReg; do the compare (a prime candidated for use of AndCq:R:R:)"
  		MoveMw: FoxMethod r: FPReg R: ClassReg;
  		AndCq: MFMethodFlagHasContextFlag R: ClassReg R: TempReg.
  	jumpSingle := cogit JumpZero: 0. "jump if flag bit not set"
  	cogit "since the flag bit was set, get the context in the receiver reg and return"
  		MoveMw: FoxThisContext r: FPReg R: ReceiverResultReg;
  		RetN: 0.
  	jumpSingle jmpTarget: cogit Label.
  
  	"OK, it doesn't exist; instantiate and initialize it"
  	"set the hasContext flag; See CoInterpreter class>>initializeFrameIndices"
  	cogit
  		OrCq: MFMethodFlagHasContextFlag R: ClassReg;
  		MoveR: ClassReg Mw: FoxMethod r: FPReg.
  	"now get the home CogMethod into ClassReg and save for post-instantiation."
  	isInBlock caseOf: {
  	[InFullBlock]	-> [cogit SubCq: 3 R: ClassReg]. "-3 is -(hasContext+isBlock) flags"
  	[InVanillaBlock]	-> [cogit
  							SubCq: 3 R: ClassReg; "-3 is -(hasContext+isBlock) flags"
  							MoveM16: 0 r: ClassReg R: TempReg;
  							SubR: TempReg R: ClassReg].
  	[0]				-> [cogit SubCq: 1 R: ClassReg]. "-1 is hasContext flag" }.
  
  	"instantiate the context..."
  	slotSize := isLarge ifTrue: [LargeContextSlots] ifFalse: [SmallContextSlots].
  	header := objectMemory
  					headerForSlots: slotSize
  					format: objectMemory indexablePointersFormat
  					classIndex: ClassMethodContextCompactIndex.
  	self flag: #endianness.
  	cogit MoveAw: objectMemory freeStartAddress R: ReceiverResultReg.
  	self genStoreHeader: header intoNewInstance: ReceiverResultReg using: TempReg.
  	cogit
  		MoveR: ReceiverResultReg R: TempReg;
  		AddCq: (objectMemory smallObjectBytesForSlots: slotSize) R: TempReg;
  		MoveR: TempReg Aw: objectMemory freeStartAddress;
  		CmpCq: objectMemory getScavengeThreshold R: TempReg.
  	jumpNeedScavenge := cogit JumpAboveOrEqual: 0.
  
  	"Now initialize the fields of the context.  See CoInterpreter>>marryFrame:SP:copyTemps:"
  	"sender gets frame pointer as a SmallInteger"
  	continuation :=
  	cogit MoveR: FPReg R: TempReg.
  	self genSetSmallIntegerTagsIn: TempReg.
  	cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (SenderIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"pc gets frame caller as a SmallInteger"
  	cogit MoveMw: FoxSavedFP r: FPReg R: TempReg.
  	self genSetSmallIntegerTagsIn: TempReg.
  	cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (InstructionPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"Set the method field, freeing up ClassReg again, and frame's context field,"
  	cogit
  		MoveMw: (cogit offset: CogMethod of: #methodObject) r: ClassReg R: TempReg;
  		MoveR: TempReg Mw: objectMemory baseHeaderSize + (MethodIndex * objectMemory wordSize) r: ReceiverResultReg;
  		MoveR: ReceiverResultReg Mw: FoxThisContext r: FPReg.
  
  	"Now compute stack pointer; this is stackPointer (- 1 for return pc if a CISC) - framePointer - wordSize (1 each for saved pc, method, context, receiver) + 1 (1-relative) + numArgs"
  	"TPR note - the code here is actually doing
  	context stackPointer := ((((fp - sp) / wordSize) - [3|4]) + num args) asSmallInteger"
  	cogit
  		SubR: SPReg R: FPReg R: TempReg; "TempReg := FPReg - SPReg"
  		LogicalShiftRightCq: self log2BytesPerWord R: TempReg;
  		SubCq: (cogit backEnd hasLinkRegister ifTrue: [3] ifFalse: [4]) R: TempReg;
  		AddR: SendNumArgsReg R: TempReg.
  	self genConvertIntegerToSmallIntegerInReg: TempReg.
  	cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (StackPointerIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"Set closureOrNil to either the stacked receiver or nil"
  	isInBlock > 0
  		ifTrue:
  			[cogit
  				MoveR: SendNumArgsReg R: TempReg;
  				AddCq: 2 R: TempReg; "+2 for saved fp and saved pc"
  				MoveXwr: TempReg R: FPReg R: TempReg]
  		ifFalse:
  			[cogit genMoveNilR: TempReg].
  	cogit MoveR: TempReg Mw: objectMemory baseHeaderSize + (ClosureIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"Set the receiver"
  	cogit
  		MoveMw: FoxMFReceiver r: FPReg R: TempReg;
  		MoveR: TempReg Mw: objectMemory baseHeaderSize + (ReceiverIndex * objectMemory bytesPerOop) r: ReceiverResultReg.
  
  	"Now copy the arguments.  This is tricky because of the shortage of registers,.  ClassReg ranges
  	 from 1 to numArgs (SendNumArgsReg), and from ReceiverIndex + 1 to ReceiverIndex + numArgs.
  	 1 to: numArgs do:
  		[:i|
  		temp := longAt(FPReg + ((SendNumArgs - i + 2) * wordSize)). +2 for saved pc and savedfp
  		longAtput(FPReg + FoxMFReceiver + (i * wordSize), temp)]"
  	"TPR note: this is a prime candidate for passing off to the backend to do at least faintly optimal code"
  	cogit MoveCq: 1 R: ClassReg.
  	loopHead := cogit CmpR: SendNumArgsReg R: ClassReg.
  	exit := cogit JumpGreater: 0.
  	cogit
  		MoveR: SendNumArgsReg R: TempReg;
  		SubR: ClassReg R: TempReg;
  		AddCq: 2 R: TempReg; "+2 for saved fp and saved pc"
  		MoveXwr: TempReg R: FPReg R: TempReg;
  		AddCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) R: ClassReg; "Now convert ClassReg from frame index to context index"
  		MoveR: TempReg Xwr: ClassReg R: ReceiverResultReg;
  		SubCq: ReceiverIndex + (objectMemory baseHeaderSize / objectMemory wordSize) - 1 R: ClassReg; "convert back adding 1 ;-)"
  		Jump: loopHead.
  	exit jmpTarget: cogit Label.
  
  	"Finally nil or copy the non-argument temps.
  	 ClassReg := FPReg + FoxMFReceiver.
  	 SendNumArgsReg := SendNumArgsReg+ReceiverIndex.
  	 [ClassReg := ClassReg - wordSize.
  	  backEnd hasLinkRegister
  			ifTrue: [ClassReg > SPReg]
  			ifFalse: [ClassReg >= SPReg]] whileTrue:
  		[receiver[SendNumArgsReg] := *ClassReg.
  		 SendNumArgsReg := SendNumArgsReg + 1]]"
  	coInterpreter marryFrameCopiesTemps ifFalse:
  		[cogit MoveCq: objectMemory nilObject R: TempReg].
  	cogit
  		MoveR: FPReg R: ClassReg;
  		AddCq: FoxMFReceiver R: ClassReg;
  		AddCq: ReceiverIndex + 1 + (objectMemory baseHeaderSize / objectMemory wordSize) R: SendNumArgsReg.
  	loopHead :=
  	cogit SubCq: objectMemory wordSize R: ClassReg.
+ 	cogit CmpR: ClassReg R: SPReg.
- 	cogit CmpR: SPReg R: ClassReg.
  	"If on a CISC there's a retpc for the trampoline call on top of stack; if on a RISC there isn't."
  	exit := cogit backEnd hasLinkRegister
+ 				ifTrue: [cogit JumpAboveOrEqual: 0]
+ 				ifFalse: [cogit JumpBelow: 0].
- 				ifTrue: [cogit JumpBelow: 0]
- 				ifFalse: [cogit JumpBelowOrEqual: 0].
  	coInterpreter marryFrameCopiesTemps ifTrue:
  		[cogit MoveMw: 0 r: ClassReg R: TempReg].
  	cogit
  		MoveR: TempReg Xwr: SendNumArgsReg R: ReceiverResultReg;
  		AddCq: 1 R: SendNumArgsReg;
  		Jump: loopHead.
  	exit jmpTarget: cogit Label.
  
  	cogit RetN: 0.
  	
  	jumpNeedScavenge jmpTarget: cogit Label.
  	cogit backEnd saveAndRestoreLinkRegAround:
  		[cogit
  			CallRT: ceScheduleScavengeTrampoline
  			registersToBeSavedMask: (cogit registerMaskFor: ReceiverResultReg and: SendNumArgsReg and: ClassReg)].
  	cogit Jump: continuation.
  	^0!

Item was changed:
  ----- Method: Cogit>>blockAlignment (in category 'accessing') -----
  blockAlignment
  	"Block method headers must be aligned on the correct boundary, just like non-block method headers.
  	 This is because the CoInterpreter encodes flags in the least significant three bits of the method field."
  	<api>
  	<cmacro: '() 8'>
+ 	self assert: (methodZone roundUpLength: 1) >= 8.
- 	self assert: (methodZone roundUpLength: 1) = 8.
  	^8!

Item was added:
+ ----- Method: CogitForTests>>codeSize (in category 'generate machine code') -----
+ codeSize
+ 	"Answer the size of code generated, which includes the offset at which the code was generated."
+ 	^codeBytes size!



More information about the Vm-dev mailing list