VM Maker: VMMaker.oscog-eem.2076.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

VM Maker: VMMaker.oscog-eem.2076.mcz

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

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

Name: VMMaker.oscog-eem.2076
Author: eem
Time: 6 January 2017, 4:58:37.437473 pm
UUID: 6da05305-9e5a-43eb-9eb1-3a893606256f
Ancestors: VMMaker.oscog-eem.2075

SpurPlanningCompactor:
Fix stupid slip in seeing if enough space to move an object below previous pin.

Never inline the three phases for ease of debugging (so objOop, prevOpb et al don't get renamed due to multiple copies of the object enumeration loop) as much as for performance measurment.

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

Item was changed:
  ----- Method: SpurPlanningCompactor>>copyAndUnmark: (in category 'compaction') -----
  copyAndUnmark: firstPass
  "Sweep the heap, unmarking all objects and moving mobile objects to their correct positions,
  restoring their savedFirstFields."
+ <inline: #never>
  | onePass |
  self logPhase: 'copying and unmarking...'.
  firstPass ifTrue:
  [self unmarkInitialImmobileObjects].
  "If savedFirstFieldsSpace is empty there is nothing to move, and no second pass."
  savedFirstFieldsSpace top < savedFirstFieldsSpace start ifTrue:
  [self assert: (self oop: firstMobileObject isGreaterThanOrEqualTo: manager endOfMemory).
  ^self].
  onePass := self copyAndUnmarkMobileObjects.
  (onePass not and: [biasForGC]) ifTrue: "only ever one pass if biasForGC is true."
  [self unmarkObjectsAfterLastMobileObject]!

Item was changed:
  ----- Method: SpurPlanningCompactor>>copyAndUnmarkMobileObjects (in category 'compaction') -----
  copyAndUnmarkMobileObjects
  "Sweep the mobile portion of the heap, moving objects to their eventual locations, and clearing their marked bits.
  Remember to update the savedFirstFields of pointer objects, as these have been forwarded.
  Answer if the end of the heap was reached (savedFirstFieldsSpace has not overflowed).
 
  This enumeration matches those in planCompactSavingForwarders and updatePointersInMobileObjects."
+ <inline: #never>
  | toFinger top previousPin |
  <var: 'top' type: #usqInt>
  <var: 'toFinger' type: #usqInt>
  self deny: (manager isMarked: firstFreeObject).
  toFinger := manager startOfObject: firstFreeObject.
  top := savedFirstFieldsSpace start.
  manager allOldSpaceEntitiesForCompactingFrom: firstFreeObject do:
  [:o :n|
  self check: o.
  self assert: (previousPin
  ifNil: [toFinger <= (manager startOfObject: o)]
  ifNotNil: [(manager isMarked: previousPin) and: [toFinger <= (manager startOfObject: previousPin)]]).
  self assert: (savedFirstFieldsSpaceWasAllocated
  or: [savedFirstFieldsSpace limit <= manager firstObject asUnsignedInteger
  or: [toFinger < top]]).
  (manager isMarked: o) ifTrue:
  [(manager isPinned: o)
  ifTrue:
  [(manager isSegmentBridge: o) ifFalse:
  [manager setIsMarkedOf: o to: false.
  manager segmentManager notePinned: o].
  previousPin ifNotNil:
  [| limit |
  limit := manager startOfObject: previousPin.
  manager addFreeChunkWithBytes: limit - toFinger at: toFinger.
  toFinger := manager addressAfter: previousPin.
  self assert: toFinger <= (manager startOfObject: o)].
  previousPin := o]
  ifFalse:
  [| availableSpace bytes next |
  [previousPin notNil
   and: [availableSpace := (manager startOfObject: previousPin) - toFinger.
  bytes := manager bytesInObject: o.
  bytes ~= availableSpace
+ and: [bytes + (2 * manager allocationUnit) > availableSpace]]] whileTrue:
- and: [bytes + (2 * manager allocationUnit) < availableSpace]]] whileTrue:
  ["The object does not fit in the space between toFinger and previousPin.
   Move toFinger beyond previousPin and update previousPin appropriately."
  availableSpace > 0 ifTrue:
  [manager addFreeChunkWithBytes: availableSpace at: toFinger].
  toFinger := manager addressAfter: previousPin.
  next := manager objectStartingAt: toFinger.
  previousPin := ((manager isMarked: next) and: [manager isPinned: next]) ifTrue: [next]].
  toFinger := self copyAndUnmarkObject: o to: toFinger firstField: (manager longAt: top).
  (top := top + manager bytesPerOop) >= savedFirstFieldsSpace limit ifTrue:
  [| done |
  self assert: savedFirstFieldsSpace top = (top - manager bytesPerOop).
  done := self noMobileObjectsAfter: n.
  done
  ifTrue: [self freeAllUnpinnedObjectsFromObject: (previousPin ifNil: [n]) toFinger: toFinger]
  ifFalse: [self freeFrom: toFinger upTo: (manager startOfObject: n) previousPin: previousPin].
  ^done]]]].
  self freeFrom: toFinger upTo: manager endOfMemory previousPin: previousPin.
  ^true!

Item was changed:
  ----- Method: SpurPlanningCompactor>>findHighestSuitableFreeBlock: (in category 'space management') -----
  findHighestSuitableFreeBlock: spaceEstimate
  "If a freeBlock of size at least spaceEstimate exists high enough in the heap, choose it.
  Ignoring pinned objects for now, the total ammount of shrinkage is expected to be
  at least totalFreeOldSpace (because of collected objects).  So any free chunk which is
  at or above endOfMemory - totalFreeOldSpace should not be corrupted during compaction.
  Let's play with this for a while and see how we get on."
  <inline: true>
  manager findLargestFreeChunk ifNotNil:
  [:largestFreeChunk|
  ((manager bytesInObject: largestFreeChunk) >= spaceEstimate
+ and: [largestFreeChunk asUnsignedInteger > (manager endOfMemory - manager freeSize) asUnsignedInteger]) ifTrue:
- and: [largestFreeChunk asUnsignedInteger > (manager endOfMemory - manager totalFreeOldSpace) asUnsignedInteger]) ifTrue:
  [^largestFreeChunk]].
  ^nil!

Item was changed:
  ----- Method: SpurPlanningCompactor>>planCompactSavingForwarders (in category 'compaction') -----
  planCompactSavingForwarders
  "Sweep the heap from firstFreeObject forwarding marked objects to where they
  can be moved to, saving their forwarding pointer in savedFirstFieldsSpace.
  Continue until either the end of the heap is reached or savedFirstFieldsSpace is full.
  Answer if the end of the heap was reached (savedFirstFieldsSpace has not overflowed).
 
  This enumeration matches those in updatePointersInMobileObjects and copyAndUnmarkMobileObjects."
+ <inline: #never>
-
  | toFinger top previousPin |
  <var: 'top' type: #usqInt>
  <var: 'toFinger' type: #usqInt>
  savedFirstFieldsSpace top < savedFirstFieldsSpace start ifTrue:
  [self logPhase: 'planning...'].
  self deny: (manager isMarked: firstFreeObject).
  toFinger := manager startOfObject: firstFreeObject.
  top := savedFirstFieldsSpace start.
  manager allOldSpaceEntitiesFrom: firstFreeObject do:
  [:o|
  self check: o.
  self assert: (previousPin
  ifNil: [toFinger <= (manager startOfObject: o)]
  ifNotNil: [(manager isMarked: previousPin) and: [toFinger <= (manager startOfObject: previousPin)]]).
  self assert: (savedFirstFieldsSpaceWasAllocated
  or: [savedFirstFieldsSpace limit <= manager firstObject asUnsignedInteger
  or: [toFinger < top]]).
  (manager isMarked: o) ifTrue:
  [(manager isPinned: o)
  ifTrue: "The empty gaps between two adjacent pinned objects (when not filled below) are freed."
  [previousPin ifNotNil:
  [self assert: (manager startOfObject: previousPin) - toFinger >= (manager allocationUnit * 2).
  toFinger := manager addressAfter: previousPin.
  self assert: toFinger <= (manager startOfObject: o)].
  previousPin := o]
  ifFalse:
  [| availableSpace bytes next |
  [previousPin notNil
   and: [availableSpace := (manager startOfObject: previousPin) - toFinger.
  bytes := manager bytesInObject: o.
  bytes ~= availableSpace
+ and: [bytes + (2 * manager allocationUnit) > availableSpace]]] whileTrue:
- and: [bytes + (2 * manager allocationUnit) < availableSpace]]] whileTrue:
  ["The object does not fit in the space between toFinger and previousPin.
   Move toFinger beyond previousPin and update previousPin appropriately."
  toFinger := manager addressAfter: previousPin.
  next := manager objectStartingAt: toFinger.
  previousPin := ((manager isMarked: next) and: [manager isPinned: next]) ifTrue: [next]].
  toFinger := self forwardMobileObject: o to: toFinger savedFirstFieldPtr: top.
  (top := top + manager bytesPerOop) >= savedFirstFieldsSpace limit ifTrue:
  [savedFirstFieldsSpace top: top - manager bytesPerOop.
  ^self noMobileObjectsAfter: o]]]].
  savedFirstFieldsSpace top: top - manager bytesPerOop.
  ^true!

Item was changed:
  ----- Method: SpurPlanningCompactor>>updatePointers (in category 'compaction') -----
  updatePointers
  "Sweep the heap, updating all objects to their eventual locations.
  Remember to update the savedFirstFields of pointer objects, as these have been forwarded."
+ <inline: #never>
  | onePass |
  self logPhase: 'updating pointers...'.
  "If savedFirstFieldsSpace is empty there is nothing to do."
  savedFirstFieldsSpace top < savedFirstFieldsSpace start ifTrue:
  [^self].
  self assert: (manager startOfObject: firstFreeObject) = mobileStart.
  coInterpreter mapInterpreterOops.
  manager mapExtraRoots.
  self updatePointersInManagerHeapEntities.
  self updatePointersInSurvivingObjects.
  self updatePointersInInitialImmobileObjects.
  onePass := self updatePointersInMobileObjects.
  onePass ifFalse:
  [self updatePointersInObjectsOverflowingSavedFirstFieldsSpace]!

Item was changed:
  ----- Method: SpurPlanningCompactor>>updatePointersInMobileObjects (in category 'compaction') -----
  updatePointersInMobileObjects
  "Sweep the mobile portion of the heap, updating all references to objects to their eventual locations.
  Remember to update the savedFirstFields of pointer objects, as these have been forwarded.
  Answer if the end of the heap was reached (savedFirstFieldsSpace has not overflowed).
 
  This enumeration matches that in planCompactSavingForwarders and copyAndUnmarkMobileObjects."
  | toFinger top previousPin |
  <var: 'top' type: #usqInt>
  <var: 'toFinger' type: #usqInt>
  self deny: (manager isMarked: firstFreeObject).
  toFinger := manager startOfObject: firstFreeObject.
  top := savedFirstFieldsSpace start.
  manager allOldSpaceEntitiesFrom: firstFreeObject do:
  [:o|
  self check: o.
  self assert: (previousPin
  ifNil: [toFinger <= (manager startOfObject: o)]
  ifNotNil: [(manager isMarked: previousPin) and: [toFinger <= (manager startOfObject: previousPin)]]).
  (manager isMarked: o) ifTrue:
  [(manager isPinned: o)
  ifTrue: "The empty gaps between two adjacent pinned objects (when not filled below) are freed."
  [self updatePointersIn: o.
  previousPin ifNotNil:
  [toFinger := manager addressAfter: previousPin].
  previousPin := o]
  ifFalse:
  [| availableSpace bytes next |
  [previousPin notNil
   and: [availableSpace := (manager startOfObject: previousPin) - toFinger.
  bytes := manager bytesInObject: o.
  bytes ~= availableSpace
+ and: [bytes + (2 * manager allocationUnit) > availableSpace]]] whileTrue:
- and: [bytes + (2 * manager allocationUnit) < availableSpace]]] whileTrue:
  ["The object does not fit in the space between toFinger and previousPin.
   Move toFinger beyond previousPin and update previousPin appropriately."
  toFinger := manager addressAfter: previousPin.
  next := manager objectStartingAt: toFinger.
  previousPin := ((manager isMarked: next) and: [manager isPinned: next]) ifTrue: [next]].
  self updatePointersIn: o savedFirstFieldPointer: top.
  toFinger := toFinger + (manager bytesInObject: o).
  (top := top + manager bytesPerOop) >= savedFirstFieldsSpace limit ifTrue:
  [self assert: savedFirstFieldsSpace top = (top - manager bytesPerOop).
  ^self noMobileObjectsAfter: o]]]].
  self assert: savedFirstFieldsSpace top = (top - manager bytesPerOop).
  ^true!