[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