VM Maker: VMMaker.oscog-eem.2623.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.2623.mcz

commits-2
 
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!