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

Ben Coman btc at openinworld.com
Thu Jun 2 05:35:15 UTC 2016


On Thu, Jun 2, 2016 at 8:57 AM,  <commits at source.squeak.org> wrote:
>
> 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.

Hi Eliot,

Does "not to GC *in* primitives" mean from the Image's or VM's perspective?

Naively I wonder if your approach to primitives failing due to forwarders
would apply here.  If the primitive runs out of space, set a flag
before failing,
and at the same point you test and resolve forwarders, then retry the primitive,
you could check for this flag, run a GC (outside of the primitive from
the VM's perspective?),
then retry the primitive ??

cheers -ben

> If we change the plugin to do GC in primitives 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