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

commits at source.squeak.org commits at source.squeak.org
Thu Jun 2 00:58:49 UTC 2016


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

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

Name: VMMaker.oscog-eem.1878
Author: eem
Time: 1 June 2016, 5:56:53.625028 pm
UUID: 71f5bdb3-74c3-4a8c-bbb9-c78c327e4823
Ancestors: VMMaker.oscog-eem.1877

Check for allocation failure in the LargeIntegersPlugin and fail primitives when space runs out.

This is clearly unsatisfactory;. the ciode fails to slow Smalltalk code.  We'd like to run the GC but Spur's style is not to GC in primitives.  If we change the plugin to do GC in primtiives we lose the speed advantage of the no-GC style of code.  One approach might be to estimate the memory needed as early as possible, and run a GC if not enough memory is available for the result, recomputing base pointers if GC is run.  This would avoid the awful remapOop:in: style whioch is pessimistic; it puts things in a stack and takes them back out whether a GC is needed or not.  We shoudl use an optimistic algorithm; especially for something as performance sensitive as large integer arithmetic.

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

Item was changed:
  ----- Method: LargeIntegersPlugin>>digit:Lshift: (in category 'oop functions') -----
  digit: anOop Lshift: shiftCount 
  	"Attention: this method invalidates all oop's!! Only newOop is valid at return."
  	"Does not normalize."
  	| newOop highBit newDigitLen newByteLen oldDigitLen |
  	oldDigitLen := self digitSizeOfLargeInt: anOop.
  	(highBit := self cDigitHighBit: (self pointerToFirstDigitOfLargeInt: anOop)
  				len: oldDigitLen) = 0 ifTrue: [^  interpreterProxy instantiateClass: (interpreterProxy fetchClassOf: anOop) indexableSize: 1].
  	newByteLen := highBit + shiftCount + 7 // 8.
+ 	self remapOop: anOop in:
+ 		[newOop := interpreterProxy
+ 						instantiateClass: (interpreterProxy fetchClassOf: anOop)
+ 						indexableSize: newByteLen].
+ 	newOop ifNil: [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
- 	self remapOop: anOop in: [newOop := interpreterProxy instantiateClass: (interpreterProxy fetchClassOf: anOop)
- 					indexableSize: newByteLen].
  	newDigitLen := newByteLen + 3 // 4.
  	self
  		cDigitLshift: shiftCount
  		from: (self pointerToFirstDigitOfLargeInt: anOop)
  		len: oldDigitLen
  		to: (self pointerToFirstDigitOfLargeInt: newOop)
  		len: newDigitLen.
  	^ newOop!

Item was changed:
  ----- Method: LargeIntegersPlugin>>digit:Rshift:lookfirst: (in category 'oop functions') -----
  digit: anOop Rshift: shiftCount lookfirst: a 
  	"Attention: this method invalidates all oop's!! Only newBytes is valid at return."
  	"Shift right 32*digitShift+bitShift bits, 0<=bitShift<32.         
  	Discard all digits beyond a, and all zeroes at or below a."
  	"Does not normalize."
  	| newByteLen newOop oldBitLen newBitLen oldDigitLen newDigitLen |
  	oldBitLen := self cDigitHighBit: (self pointerToFirstDigitOfLargeInt: anOop) len: a.
  	oldDigitLen := oldBitLen + 31 // 32.
  	newBitLen := oldBitLen - shiftCount.
  	newBitLen <= 0 ifTrue: ["All bits lost"
  		^ interpreterProxy
  			instantiateClass: (interpreterProxy fetchClassOf: anOop)
  			indexableSize: 0].
  	newByteLen := newBitLen + 7 // 8.
  	newDigitLen := newByteLen + 3 // 4.
+ 	self remapOop: anOop in:
+ 		[newOop := interpreterProxy
+ 						instantiateClass: (interpreterProxy fetchClassOf: anOop)
+ 						indexableSize: newByteLen].
+ 	newOop ifNil: [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
- 	self remapOop: anOop in: [newOop := interpreterProxy instantiateClass: (interpreterProxy fetchClassOf: anOop)
- 					indexableSize: newByteLen].
  	self
  		cDigitRshift: shiftCount
  		from: (self pointerToFirstDigitOfLargeInt: anOop)
  		len: oldDigitLen
  		to: (self pointerToFirstDigitOfLargeInt: newOop)
  		len: newDigitLen.
  	^ newOop!

Item was changed:
  ----- Method: LargeIntegersPlugin>>digitAddLarge:with: (in category 'oop functions') -----
  digitAddLarge: firstInteger with: secondInteger 
  	"Does not need to normalize!!"
  	| over firstDigitLen secondDigitLen shortInt shortDigitLen longInt longDigitLen sum newSum neg |
  	<var: #over type: #'unsigned int'>
  	firstDigitLen := self digitSizeOfLargeInt: firstInteger.
  	secondDigitLen := self digitSizeOfLargeInt: secondInteger.
  	neg := interpreterProxy isLargeNegativeIntegerObject: firstInteger.
  	firstDigitLen <= secondDigitLen
  		ifTrue: 
  			[shortInt := firstInteger.
  			shortDigitLen := firstDigitLen.
  			longInt := secondInteger.
  			longDigitLen := secondDigitLen]
  		ifFalse: 
  			[shortInt := secondInteger.
  			shortDigitLen := secondDigitLen.
  			longInt := firstInteger.
  			longDigitLen := firstDigitLen].
  	"	sum := Integer new: len neg: firstInteger negative."
  	self remapOop: #(shortInt longInt ) in: [sum := self createLargeIntegerNeg: neg digitLength: longDigitLen].
+ 	sum ifNil: [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
  	over := self
  				cDigitAdd: (self pointerToFirstDigitOfLargeInt: shortInt)
  				len: shortDigitLen
  				with: (self pointerToFirstDigitOfLargeInt: longInt)
  				len: longDigitLen
  				into: (self pointerToFirstDigitOfLargeInt: sum).
  	over > 0
  		ifTrue: 
  			["sum := sum growby: 1."
  			self remapOop: sum in: [newSum := self createLargeIntegerNeg: neg byteLength: longDigitLen * 4 + 1].
+ 			newSum ifNil: [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
  			self
  				cDigitCopyFrom: (self pointerToFirstDigitOfLargeInt: sum)
  				to: (self pointerToFirstDigitOfLargeInt: newSum)
  				len: longDigitLen.
  			sum := newSum.
  			"C index!!"
  			self cDigitOf: (self pointerToFirstDigitOfLargeInt: sum)
  				at: longDigitLen put: over]
  		ifFalse:
  			[sum := neg 
  				ifTrue: [self normalizeNegative: sum]
  				ifFalse: [self normalizePositive: sum]].
  	^ sum!

Item was changed:
  ----- Method: LargeIntegersPlugin>>digitBitLogic:with:opIndex: (in category 'oop functions') -----
  digitBitLogic: firstInteger with: secondInteger opIndex: opIx 
  	"Bit logic here is only implemented for positive integers or Zero;
  	if rec or arg is negative, it fails."
  	| firstLarge secondLarge firstLen secondLen shortLen shortLarge longLen longLarge result |
  	(interpreterProxy isIntegerObject: firstInteger)
  		ifTrue: 
+ 			[(interpreterProxy integerValueOf: firstInteger) < 0 ifTrue:
+ 				[^ interpreterProxy primitiveFail].
- 			[(interpreterProxy integerValueOf: firstInteger)
- 				< 0 ifTrue: [^ interpreterProxy primitiveFail].
  			"convert it to a not normalized LargeInteger"
  			self remapOop: secondInteger in: [firstLarge := self createLargeFromSmallInteger: firstInteger]]
  		ifFalse: 
  			[(interpreterProxy isLargePositiveIntegerObject: firstInteger) ifFalse: [^ interpreterProxy primitiveFail].
  			firstLarge := firstInteger].
  	(interpreterProxy isIntegerObject: secondInteger)
  		ifTrue: 
+ 			[(interpreterProxy integerValueOf: secondInteger) < 0 ifTrue:
+ 				[^ interpreterProxy primitiveFail].
- 			[(interpreterProxy integerValueOf: secondInteger)
- 				< 0 ifTrue: [^ interpreterProxy primitiveFail].
  			"convert it to a not normalized LargeInteger"
  			self remapOop: firstLarge in: [secondLarge := self createLargeFromSmallInteger: secondInteger]]
  		ifFalse: 
  			[(interpreterProxy isLargePositiveIntegerObject: secondInteger) ifFalse: [^ interpreterProxy primitiveFail].
  			secondLarge := secondInteger].
  	firstLen := self byteSizeOfLargeInt: firstLarge.
  	secondLen := self byteSizeOfLargeInt: secondLarge.
  	firstLen < secondLen
  		ifTrue: 
  			[shortLen := firstLen.
  			shortLarge := firstLarge.
  			longLen := secondLen.
  			longLarge := secondLarge]
  		ifFalse: 
  			[shortLen := secondLen.
  			shortLarge := secondLarge.
  			longLen := firstLen.
  			longLarge := firstLarge].
+ 	self remapOop: #(shortLarge longLarge) in:
+ 		[result := interpreterProxy instantiateClass: interpreterProxy classLargePositiveInteger indexableSize: longLen].
+ 	result ifNil: [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
- 	self remapOop: #(shortLarge longLarge ) in: [result := interpreterProxy instantiateClass: interpreterProxy classLargePositiveInteger indexableSize: longLen].
  	self
  		cDigitOp: opIx
  		short: (self pointerToFirstDigitOfLargeInt: shortLarge)
  		len: shortLen + 3 // 4
  		long: (self pointerToFirstDigitOfLargeInt: longLarge)
  		len: longLen + 3 // 4
  		into: (self pointerToFirstDigitOfLargeInt: result).
  	interpreterProxy failed ifTrue: [^ 0].
+ 	^self normalizePositive: result!
- 	^ self normalizePositive: result!

Item was changed:
  ----- Method: LargeIntegersPlugin>>digitMontgomery:times:modulo:mInvModB: (in category 'oop functions') -----
  digitMontgomery: firstLarge times: secondLarge modulo: thirdLarge mInvModB: mInv
  	<var: #mInv type: #'unsigned int'>
  	| firstLen secondLen thirdLen prod |
  	firstLen := self digitSizeOfLargeInt: firstLarge.
  	secondLen := self digitSizeOfLargeInt: secondLarge.
  	thirdLen := self digitSizeOfLargeInt: thirdLarge.
  	(firstLen <= thirdLen and: [secondLen <= thirdLen]) ifFalse: [^interpreterProxy primitiveFail].
  
  	self remapOop: #(firstLarge secondLarge thirdLarge)
  		in: [prod := interpreterProxy instantiateClass: interpreterProxy classLargePositiveInteger indexableSize: thirdLen * 4].
+ 	prod ifNil: [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
  	self
  		cDigitMontgomery: (self pointerToFirstDigitOfLargeInt: firstLarge)
  		len: firstLen
  		times: (self pointerToFirstDigitOfLargeInt: secondLarge)
  		len: secondLen
  		modulo: (self pointerToFirstDigitOfLargeInt: thirdLarge)
  		len: thirdLen
  		mInvModB: mInv
  		into: (self pointerToFirstDigitOfLargeInt: prod).
  	^self normalizePositive: prod!

Item was changed:
  ----- Method: LargeIntegersPlugin>>digitMultiplyLarge:with:negative: (in category 'oop functions') -----
  digitMultiplyLarge: firstInteger with: secondInteger negative: neg 
  	"Normalizes."
  	| firstLen secondLen shortInt shortLen longInt longLen prod |
  	firstLen := self byteSizeOfLargeInt: firstInteger.
  	secondLen := self byteSizeOfLargeInt: secondInteger.
  	firstLen <= secondLen
  		ifTrue: 
  			[shortInt := firstInteger.
  			shortLen := firstLen.
  			longInt := secondInteger.
  			longLen := secondLen]
  		ifFalse: 
  			[shortInt := secondInteger.
  			shortLen := secondLen.
  			longInt := firstInteger.
  			longLen := firstLen].
  	self remapOop: #(shortInt longInt) in: [prod := self createLargeIntegerNeg: neg byteLength: longLen + shortLen].
+ 	prod ifNil: [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
  	self
  		cDigitMultiply: (self pointerToFirstDigitOfLargeInt: shortInt)
  		len: shortLen + 3 // 4
  		with: (self pointerToFirstDigitOfLargeInt: longInt)
  		len: longLen + 3 // 4
  		into: (self pointerToFirstDigitOfLargeInt: prod)
  		len: longLen + shortLen + 3 // 4.
  	^neg 
  		ifTrue: [self normalizeNegative: prod]
  		ifFalse: [self normalizePositive: prod]!

Item was changed:
  ----- Method: LargeIntegersPlugin>>digitSubLarge:with: (in category 'oop functions') -----
  digitSubLarge: firstInteger with: secondInteger 
  	"Normalizes."
  	| firstDigitLen secondDigitLen larger largeDigitLen smaller smallerDigitLen neg resDigitLen res firstNeg |
  	firstNeg := interpreterProxy isLargeNegativeIntegerObject: firstInteger.
  	firstDigitLen := self digitSizeOfLargeInt: firstInteger.
  	secondDigitLen := self digitSizeOfLargeInt: secondInteger.
  	firstDigitLen = secondDigitLen ifTrue: 
  		[[firstDigitLen > 1
  		  and: [(self unsafeDigitOfLargeInt: firstInteger at: firstDigitLen) = (self unsafeDigitOfLargeInt: secondInteger at: firstDigitLen)]]
  			whileTrue: [firstDigitLen := firstDigitLen - 1].
  		secondDigitLen := firstDigitLen].
  	(firstDigitLen < secondDigitLen
  	 or: [firstDigitLen = secondDigitLen
  		 and: [(self unsafeDigitOfLargeInt: firstInteger at: firstDigitLen) < (self unsafeDigitOfLargeInt: secondInteger at: firstDigitLen)]])
  		ifTrue: 
  			[larger := secondInteger.
  			largeDigitLen := secondDigitLen.
  			smaller := firstInteger.
  			smallerDigitLen := firstDigitLen.
  			neg := firstNeg == false]
  		ifFalse: 
  			[larger := firstInteger.
  			largeDigitLen := firstDigitLen.
  			smaller := secondInteger.
  			smallerDigitLen := secondDigitLen.
  			neg := firstNeg].
  	resDigitLen := largeDigitLen.
  	self remapOop: #(smaller larger)
  		in: [res := self createLargeIntegerNeg: neg digitLength: resDigitLen].
+ 	res ifNil: [^interpreterProxy primitiveFailFor: PrimErrNoMemory].
  	self
  		cDigitSub: (self pointerToFirstDigitOfLargeInt: smaller)
  		len: smallerDigitLen
  		with: (self pointerToFirstDigitOfLargeInt: larger)
  		len: largeDigitLen
  		into: (self pointerToFirstDigitOfLargeInt: res).
  	^neg 
  		ifTrue: [self normalizeNegative: res]
  		ifFalse: [self normalizePositive: res]!



More information about the Vm-dev mailing list