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

commits at source.squeak.org commits at source.squeak.org
Tue Apr 21 18:11:17 UTC 2015


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

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

Name: VMMaker.oscog-eem.1231
Author: eem
Time: 21 April 2015, 11:09:26.049 am
UUID: 208aaef1-8c8d-43fb-8af9-5189214ff390
Ancestors: VMMaker.oscog-tpr.1230

Cogit:
Change map generationa nd interpretation so that
the displacements are in codeGranularity units, and
make the codeGranularity 4 on ARM.  Comment
machineCodeSize and maxSize.

Fix a translation-time warning for
outputMachineCodeAt: (thanks Esteban).

Introduce UnfailingPrimitive and use it to avoid
generating the interpreter primitive call in Spur
the Character>>asInteger primitive.

=============== Diff against VMMaker.oscog-tpr.1230 ===============

Item was added:
+ ----- Method: CogARMCompiler>>codeGranularity (in category 'accessing') -----
+ codeGranularity
+ 	"Answer the size in bytes of a unit of machine code."
+ 	<inline: true>
+ 	^4!

Item was changed:
  ----- Method: CogARMCompiler>>outputMachineCodeAt: (in category 'inline cacheing') -----
+ outputMachineCodeAt: targetAddress
+ 	"Override to move machine code a word at a time."
- outputMachineCodeAt: address
- 	"By default move machine code a byte at a time
- 	  Subclasses with coarser granularity can override as desired."
  	<inline: true>
  	0 to: machineCodeSize - 1 by: 4 do:
  		[:j|
+ 		objectMemory longAt: targetAddress + j put: (machineCode at: j // 4)]!
- 		objectMemory longAt: address + j put: (machineCode at: j // 4)]!

Item was changed:
  VMStructType subclass: #CogAbstractInstruction
  	instanceVariableNames: 'opcode machineCodeSize maxSize machineCode operands address dependent cogit objectMemory bcpc'
  	classVariableNames: 'NumOperands'
  	poolDictionaries: 'CogRTLOpcodes'
  	category: 'VMMaker-JIT'!
  
+ !CogAbstractInstruction commentStamp: 'eem 4/21/2015 09:12' prior: 0!
+ I am an abstract instruction generated by the Cogit.  I am subsequently concretized to machine code for the current processor.  A sequence of concretized CogAbstractInstructions are concatenated to form the code for a CogMethod.  I am an abstract class.  My concrete subclasses concretize to the machine code of a specific processor.
+ 
+ Instance Variables
+ 	address:			<Integer>
+ 	bcpc:				<Integer>
+ 	cogit:				<Cogit>
+ 	dependent:			<AbstractInstruction|nil>
+ 	machineCode:		<CArray on: (ByteArray|Array)>
+ 	machineCodeSize:	<Integer>
+ 	maxSize:			<Integer>
+ 	objectMemory:		<NewCoObjectMemory|SpurCoMemoryManager etc>
+ 	opcode:			<Integer>
+ 	operands:			<CArray on: Array>
+ 
+ address
+ 	- the address at which the instruction will be generated
+ 
+ bcpc
+ 	- the bytecode pc for which the instruction was generated; simulation only
+ 
+ cogit
+ 	- the Cogit assembling the receiver; simulation only
+ 
+ dependent
+ 	- a reference to another instruction which depends on the receiver, if any; in C this is a pointer
+ 
+ machineCode
+ 	- the array of machine code the receiver generates when concretized
+ 
+ machineCodeSize
+ 	- the size of machineCode in bytes
+ 
+ maxSize
+ 	- the maximum size of machine code that the current instruction will generate, in bytes
+ 
+ objectMemory
+ 	- the memory manager for the system; simulation only
+ 
+ opcode
+ 	- the opcode for the receiver which defines which abstract opcode it represents; see CogRTLOpcodes class>>initialize and CogAbstractInstruction subclass initialize methods
+ 
+ operands
+ 	- the array containing any operands the instruction may have; the opcode defines implicitly how many operands are consdered!
- !CogAbstractInstruction commentStamp: 'eem 7/17/2012 15:04' prior: 0!
- I am an abstract instruction generated by the Cogit.  I am subsequently concretized to machine code for the current processor.  A sequence of concretized CogAbstractInstructions are concatenated to form the code for a CogMethod.  I am an abstract class.  My concrete subclasses concretize to the machine code of a specific processor.!

Item was added:
+ ----- Method: CogAbstractInstruction>>codeGranularity (in category 'accessing') -----
+ codeGranularity
+ 	"Answer the size in bytes of a unit of machine code."
+ 	<inline: true>
+ 	^self subclassResponsibility!

Item was changed:
  ----- Method: CogAbstractInstruction>>machineCodeSize (in category 'accessing') -----
  machineCodeSize
+ 	"N.B. This is a byte size."
  	^machineCodeSize!

Item was changed:
  ----- Method: CogAbstractInstruction>>machineCodeSize: (in category 'accessing') -----
  machineCodeSize: size "<signed byte>"
+ 	"N.B. This is a byte size."
  	^machineCodeSize := size!

Item was changed:
  ----- Method: CogAbstractInstruction>>maxSize (in category 'accessing') -----
  maxSize
+ 	"N.B. This is a byte size."
  	^maxSize!

Item was changed:
  ----- Method: CogAbstractInstruction>>maxSize: (in category 'accessing') -----
+ maxSize: size "<signed byte>"
+ 	"N.B. This is a byte size."
+ 	maxSize := size!
- maxSize: anObject
- 	"Set the value of maxSize"
- 
- 	maxSize := anObject!

Item was added:
+ ----- Method: CogIA32Compiler>>codeGranularity (in category 'accessing') -----
+ codeGranularity
+ 	"Answer the size in bytes of a unit of machine code."
+ 	<inline: true>
+ 	^1!

Item was changed:
  ----- Method: CogIA32Compiler>>dispatchConcretize (in category 'generate machine code') -----
  dispatchConcretize
  	"Attempt to generate concrete machine code for the instruction at address.
  	 This is the inner dispatch of concretizeAt: actualAddress which exists only
  	 to get around the branch size limits in the SqueakV3 (blue book derived)
  	 bytecode set."
  	<returnTypeC: #void>
  	opcode caseOf: {
  		"Noops & Pseudo Ops"
  		[Label]				-> [^self concretizeLabel].
  		[AlignmentNops]	-> [^self concretizeAlignmentNops].
  		[Fill16]				-> [^self concretizeFill16].
  		[Fill32]				-> [^self concretizeFill32].
  		[FillFromWord]		-> [^self concretizeFillFromWord].
  		[Nop]				-> [^self concretizeNop].
  		"Specific Control/Data Movement"
  		[CDQ]					-> [^self concretizeCDQ].
  		[IDIVR]					-> [^self concretizeIDIVR].
  		[IMULRR]				-> [^self concretizeMulRR].
  		[CPUID]					-> [^self concretizeCPUID].
  		[CMPXCHGAwR]			-> [^self concretizeCMPXCHGAwR].
  		[CMPXCHGMwrR]		-> [^self concretizeCMPXCHGMwrR].
  		[LFENCE]				-> [^self concretizeFENCE: 5].
  		[MFENCE]				-> [^self concretizeFENCE: 6].
  		[SFENCE]				-> [^self concretizeFENCE: 7].
  		[LOCK]					-> [^self concretizeLOCK].
  		[XCHGAwR]				-> [^self concretizeXCHGAwR].
  		[XCHGMwrR]			-> [^self concretizeXCHGMwrR].
  		[XCHGRR]				-> [^self concretizeXCHGRR].
  		"Control"
  		[Call]					-> [^self concretizeCall].
  		[CallFull]				-> [^self concretizeCall].
  		[JumpR]					-> [^self concretizeJumpR].
+ 		[JumpFull]				-> [^self concretizeJumpLong].
+ 		[JumpLong]				-> [^self concretizeJumpLong].
- 		[JumpFull]				-> [^self concretizeJumpFull].
- 		[JumpLong]				-> [^self concretizeJump].
  		[JumpLongZero]		-> [^self concretizeConditionalJump: 16r4].
  		[JumpLongNonZero]	-> [^self concretizeConditionalJump: 16r5].
  		[Jump]					-> [^self concretizeJump].
  		"Table B-1 Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 1: Basic Architecture"
  		[JumpZero]				-> [^self concretizeConditionalJump: 16r4].
  		[JumpNonZero]			-> [^self concretizeConditionalJump: 16r5].
  		[JumpNegative]			-> [^self concretizeConditionalJump: 16r8].
  		[JumpNonNegative]		-> [^self concretizeConditionalJump: 16r9].
  		[JumpOverflow]			-> [^self concretizeConditionalJump: 16r0].
  		[JumpNoOverflow]		-> [^self concretizeConditionalJump: 16r1].
  		[JumpCarry]			-> [^self concretizeConditionalJump: 16r2].
  		[JumpNoCarry]			-> [^self concretizeConditionalJump: 16r3].
  		[JumpLess]				-> [^self concretizeConditionalJump: 16rC].
  		[JumpGreaterOrEqual]	-> [^self concretizeConditionalJump: 16rD].
  		[JumpGreater]			-> [^self concretizeConditionalJump: 16rF].
  		[JumpLessOrEqual]		-> [^self concretizeConditionalJump: 16rE].
  		[JumpBelow]			-> [^self concretizeConditionalJump: 16r2].
  		[JumpAboveOrEqual]	-> [^self concretizeConditionalJump: 16r3].
  		[JumpAbove]			-> [^self concretizeConditionalJump: 16r7].
  		[JumpBelowOrEqual]	-> [^self concretizeConditionalJump: 16r6].
  		[JumpFPEqual]				-> [^self concretizeConditionalJump: 16r4].
  		[JumpFPNotEqual]			-> [^self concretizeConditionalJump: 16r5].
  		[JumpFPLess]				-> [^self concretizeConditionalJump: 16r2].
  		[JumpFPGreaterOrEqual]	-> [^self concretizeConditionalJump: 16r3].
  		[JumpFPGreater]			-> [^self concretizeConditionalJump: 16r7].
  		[JumpFPLessOrEqual]		-> [^self concretizeConditionalJump: 16r6].
  		[JumpFPOrdered]			-> [^self concretizeConditionalJump: 16rB].
  		[JumpFPUnordered]			-> [^self concretizeConditionalJump: 16rA].
  		[RetN]						-> [^self concretizeRetN].
  		[Stop]						-> [^self concretizeStop].
  		"Arithmetic"
  		[AddCqR]					-> [^self concretizeAddCqR].
  		[AddCwR]					-> [^self concretizeAddCwR].
  		[AddRR]						-> [^self concretizeAddRR].
  		[AddRdRd]					-> [^self concretizeSEE2OpRdRd: 16r58].
  		[AndCqR]					-> [^self concretizeAndCqR].
  		[AndCwR]					-> [^self concretizeAndCwR].
  		[AndRR]						-> [^self concretizeAndRR].
  		[CmpCqR]					-> [^self concretizeCmpCqR].
  		[CmpCwR]					-> [^self concretizeCmpCwR].
  		[CmpRR]					-> [^self concretizeCmpRR].
  		[CmpRdRd]					-> [^self concretizeCmpRdRd].
  		[DivRdRd]					-> [^self concretizeSEE2OpRdRd: 16r5E].
  		[MulRdRd]					-> [^self concretizeSEE2OpRdRd: 16r59].
  		[OrCqR]						-> [^self concretizeOrCqR].
  		[OrCwR]					-> [^self concretizeOrCwR].
  		[OrRR]						-> [^self concretizeOrRR].
  		[SubCqR]					-> [^self concretizeSubCqR].
  		[SubCwR]					-> [^self concretizeSubCwR].
  		[SubRR]						-> [^self concretizeSubRR].
  		[SubRdRd]					-> [^self concretizeSEE2OpRdRd: 16r5C].
  		[SqrtRd]						-> [^self concretizeSqrtRd].
  		[XorCwR]						-> [^self concretizeXorCwR].
  		[XorRR]							-> [^self concretizeXorRR].
  		[NegateR]						-> [^self concretizeNegateR].
  		[LoadEffectiveAddressMwrR]	-> [^self concretizeLoadEffectiveAddressMwrR].
  		[ArithmeticShiftRightCqR]		-> [^self concretizeArithmeticShiftRightCqR].
  		[LogicalShiftRightCqR]			-> [^self concretizeLogicalShiftRightCqR].
  		[LogicalShiftLeftCqR]			-> [^self concretizeLogicalShiftLeftCqR].
  		[ArithmeticShiftRightRR]			-> [^self concretizeArithmeticShiftRightRR].
  		[LogicalShiftLeftRR]				-> [^self concretizeLogicalShiftLeftRR].
  		"Data Movement"
  		[MoveCqR]			-> [^self concretizeMoveCqR].
  		[MoveCwR]			-> [^self concretizeMoveCwR].
  		[MoveRR]			-> [^self concretizeMoveRR].
  		[MoveAwR]			-> [^self concretizeMoveAwR].
  		[MoveRAw]			-> [^self concretizeMoveRAw].
  		[MoveMbrR]			-> [^self concretizeMoveMbrR].
  		[MoveRMbr]			-> [^self concretizeMoveRMbr].
  		[MoveM16rR]		-> [^self concretizeMoveM16rR].
  		[MoveM64rRd]		-> [^self concretizeMoveM64rRd].
  		[MoveMwrR]		-> [^self concretizeMoveMwrR].
  		[MoveXbrRR]		-> [^self concretizeMoveXbrRR].
  		[MoveRXbrR]		-> [^self concretizeMoveRXbrR].
  		[MoveXwrRR]		-> [^self concretizeMoveXwrRR].
  		[MoveRXwrR]		-> [^self concretizeMoveRXwrR].
  		[MoveRMwr]		-> [^self concretizeMoveRMwr].
  		[MoveRdM64r]		-> [^self concretizeMoveRdM64r].
  		[PopR]				-> [^self concretizePopR].
  		[PushR]				-> [^self concretizePushR].
  		[PushCq]			-> [^self concretizePushCq].
  		[PushCw]			-> [^self concretizePushCw].
  		[PrefetchAw]		-> [^self concretizePrefetchAw].
  		"Conversion"
  		[ConvertRRd]		-> [^self concretizeConvertRRd] }!

Item was changed:
  SharedPool subclass: #CogMethodConstants
  	instanceVariableNames: ''
+ 	classVariableNames: 'CMBlock CMClosedPIC CMFree CMMaxUsageCount CMMethod CMOpenPIC CheckAllocationFillerAfterPrimCall EncounteredUnknownBytecode InsufficientCodeSpace MaxLiteralCountForCompile MaxMethodSize MaxNegativeErrorCode MaxNumArgs MaxStackCheckOffset MethodTooBig NotFullyInitialized PrimCallCollectsProfileSamples PrimCallDoNotJIT PrimCallMayCallBack PrimCallNeedsNewMethod PrimCallNeedsPrimitiveFunction ShouldNotJIT UnfailingPrimitive UnimplementedPrimitive YoungSelectorInPIC'
- 	classVariableNames: 'CMBlock CMClosedPIC CMFree CMMaxUsageCount CMMethod CMOpenPIC CheckAllocationFillerAfterPrimCall EncounteredUnknownBytecode InsufficientCodeSpace MaxLiteralCountForCompile MaxMethodSize MaxNegativeErrorCode MaxNumArgs MaxStackCheckOffset MethodTooBig NotFullyInitialized PrimCallCollectsProfileSamples PrimCallDoNotJIT PrimCallMayCallBack PrimCallNeedsNewMethod PrimCallNeedsPrimitiveFunction ShouldNotJIT UnimplementedPrimitive YoungSelectorInPIC'
  	poolDictionaries: ''
  	category: 'VMMaker-JIT'!

Item was changed:
  ----- Method: CogObjectRepresentationForSpur>>genInnerPrimitiveCharacterValue: (in category 'primitive generators') -----
  genInnerPrimitiveCharacterValue: retNOffset
  	self genConvertCharacterToSmallIntegerInReg: ReceiverResultReg.
  	cogit RetN: retNOffset.
+ 	^UnfailingPrimitive!
- 	^0!

Item was changed:
  ----- Method: Cogit class>>initializeAnnotationConstants (in category 'class initialization') -----
  initializeAnnotationConstants
+ 	"These form the method map for a cog method.  The map defines which addresses
+ 	 in a machine code method are ones with important functions, such as being a send
+ 	 site or being a reference to a heap object.  Each annotated instruction has a byte
+ 	 in the map, and each byte in the map has two parts.  In the least signficant bits are
+ 	 a distance in codeGranularity units from the start of the method or the previous
+ 	 map entry, except for the IsAnnotationExtension type.  In the most signficant bits
+ 	 are the type of annotation at the point reached.  A null byte ends the map.  The
+ 	 first mapped location is a distance from the cmNoCheckEntryOffset.
- 	"These form the method map for a cog method.  Each annotated instruction has a
- 	 byte in the map, and each byte in the map has two parts.  In the least signficant
- 	 bits are a byte distance from the start of the method or previous map entry.  In
- 	 the most signficant bits are the type of annotation at the point reached.  A null
- 	 byte ends the map.
  
  	 The map occurs at the end of a method (*), in reverse, so that its start is found
  	 by adding the method's block size.  If the distance between two mapped
  	 instructions will not fit in the displacement field then one or more displacement
+ 	 entries are placed in the map to bridge the gap.  There is a * 32 displacement
+ 	 units type for spanning large gaps.  The displacements are in codeGranularity
+ 	 units so that processors like e.g. ARM, with 4-byte instructions, do not have overly
+ 	 large maps.  In [practice maps are very compact, but they should be as quick to
+ 	 navigate as possible, and hence be as compact as possible.
- 	 entries are placed in the map to bridge the gap.  There are either unit displacement
- 	 bytes or * 32 displacement bytes. (* if methods have performance counters then
- 	 the map preceedes the counters and so one finds the map by adding the block
- 	 size and subtracting numCounters * sizeof(counter)).
  
  	 There is only one kind of call annotation that serves for all calls from machine
  	 code. There are several kinds of call, sends, super sends, calls of the generated
  	 run-time, and direct calls of primitive functions in the interpreter.  These need
  	 different treatment at different times.  For example, when the send cache is
  	 flushed or the method zone is shrunk some sends must be unlinked and some
  	 sends must be relocated.  But to be able to parse bytecoded methods and match
  	 their pcs with corresponding machine code pcs the map needs to differentiate
  	 between sends and run-time calls. 
  
  	 Sends can be distinguished from run-time or direct primitive calls based on address;
  	 only sends have their target between methodZoneBase and methodZone freeStart.
+ 	 We used to distinguish normal sends from super sends based on alignment of
+ 	 entry-point, because normal sends link to the checked entry-point, whereas super sends
+ 	 link to the unchecked entry-point, and both entry points have different alignments.
+ 	 But now we use the IsAnnotationExtension to label sends other than normal sends.
+ 	 For these ``exotic'' sends there is both an IsAnnotationExtension annotation and an
+ 	 IsSendCall annotation.
- 	 We used to distinguish normal sends from super sends because normal sends link to
- 	 the checked entry-point, whereas super sends link to the unchecked entry-point, and
- 	 both entry points have different alignment.  But now we use the IsAnnotationExtension
- 	 to label sends other than normal sends.  For these ``exotic'' sends there is both an
- 	 IsAnnotationExtension annotation and an IsSendCall annotation.
  
  	 While run-time calls can be distinguished from direct primitive calls on the basis
  	 of address there is no need to do so.  They are merely calls to locations that
  	 don't move during method zone compaction.
  
  	 Absolute PC references are used for method references and counter references.
  	 These are references from within a particular method to absolute pcs in that same
  	 method that must be relocated when the method moves."
  	"self initializeAnnotationConstants"
  
  	AnnotationShift := 5.
+ 	IsDisplacementX2N := 0.	"N.B. A 0 byte ends the map"
- 	IsDisplacementX2N := 0.	"N.B. 0 byet ends the map"
  	IsAnnotationExtension := 1.	"Used to extend IsSendCall with different codes for exotic send types."
  	IsObjectReference := 2.
  	IsAbsPCReference := 3.
  	HasBytecodePC := 4.
  	IsRelativeCall := 5.
  	IsNSSendCall := NewspeakVM ifTrue: [6].
  	IsSendCall := 7.
  	"These are formed by combining IsSendCall and IsAnnotationExtension annotations."
  	IsSuperSend := 8.
  	IsDirectedSuperSend := 9.
  	IsNSSelfSend := NewspeakVM ifTrue: [10].
  	IsNSDynamicSuperSend := NewspeakVM ifTrue: [11].
  	IsNSImplicitReceiverSend := NewspeakVM ifTrue: [12].
  
  	DisplacementMask := (1 << AnnotationShift) - 1.
  	DisplacementX2N := IsDisplacementX2N << AnnotationShift.
  	FirstAnnotation := IsObjectReference << AnnotationShift.
  	MaxX2NDisplacement := DisplacementMask << AnnotationShift.
  
  	MapEnd := 0.
  
  	AnnotationConstantNames := #(	IsDisplacementX2N
  										IsAnnotationExtension
  										IsObjectReference
  										IsAbsPCReference
  										HasBytecodePC
  										IsRelativeCall
  										IsNSSendCall
  										IsSendCall
  										IsSuperSend
  										IsDirectedSuperSend
  										IsNSSelfSend
  										IsNSDynamicSuperSend
  										IsNSImplicitReceiverSend).
  	AnnotationsWithBytecodePCs := #(HasBytecodePC
  										IsNSSendCall
  										IsSendCall
  										IsSuperSend
  										IsDirectedSuperSend
  										IsNSSelfSend
  										IsNSDynamicSuperSend
  										IsNSImplicitReceiverSend)!

Item was changed:
  ----- Method: Cogit class>>initializeErrorCodes (in category 'class initialization') -----
  initializeErrorCodes
  	"External errors, returned to or from cog:selector:"
  	NotFullyInitialized := -1.
  	InsufficientCodeSpace := -2.
  	MethodTooBig := -4.
  	YoungSelectorInPIC := -5.
  	EncounteredUnknownBytecode := -6.
  	UnimplementedPrimitive := -7.
  	ShouldNotJIT := -8.
  	MaxNegativeErrorCode := ShouldNotJIT.
  	"Internal errors returned by generator routines to other generator routines"
+ 	BadRegisterSet := 1.
+ 	"Internal successes answered by CogObjectRepresentation to JIT, etc"
+ 	UnfailingPrimitive := 2.!
- 	BadRegisterSet := 1!

Item was changed:
  ----- Method: Cogit>>findMapLocationForMcpc:inMethod: (in category 'method map') -----
  findMapLocationForMcpc: targetMcpc inMethod: cogMethod
  	<var: #cogMethod type: #'CogMethod *'>
  	| mcpc map mapByte annotation |
  	mcpc := cogMethod asInteger + cmNoCheckEntryOffset.
  	map := self mapStartFor: cogMethod.
  	mcpc = targetMcpc ifTrue: [^map].
  	[(mapByte := objectMemory byteAt: map) ~= MapEnd] whileTrue:
  		[annotation := mapByte >> AnnotationShift.
  		 annotation ~= IsAnnotationExtension ifTrue:
+ 			[mcpc := mcpc + (backEnd codeGranularity
+ 								* (annotation = IsDisplacementX2N
+ 									ifTrue: [mapByte - DisplacementX2N << AnnotationShift]
+ 									ifFalse: [mapByte bitAnd: DisplacementMask]))].
- 			[mcpc := mcpc + (annotation = IsDisplacementX2N
- 								ifTrue: [mapByte - DisplacementX2N << AnnotationShift]
- 								ifFalse: [mapByte bitAnd: DisplacementMask])].
  		 mcpc >= targetMcpc ifTrue:
  			[self assert: mcpc = targetMcpc.
  			 annotation = IsDisplacementX2N ifTrue:
  				[map := map - 1.
  				 mapByte := objectMemory byteAt: map.
  				 annotation := mapByte >> AnnotationShift.
  				 self assert: annotation > IsAnnotationExtension].
  			 ^map].
  		 map := map - 1].
  	^0!

Item was changed:
  ----- Method: Cogit>>generateMapAt:start: (in category 'method map') -----
  generateMapAt: addressOrNull start: startAddress
+ 	"Generate the method map at addressrNull (or compute it if addressOrNull is null).
- 	"Generate the method map at addressrNull (or compute it if adressOrNull is null).
  	 Answer the length of the map in byes.  Each entry in the map is in two parts.  In the
  	 least signficant bits are a displacement of how far from the start or previous entry,
  	 unless it is an IsAnnotationExtension byte, in which case those bits are the extension.
  	 In the most signficant bits are the type of annotation at the point reached.  A null
  	 byte ends the map."
  	| length location |
  	<var: #annotation type: #'InstructionAnnotation *'>
  	length := 0.
  	location := startAddress.
  	0 to: annotationIndex - 1 do:
  		[:i| | annotation mcpc delta maxDelta mapEntry |
  		 annotation := self addressOf: (annotations at: i).
  		 mcpc := annotation instruction address + annotation instruction machineCodeSize.
+ 		 [(delta := mcpc - location / backEnd codeGranularity) > DisplacementMask] whileTrue:
- 		 [(delta := mcpc - location) > DisplacementMask] whileTrue:
  			[maxDelta := (delta min: MaxX2NDisplacement) bitClear: DisplacementMask.
  			 self assert: maxDelta >> AnnotationShift <= DisplacementMask.
  			 addressOrNull ifNotNil:
  				[objectMemory
  					byteAt: addressOrNull - length
  					put: maxDelta >> AnnotationShift + DisplacementX2N.
  				 self traceMap: IsDisplacementX2N
  					  byte: maxDelta >> AnnotationShift + DisplacementX2N
  					  at: addressOrNull - length
  					  for: mcpc].
+ 			 location := location + (maxDelta * backEnd codeGranularity).
- 			 location := location + maxDelta.
  			 length := length + 1].
  		 addressOrNull ifNotNil:
  			[mapEntry := delta + ((annotation annotation min: IsSendCall) << AnnotationShift).
  			 objectMemory byteAt: addressOrNull - length put: mapEntry.
  			 self traceMap: annotation
  				  byte: mapEntry
  				  at: addressOrNull - length
  				  for: mcpc].
+ 		 location := location + (delta * backEnd codeGranularity)..
- 		 location := location + delta.
  		 length := length + 1.
  		 annotation annotation > IsSendCall ifTrue: "Add the necessary IsAnnotationExtension"
  			[addressOrNull ifNotNil:
  				[mapEntry := IsAnnotationExtension << AnnotationShift + (annotation annotation - IsSendCall).
  				 objectMemory byteAt: addressOrNull - length put: mapEntry.
  				 self traceMap: annotation
  					  byte: mapEntry
  					  at: addressOrNull - length
  					  for: mcpc].
  			 length := length + 1]].
  	addressOrNull ifNotNil:
  		[objectMemory byteAt: addressOrNull - length put: MapEnd.
  		 self traceMap: MapEnd
  			  byte: MapEnd
  			  at: addressOrNull - length
  			  for: 0].
  	^length + 1!

Item was changed:
  ----- Method: Cogit>>mapFor:bcpc:performUntil:arg: (in category 'method map') -----
  mapFor: cogMethod bcpc: startbcpc performUntil: functionSymbol arg: arg
  	"Machine-code <-> bytecode pc mapping support.  Evaluate functionSymbol
  	 for each mcpc, bcpc pair in the map until the function returns non-zero,
  	 answering that result, or 0 if it fails to.  This works only for frameful methods."
  	<var: #cogMethod type: #'CogBlockMethod *'>
  	<var: #functionSymbol declareC: 'sqInt (*functionSymbol)(BytecodeDescriptor *desc, sqInt isBackwardBranch, char *mcpc, sqInt bcpc, void *arg)'>
  	<var: #arg type: #'void *'>
  	<inline: true>
  	| isInBlock mcpc bcpc endbcpc map mapByte homeMethod aMethodObj result
  	  latestContinuation byte descriptor bsOffset nExts |
  	<var: #descriptor type: #'BytecodeDescriptor *'>
  	<var: #homeMethod type: #'CogMethod *'>
  	self assert: cogMethod stackCheckOffset > 0.
  	"In both CMMethod and CMBlock cases find the start of the map and
  	 skip forward to the bytecode pc map entry for the stack check."
  	cogMethod cmType = CMMethod
  		ifTrue:
  			[isInBlock := false.
  			 homeMethod := self cCoerceSimple: cogMethod to: #'CogMethod *'.
  			 self assert: startbcpc = (coInterpreter startPCOfMethodHeader: homeMethod methodHeader).
  			 map := self mapStartFor: homeMethod.
  			 self assert: ((objectMemory byteAt: map) >> AnnotationShift = IsAbsPCReference
  						 or: [(objectMemory byteAt: map) >> AnnotationShift = IsObjectReference
  						 or: [(objectMemory byteAt: map) >> AnnotationShift = IsRelativeCall
  						 or: [(objectMemory byteAt: map) >> AnnotationShift = IsDisplacementX2N]]]).
  			 latestContinuation := startbcpc.
  			 aMethodObj := homeMethod methodObject.
  			 endbcpc := (objectMemory numBytesOf: aMethodObj) - 1.
  			 bsOffset := self bytecodeSetOffsetForHeader: homeMethod methodHeader]
  		ifFalse:
  			[isInBlock := true.
  			 homeMethod := cogMethod cmHomeMethod.
  			 map := self findMapLocationForMcpc: cogMethod asUnsignedInteger + (self sizeof: CogBlockMethod)
  						inMethod: homeMethod.
  			 self assert: map ~= 0.
  			 self assert: ((objectMemory byteAt: map) >> AnnotationShift = HasBytecodePC "fiducial"
  						 or: [(objectMemory byteAt: map) >> AnnotationShift = IsDisplacementX2N]).
  			 [(objectMemory byteAt: map) >> AnnotationShift ~= HasBytecodePC] whileTrue:
  				[map := map - 1].
  			 map := map - 1. "skip fiducial; i.e. the map entry for the pc immediately following the method header."
  			 aMethodObj := homeMethod methodObject.
  			 bcpc := startbcpc - (self blockCreationBytecodeSizeForHeader: homeMethod methodHeader).
  			 bsOffset := self bytecodeSetOffsetForHeader: homeMethod methodHeader.
  			 byte := (objectMemory fetchByte: bcpc ofObject: aMethodObj) + bsOffset.
  			 descriptor := self generatorAt: byte.
  			 endbcpc := self nextBytecodePCFor: descriptor at: bcpc exts: -1 in: aMethodObj].
  	bcpc := startbcpc.
  	mcpc := cogMethod asUnsignedInteger + cogMethod stackCheckOffset.
  	nExts := 0.
  	"The stack check maps to the start of the first bytecode,
  	 the first bytecode being effectively after frame build."
  	result := self perform: functionSymbol
  					with: nil
  					with: false
  					with: (self cCoerceSimple: mcpc to: #'char *')
  					with: startbcpc
  					with: arg.
  	result ~= 0 ifTrue:
  		[^result].
  	"Now skip up through the bytecode pc map entry for the stack check." 
  	[(objectMemory byteAt: map) >> AnnotationShift ~= HasBytecodePC] whileTrue:
  		[map := map - 1].
  	map := map - 1.
  	[(mapByte := objectMemory byteAt: map) ~= MapEnd] whileTrue: "defensive; we exit on bcpc"
  		[mapByte >= FirstAnnotation
  			ifTrue:
  				[| annotation nextBcpc isBackwardBranch |
  				annotation := mapByte >> AnnotationShift.
+ 				mcpc := mcpc + ((mapByte bitAnd: DisplacementMask) * backEnd codeGranularity).
- 				mcpc := mcpc + (mapByte bitAnd: DisplacementMask).
  				(self isPCMappedAnnotation: annotation) ifTrue:
  					[[byte := (objectMemory fetchByte: bcpc ofObject: aMethodObj) + bsOffset.
  					  descriptor := self generatorAt: byte.
  					  isInBlock
  						ifTrue: [bcpc >= endbcpc ifTrue: [^0]]
  						ifFalse:
  							[(descriptor isReturn and: [bcpc >= latestContinuation]) ifTrue: [^0].
  							 (descriptor isBranch or: [descriptor isBlockCreation]) ifTrue:
  								[| targetPC |
  								 targetPC := self latestContinuationPCFor: descriptor at: bcpc exts: nExts in: aMethodObj.
  								 latestContinuation := latestContinuation max: targetPC]].
  					  nextBcpc := self nextBytecodePCFor: descriptor at: bcpc exts: nExts in: aMethodObj.
  					  descriptor isMapped
  					  or: [isInBlock and: [descriptor isMappedInBlock]]] whileFalse:
  						[bcpc := nextBcpc.
  						 nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [0]].
  					isBackwardBranch := descriptor isBranch
  										   and: [self isBackwardBranch: descriptor at: bcpc exts: nExts in: aMethodObj].
  					result := self perform: functionSymbol
  									with: descriptor
  									with: isBackwardBranch
  									with: (self cCoerceSimple: mcpc to: #'char *')
  									with: bcpc
  									with: arg.
  					 result ~= 0 ifTrue:
  						[^result].
  					 bcpc := nextBcpc.
  					 nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [0]]]
  			ifFalse:
  				[self assert: (mapByte >> AnnotationShift = IsDisplacementX2N
  							or: [mapByte >> AnnotationShift = IsAnnotationExtension]).
  				 mapByte < (IsAnnotationExtension << AnnotationShift) ifTrue:
+ 					[mcpc := mcpc + ((mapByte - DisplacementX2N << AnnotationShift) * backEnd codeGranularity)]].
- 					[mcpc := mcpc + (mapByte - DisplacementX2N << AnnotationShift)]].
  		 map := map - 1].
  	^0!

Item was changed:
  ----- Method: Cogit>>mapFor:performAllMapEntriesUntil:arg: (in category 'method map') -----
  mapFor: cogMethod performAllMapEntriesUntil: functionSymbol arg: arg
  	"Analysis support"
  	<doNotGenerate>
  	| mcpc map mapByte result |
  	mcpc := cogMethod asInteger + cmNoCheckEntryOffset.
  	map := self mapStartFor: cogMethod.
  	[(mapByte := objectMemory byteAt: map) ~= MapEnd] whileTrue:
  		[mapByte >= FirstAnnotation
  			ifTrue:
+ 				[mcpc := mcpc + ((mapByte bitAnd: DisplacementMask) * backEnd codeGranularity)]
- 				[mcpc := mcpc + (mapByte bitAnd: DisplacementMask)]
  			ifFalse:
  				[mapByte < (IsAnnotationExtension << AnnotationShift) ifTrue:
+ 					[mcpc := mcpc + ((mapByte - DisplacementX2N << AnnotationShift) * backEnd codeGranularity)]].
- 					[mcpc := mcpc + (mapByte - DisplacementX2N << AnnotationShift)]].
  		 result := self perform: functionSymbol
  					   with: mapByte >> AnnotationShift
  					   with: (self cCoerceSimple: mcpc to: #'char *')
  					   with: arg.
  		 result ~= 0 ifTrue:
  			[^result].
  		 map := map - 1].
  	^0!

Item was changed:
  ----- Method: Cogit>>mapFor:performUntil:arg: (in category 'method map') -----
  mapFor: cogMethod performUntil: functionSymbol arg: arg
  	"Unlinking/GC/Disassembly support"
  	<var: #cogMethod type: #'CogMethod *'>
  	<var: #functionSymbol declareC: 'int (*functionSymbol)(sqInt annotation, char *mcpc, sqInt arg)'>
  	<inline: true>
  	| mcpc map mapByte annotation result |
  	mcpc := cogMethod asInteger + cmNoCheckEntryOffset.
  	map := self mapStartFor: cogMethod.
  	[(mapByte := objectMemory byteAt: map) ~= MapEnd] whileTrue:
  		[mapByte >= FirstAnnotation
  			ifTrue:
+ 				[mcpc := mcpc + ((mapByte bitAnd: DisplacementMask) * backEnd codeGranularity).
- 				[mcpc := mcpc + (mapByte bitAnd: DisplacementMask).
  				 "If this is an IsSendCall annotation, peek ahead for an IsAnnotationExtension, and consume it."
  				 ((annotation := mapByte >> AnnotationShift) = IsSendCall
  				  and: [(mapByte := objectMemory byteAt: map - 1) >> AnnotationShift = IsAnnotationExtension]) ifTrue:
  					[annotation := annotation + (mapByte bitAnd: DisplacementMask).
  					 map := map - 1].
  				 result := self perform: functionSymbol
  							   with: annotation
  							   with: (self cCoerceSimple: mcpc to: #'char *')
  							   with: arg.
  				 result ~= 0 ifTrue:
  					[^result]]
  			ifFalse:
  				[mapByte < (IsAnnotationExtension << AnnotationShift) ifTrue:
+ 					[mcpc := mcpc + ((mapByte - DisplacementX2N << AnnotationShift) * backEnd codeGranularity)]].
- 					[mcpc := mcpc + (mapByte - DisplacementX2N << AnnotationShift)]].
  		 map := map - 1].
  	^0!

Item was changed:
  ----- Method: Cogit>>printPCMapPairsFor:on: (in category 'method map') -----
  printPCMapPairsFor: cogMethod on: aStream
  	<doNotGenerate>
  	<inline: true>
  	| mcpc map mapByte annotation |
  	mcpc := cogMethod asInteger + cmNoCheckEntryOffset.
  	map := self mapStartFor: cogMethod.
  	[(mapByte := objectMemory byteAt: map) ~= MapEnd] whileTrue:
  		[annotation := mapByte >> AnnotationShift.
  		 annotation ~= IsAnnotationExtension ifTrue:
+ 			[mcpc := mcpc + (backEnd codeGranularity
+ 								* (annotation = IsDisplacementX2N
+ 									ifTrue: [mapByte - DisplacementX2N << AnnotationShift]
+ 									ifFalse: [mapByte bitAnd: DisplacementMask]))].
- 			[mcpc := mcpc + (annotation = IsDisplacementX2N
- 								ifTrue: [mapByte - DisplacementX2N << AnnotationShift]
- 								ifFalse: [mapByte bitAnd: DisplacementMask])].
  		 aStream ensureCr.
  		 map printOn: aStream base: 16.
  		 aStream nextPutAll: ': '.
  		 mapByte printOn: aStream base: 16.
  		 aStream space.
  		 annotation printOn: aStream base: 16.
  		 aStream nextPutAll: ' ('; print: (AnnotationConstantNames at: annotation + 1); nextPutAll: ') '.
  		 (mapByte bitAnd: DisplacementMask) printOn: aStream base: 16.
  		 aStream space.
  		 aStream nextPut: $@.
  		 mcpc printOn: aStream base: 16.
  		 aStream flush.
  		 map := map - 1]!

Item was changed:
  ----- Method: SimpleStackBasedCogit>>genPrimitiveCharacterValue (in category 'primitive generators') -----
  genPrimitiveCharacterValue
  	| r |
  	(r := objectRepresentation genInnerPrimitiveCharacterValue: objectMemory wordSize) < 0 ifTrue:
  		[^r].
+ 	^r = UnfailingPrimitive
+ 		ifTrue: [0]
+ 		ifFalse: [self compileFallbackToInterpreterPrimitive]!
- 	^self compileFallbackToInterpreterPrimitive!

Item was changed:
  ----- Method: SistaStackToRegisterMappingCogit>>mapFor:bcpc:withAnnotationPerformUntil:arg: (in category 'method map') -----
  mapFor: cogMethod bcpc: startbcpc withAnnotationPerformUntil: functionSymbol arg: arg
+ 	"A version of mapFor:bcpc:performUntil:arg: that passes the annotation instead of the isBackwardBranch
+ 	 flag. Evaluate functionSymbol for each mcpc, bcpc pair in the map until the function returns non-zero,
+ 	 answering that result, or 0 if it fails to.  This works only for frameful methods"
- 	"A version of mapFor:bcpc:performUntil:arg: that passes the annotation instead of the isBackwardBranch flag."
  	<var: #cogMethod type: #'CogBlockMethod *'>
  	<var: #functionSymbol declareC: 'sqInt (*functionSymbol)(BytecodeDescriptor *desc, sqInt annotation, char *mcpc, sqInt bcpc, void *arg)'>
  	<var: #arg type: #'void *'>
  	<inline: true>
  	| isInBlock mcpc bcpc endbcpc map mapByte homeMethod aMethodObj result
  	  latestContinuation byte descriptor bsOffset nExts annotation |
  	<var: #descriptor type: #'BytecodeDescriptor *'>
  	<var: #homeMethod type: #'CogMethod *'>
  	self assert: cogMethod stackCheckOffset > 0.
  	"In both CMMethod and CMBlock cases find the start of the map and
  	 skip forward to the bytecode pc map entry for the stack check."
  	cogMethod cmType = CMMethod
  		ifTrue:
  			[isInBlock := false.
  			 homeMethod := self cCoerceSimple: cogMethod to: #'CogMethod *'.
  			 self assert: startbcpc = (coInterpreter startPCOfMethodHeader: homeMethod methodHeader).
  			 map := self mapStartFor: homeMethod.
  			 annotation := (objectMemory byteAt: map) >> AnnotationShift.
  			 self assert: (annotation = IsAbsPCReference
  						 or: [annotation = IsObjectReference
  						 or: [annotation = IsRelativeCall
  						 or: [annotation = IsDisplacementX2N]]]).
  			 latestContinuation := startbcpc.
  			 aMethodObj := homeMethod methodObject.
  			 endbcpc := (objectMemory numBytesOf: aMethodObj) - 1.
  			 bsOffset := self bytecodeSetOffsetForHeader: homeMethod methodHeader]
  		ifFalse:
  			[isInBlock := true.
  			 homeMethod := cogMethod cmHomeMethod.
  			 map := self findMapLocationForMcpc: cogMethod asUnsignedInteger + (self sizeof: CogBlockMethod)
  						inMethod: homeMethod.
  			 self assert: map ~= 0.
  			 annotation := (objectMemory byteAt: map) >> AnnotationShift.
  			 self assert: (annotation >> AnnotationShift = HasBytecodePC "fiducial"
  						 or: [annotation >> AnnotationShift = IsDisplacementX2N]).
  			 [(annotation := (objectMemory byteAt: map) >> AnnotationShift) ~= HasBytecodePC] whileTrue:
  				[map := map - 1].
  			 map := map - 1. "skip fiducial; i.e. the map entry for the pc immediately following the method header."
  			 aMethodObj := homeMethod methodObject.
  			 bcpc := startbcpc - (self blockCreationBytecodeSizeForHeader: homeMethod methodHeader).
  			 bsOffset := self bytecodeSetOffsetForHeader: homeMethod methodHeader.
  			 byte := (objectMemory fetchByte: bcpc ofObject: aMethodObj) + bsOffset.
  			 descriptor := self generatorAt: byte.
  			 endbcpc := self nextBytecodePCFor: descriptor at: bcpc exts: -1 in: aMethodObj].
  	bcpc := startbcpc.
  	mcpc := cogMethod asUnsignedInteger + cogMethod stackCheckOffset.
  	nExts := 0.
  	"The stack check maps to the start of the first bytecode,
  	 the first bytecode being effectively after frame build."
  	result := self perform: functionSymbol
  					with: nil
  					with: annotation
  					with: (self cCoerceSimple: mcpc to: #'char *')
  					with: startbcpc
  					with: arg.
  	result ~= 0 ifTrue:
  		[^result].
  	"Now skip up through the bytecode pc map entry for the stack check." 
  	[(objectMemory byteAt: map) >> AnnotationShift ~= HasBytecodePC] whileTrue:
  		[map := map - 1].
  	map := map - 1.
  	[(mapByte := objectMemory byteAt: map) ~= MapEnd] whileTrue: "defensive; we exit on bcpc"
  		[mapByte >= FirstAnnotation
  			ifTrue:
  				[| nextBcpc |
  				annotation := mapByte >> AnnotationShift.
+ 				mcpc := mcpc + ((mapByte bitAnd: DisplacementMask) * backEnd codeGranularity).
- 				mcpc := mcpc + (mapByte bitAnd: DisplacementMask).
  				(self isPCMappedAnnotation: annotation) ifTrue:
  					[(annotation = IsSendCall
  					  and: [(mapByte := objectMemory byteAt: map - 1) >> AnnotationShift = IsAnnotationExtension]) ifTrue:
  						[annotation := annotation + (mapByte bitAnd: DisplacementMask).
  						 map := map - 1].
  					[byte := (objectMemory fetchByte: bcpc ofObject: aMethodObj) + bsOffset.
  					  descriptor := self generatorAt: byte.
  					  isInBlock
  						ifTrue: [bcpc >= endbcpc ifTrue: [^0]]
  						ifFalse:
  							[(descriptor isReturn and: [bcpc >= latestContinuation]) ifTrue: [^0].
  							 (descriptor isBranch or: [descriptor isBlockCreation]) ifTrue:
  								[| targetPC |
  								 targetPC := self latestContinuationPCFor: descriptor at: bcpc exts: nExts in: aMethodObj.
  								 latestContinuation := latestContinuation max: targetPC]].
  					  nextBcpc := self nextBytecodePCFor: descriptor at: bcpc exts: nExts in: aMethodObj.
  					  descriptor isMapped
  					  or: [isInBlock and: [descriptor isMappedInBlock]]] whileFalse:
  						[bcpc := nextBcpc.
  						 nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [0]].
  					result := self perform: functionSymbol
  									with: descriptor
  									with: annotation
  									with: (self cCoerceSimple: mcpc to: #'char *')
  									with: bcpc
  									with: arg.
  					 result ~= 0 ifTrue:
  						[^result].
  					 bcpc := nextBcpc.
  					 nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [0]]]
  			ifFalse:
  				[self assert: (mapByte >> AnnotationShift = IsDisplacementX2N
  							or: [mapByte >> AnnotationShift = IsAnnotationExtension]).
  				 mapByte < (IsAnnotationExtension << AnnotationShift) ifTrue:
+ 					[mcpc := mcpc + ((mapByte - DisplacementX2N << AnnotationShift) * backEnd codeGranularity)]].
- 					[mcpc := mcpc + (mapByte - DisplacementX2N << AnnotationShift)]].
  		 map := map - 1].
  	^0!

Item was changed:
  ----- Method: Spur32BitMMLECoSimulator>>longAt:put: (in category 'memory access') -----
  longAt: byteAddress put: a32BitValue
  	"Note: Adjusted for Smalltalk's 1-based array indexing."
  	"(byteAddress = 16r101348 and: [a32BitValue = 16r53]) ifTrue:
  		[self halt]."
+ 	"((byteAddress between: 16rda8ac and: 16rda8c0)
+ 	 or: [byteAddress between: 16r8eb98 and: 16r8ebb0]) ifTrue:
+ 		[self halt]."
  	byteAddress \\ 4 ~= 0 ifTrue: [self unalignedAccessError].
  	^memory at: byteAddress // 4 + 1 put: a32BitValue!

Item was changed:
  ----- Method: StackToRegisterMappingCogit>>genPrimitiveCharacterValue (in category 'primitive generators') -----
  genPrimitiveCharacterValue
  	| r |
  	(r := objectRepresentation genInnerPrimitiveCharacterValue: 0) < 0 ifTrue:
  		[^r].
+ 	^r = UnfailingPrimitive
+ 		ifTrue: [0]
+ 		ifFalse: [self compileFallbackToInterpreterPrimitive]!
- 	^self compileFallbackToInterpreterPrimitive!



More information about the Vm-dev mailing list