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

commits at source.squeak.org commits at source.squeak.org
Sun Feb 23 22:11:46 UTC 2020


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

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

Name: VMMaker.oscog-eem.2718
Author: eem
Time: 23 February 2020, 2:11:24.545963 pm
UUID: 76bca24c-4a2d-453b-92ed-8357426d33b4
Ancestors: VMMaker.oscog-nice.2717

Cogit: don't bother to rewrite the selector in a lnked super send; this causes overwriting of the selector index in 64-bit implementations, and hence may cause an assert failure.  So it's a waste of effort and provokes an error.

Slang: type left shifts as either usqInt or sqInt, depending on type of receiver, not #int.  These are Smalltalk semantics we're trying to mimic, not C99 semantics we're constrained to follow.  better comment (and format; forgive me) generateShiftLeft:on:indent:.

=============== Diff against VMMaker.oscog-nice.2717 ===============

Item was changed:
  ----- Method: CCodeGenerator>>generateShiftLeft:on:indent: (in category 'C translation') -----
  generateShiftLeft: msgNode on: aStream indent: level
+ 	"Generate a C bitShift.  If the receiver type is unsigned avoid C99 undefined behaviour of
+ 	 left shifting negative values (what?!!?!!? such quiche eating idiocy to treat this like anything
+ 	 other than a truncated left shift) by casting signed receiver types to unsigned and back.
+ 	 If we can determine the result would overflow the word size, cast to a long integer."
- 	"Generate a C bitShift.  If we can determine the result
- 	 would overflow the word size, cast to a long integer."
  	| rcvr arg castToLong type mustCastBackToSign mustCastToUnsigned canSuffixTheConstant typeIsUnsigned |
  	rcvr := msgNode receiver.
  	arg := msgNode args first.
  	castToLong := false.
  	(rcvr constantNumbericValueIfAtAllPossibleOrNilIn: self) ifNotNil:
  		[:rcvrVal |
  		 (arg constantNumbericValueIfAtAllPossibleOrNilIn: self)
  			ifNil: [castToLong := vmClass notNil and: [vmClass objectMemoryClass wordSize = 8]]
  			ifNotNil:
  				[:argVal |
  				| valueBeyondInt |
  				valueBeyondInt := 1 bitShift: 32. "The default type of const << N is int."
  				castToLong := rcvrVal < valueBeyondInt
  								  and: [(rcvrVal bitShift: argVal) >= valueBeyondInt]]].
  	canSuffixTheConstant := rcvr isConstant and: [rcvr name isEmpty and: [rcvr value >= 0]].
+ 	canSuffixTheConstant ifTrue:
+ 		[aStream nextPutAll: (self cLiteralForUnsignedInteger: rcvr value longlong: castToLong).
+ 		aStream nextPutAll: ' << '.
+ 		self emitCExpression: arg on: aStream indent: level.
+ 		^self].
- 	canSuffixTheConstant
- 		ifTrue:
- 			[aStream nextPutAll: (self cLiteralForUnsignedInteger: rcvr value longlong: castToLong).
- 			aStream nextPutAll: ' << '.
- 			self emitCExpression: arg on: aStream indent: level.
- 			^self].
  	type := self typeFor: rcvr in: currentMethod.
  	castToLong := castToLong and: [(self sizeOfIntegralCType: type) < (self sizeOfIntegralCType: #usqLong)].
  	typeIsUnsigned := type first = $u.
  	mustCastToUnsigned := typeIsUnsigned not
+ 							or: [castToLong
+ 							or: [(self sizeOfIntegralCType: type) < (self sizeOfIntegralCType: #usqInt)]].
- 		or: [castToLong
- 		or: [(self sizeOfIntegralCType: type) < (self sizeOfIntegralCType: #usqInt)]].
  	mustCastBackToSign := typeIsUnsigned not.
+ 	mustCastBackToSign ifTrue:
+ 		[| promotedType |
+ 		promotedType := castToLong
+ 			ifTrue: [#sqLong]
+ 			ifFalse: [(self sizeOfIntegralCType: type) < (self sizeOfIntegralCType: #sqInt)
+ 				ifTrue: [#sqInt]
+ 				ifFalse: [type]].
+ 		aStream nextPutAll: '(('; nextPutAll: promotedType; nextPut: $)].
+ 	mustCastToUnsigned ifTrue:
+ 		[| unsigned |
+ 		unsigned := castToLong
+ 			ifTrue: [#usqLong]
+ 			ifFalse: [(self sizeOfIntegralCType: type) < (self sizeOfIntegralCType: #usqLong)
+ 				ifTrue: [#usqInt]
+ 				ifFalse: [self unsignedTypeForIntegralType: type]].
+ 		aStream nextPutAll: '(('; nextPutAll: unsigned; nextPutAll: ')('].
- 	mustCastBackToSign
- 		ifTrue:
- 			[| promotedType |
- 			promotedType := castToLong
- 				ifTrue: [#sqLong]
- 				ifFalse: [(self sizeOfIntegralCType: type) < (self sizeOfIntegralCType: #sqInt)
- 					ifTrue: [#sqInt]
- 					ifFalse: [type]].
- 			aStream nextPutAll: '(('; nextPutAll: promotedType; nextPut: $)].
- 	mustCastToUnsigned
- 		ifTrue:
- 			[| unsigned |
- 			unsigned := castToLong
- 				ifTrue: [#usqLong]
- 				ifFalse: [(self sizeOfIntegralCType: type) < (self sizeOfIntegralCType: #usqLong)
- 					ifTrue: [#usqInt]
- 					ifFalse: [self unsignedTypeForIntegralType: type]].
- 			aStream nextPutAll: '(('; nextPutAll: unsigned; nextPutAll: ')('].
  	self emitCExpression: rcvr on: aStream indent: level.
  	mustCastToUnsigned ifTrue: [aStream nextPut: $)].
+ 
+ 	aStream nextPutAll: ' << '.
+ 	self emitCExpression: arg on: aStream indent: level.
+ 
- 		aStream nextPutAll: ' << '.
- 		self emitCExpression: arg on: aStream indent: level.
  	mustCastToUnsigned ifTrue: [aStream nextPut: $)].
  	mustCastBackToSign ifTrue: [aStream nextPut: $)].!

Item was added:
+ ----- Method: CCodeGenerator>>isSignedIntegralCType: (in category 'inlining') -----
+ isSignedIntegralCType: aCType "<String>"
+ 	self assert: (self isIntegralCType: aCType).
+ 	^aCType first ~= $u!

Item was changed:
  ----- Method: CCodeGenerator>>returnTypeForSend:in:ifNil: (in category 'type inference') -----
  returnTypeForSend: sendNode in: aTMethod ifNil: typeIfNil
  	"Answer the return type for a send.  Unbound sends default to typeIfNil.
  	 Methods with types as yet unknown have a type determined either by the
  	 kernelReturnTypes or the table below, or, if they are in neither set, then nil.
  	 The inferred type should match as closely as possible the C type of
  	 generated expessions so that inlining would not change the expression.
  	 If there is a method for sel but its return type is as yet unknown it mustn't
  	 be defaulted, since on a subsequent pass its type may be computable."
  	| sel methodOrNil |
  	methodOrNil := self anyMethodNamed: (sel := sendNode selector).
  	(methodOrNil notNil and: [methodOrNil returnType notNil]) ifTrue:
  		[^self baseTypeForType: methodOrNil returnType].
  	^kernelReturnTypes
  		at: sel
  		ifAbsent:
  			[sel
  				caseOf: {
  				[#integerValueOf:]		->	[#sqInt].
  				[#isIntegerObject:]		->	[#int].
  				[#negated]				->	[self promoteArithmeticTypes: (sendNode receiver typeFrom: self in: aTMethod) and: #int].
  				[#+]					->	[self typeForArithmetic: sendNode in: aTMethod].
+ 				[#-]					->	[self typeForArithmetic: sendNode in: aTMethod].
- 				[#-]						->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#*]					->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#/]						->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#//]					->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#\\]					->	[self typeForArithmetic: sendNode in: aTMethod].
+ 				[#rem:]				->	[self typeForArithmetic: sendNode in: aTMethod].
- 				[#rem:]					->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#quo:]					->	[self typeForArithmetic: sendNode in: aTMethod].
+ 				"C99 Sec Bitwise shift operators ... 3 Semantics ...
- 				"C99 Sec Bitwise shift operators ... 3 Sematics ...
  				 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand..."
  				[#>>]					->	[sendNode receiver typeFrom: self in: aTMethod].
+ 				[#<<]					->	[(self isSignedIntegralCType: (sendNode receiver typeFrom: self in: aTMethod))
+ 												ifTrue: [#sqInt]
+ 												ifFalse: [#usqInt]].
- 				[#<<]					->	[sendNode receiver typeFrom: self in: aTMethod].
  				[#addressOf:]			->	[(sendNode args first typeFrom: self in: aTMethod)
  												ifNil: [#sqInt]
  												ifNotNil: [:type| type, (type last isSeparator ifTrue: ['*'] ifFalse: [' *'])]].
  				[#addressOf:put:]		->	[(sendNode args first typeFrom: self in: aTMethod)
  												ifNil: [#sqInt]
  												ifNotNil: [:type| type, (type last isSeparator ifTrue: ['*'] ifFalse: [' *'])]].
  				[#at:]					->	[self typeForDereference: sendNode in: aTMethod].
  				[#bitAnd:]				->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#bitOr:]				->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#bitXor:]				->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#bitClear:]				->	[self typeForArithmetic: sendNode in: aTMethod].
  				[#bitInvert32]			->	[#'unsigned int'].
  				[#bitInvert64]			->	[self promoteArithmeticTypes: (sendNode receiver typeFrom: self in: aTMethod) and: #int].
  				[#byteSwap32]			->	[#'unsigned int'].
  				[#byteSwap64]			->	[#'unsigned long long'].
  				[#byteSwapped32IfBigEndian:]	->	[#'unsigned int'].
  				[#byteSwapped64IfBigEndian:]	->	[#'unsigned long long'].
  				[#=]					->	[#int].
  				[#~=]					->	[#int].
  				[#==]					->	[#int].
  				[#~~]					->	[#int].
  				[#<]					->	[#int].
  				[#<=]					->	[#int].
  				[#>]					->	[#int].
  				[#>=]					->	[#int].
  				[#between:and:]		->	[#int].
  				[#anyMask:]				->	[#int].
  				[#allMask:]				->	[#int].
  				[#noMask:]				->	[#int].
  				[#isNil]					->	[#int].
  				[#notNil]				->	[#int].
  				[#&]					->	[#int].
  				[#|]						->	[#int].
  				[#not]					->	[#int].
  				[#asFloat]				->	[#double].
  				[#atan]					->	[#double].
  				[#exp]					->	[#double].
  				[#log]					->	[#double].
  				[#sin]					->	[#double].
  				[#sqrt]					->	[#double].
  				[#asLong]				->	[#long].
  				[#asInteger]			->	[#sqInt].
  				[#asIntegerPtr]			->	[#'sqIntptr_t'].
  				[#asUnsignedInteger]	->	[#usqInt].
  				[#asUnsignedIntegerPtr]->	[#'usqIntptr_t'].
  				[#asUnsignedLong]		->	[#'unsigned long'].
  				[#asUnsignedLongLong]		->	[#'unsigned long long'].
  				[#asVoidPointer]		->	[#'void *'].
  				[#signedIntToLong]		->	[#usqInt]. "c.f. generateSignedIntToLong:on:indent:"
  				[#signedIntToShort]	->	[#usqInt]. "c.f. generateSignedIntToShort:on:indent:"
  				[#cCoerce:to:]			->	[self conventionalTypeForType: sendNode args last value].
  				[#cCoerceSimple:to:]	->	[self conventionalTypeForType: sendNode args last value].
  				[#sizeof:]				->	[#'usqIntptr_t']. "Technically it's a size_t but it matches on target architectures so far..."
  				[#ifTrue:ifFalse:]		->	[self typeForConditional: sendNode in: aTMethod].
  				[#ifFalse:ifTrue:]		->	[self typeForConditional: sendNode in: aTMethod].
  				[#ifTrue:]				->	[self typeForConditional: sendNode in: aTMethod].
  				[#ifFalse:]				->	[self typeForConditional: sendNode in: aTMethod].
  				[#and:]					->	[#sqInt].
  				[#or:]					->	[#sqInt].
  				[#caseOf:]				->	[self typeFor: sendNode args first in: aTMethod] }
  				otherwise: "If there /is/ a method for sel but its return type is as yet unknown it /mustn't/ be defaulted,
  							since on a subsequent pass its type may be computable.  Only default unbound selectors."
  					[methodOrNil ifNotNil: [nil] ifNil: [typeIfNil]]]!

Item was changed:
  ----- Method: Cogit>>linkSendAt:in:to:offset:receiver: (in category 'in-line cacheing') -----
  linkSendAt: callSiteReturnAddress in: sendingMethod to: targetMethod offset: theEntryOffset receiver: receiver
  	<api>
  	<var: #sendingMethod type: #'CogMethod *'>
  	<var: #targetMethod type: #'CogMethod *'>
+ 	| inlineCacheTag extent |
- 	| inlineCacheTag address extent |
  	self assert: (theEntryOffset = cmEntryOffset or: [theEntryOffset = cmNoCheckEntryOffset]).
  	self assert: (callSiteReturnAddress between: methodZoneBase and: methodZone freeStart).
+ 	theEntryOffset = cmNoCheckEntryOffset
+ 		ifTrue: "no need to change selector cache tag"
+ 			[extent := backEnd rewriteCallAt: callSiteReturnAddress target: targetMethod asInteger + cmNoCheckEntryOffset]
+ 		ifFalse:
+ 			[inlineCacheTag := objectRepresentation inlineCacheTagForInstance: receiver.
+ 			 (self inlineCacheTagsAreIndexes not and: [objectRepresentation inlineCacheTagIsYoung: inlineCacheTag]) ifTrue:
+ 				[methodZone ensureInYoungReferrers: sendingMethod].
+ 			 extent := backEnd
+ 						rewriteInlineCacheAt: callSiteReturnAddress
+ 						tag: inlineCacheTag
+ 						target: targetMethod asInteger + theEntryOffset].
- 	inlineCacheTag := theEntryOffset = cmNoCheckEntryOffset
- 						ifTrue: [targetMethod selector "i.e. no change"]
- 						ifFalse: [objectRepresentation inlineCacheTagForInstance: receiver].
- 	(objectRepresentation inlineCacheTagIsYoung: inlineCacheTag) ifTrue:
- 		[methodZone ensureInYoungReferrers: sendingMethod].
- 	address := targetMethod asInteger + theEntryOffset.
- 	extent := backEnd
- 				rewriteInlineCacheAt: callSiteReturnAddress
- 				tag: inlineCacheTag
- 				target: address.
  	backEnd
  		flushICacheFrom: callSiteReturnAddress asUnsignedInteger  - extent
  		to: callSiteReturnAddress asUnsignedInteger !



More information about the Vm-dev mailing list