JavaFinalizationRegistry refactored:
- registry array access optimization
- delayed finalization (hope it helps)
- catches unfinished allObjectsDo: due to oldspace compress
--- a/src/JavaFinalizationRegistry.st Fri Jul 27 19:15:40 2012 +0000
+++ b/src/JavaFinalizationRegistry.st Sat Jul 28 01:26:25 2012 +0000
@@ -21,7 +21,8 @@
"{ Package: 'stx:libjava' }"
Object subclass:#JavaFinalizationRegistry
- instanceVariableNames:'accessLock activeReferees finalizationSemaphore finalizationProcess'
+ instanceVariableNames:'accessLock referees refereesTally new newTally
+ finalizationSemaphore finalizationProcess'
classVariableNames:''
poolDictionaries:''
category:'Languages-Java-Support'
@@ -83,19 +84,15 @@
finalizationCycle
- | referees references living wasBlocked firstPendingReference lastPendingReference ref |
-
- accessLock critical:[
+ | references living firstPendingReference lastPendingReference ref finished|
- referees := (activeReferees select:[:e|e notNil]) asArray.
- references := Array new: referees size.
- living := Array new: referees size.
+ references := Array new: refereesTally.
+ living := Array new: refereesTally.
firstPendingReference := nil.
-
- ObjectMemory allObjectsIncludingContextsDo:[:o|
+ finished := self allObjectsIncludingContextsDo:[:o|
| index |
- (o ~~ referees and:[o ~~ activeReferees]) ifTrue:[
- (index := self references: o anyOf: referees) ~~ 0 ifTrue:[
+ (o ~~ referees) ifTrue:[
+ (index := self references: o anyOf: referees tally: refereesTally) ~~ 0 ifTrue:[
o class name == #'java/lang/ref/Finalizer' ifTrue:[
self assert: (self getNextOf: o) isNil.
references at: index put: o
@@ -105,21 +102,33 @@
].
].
].
-
+ finished ifFalse:[ ^ self ].
living withIndexDo:[:each :index|
each isNil ifTrue:[
ref := references at: index.
- activeReferees at: (activeReferees identityIndexOf: (referees at: index)) put: nil.
- firstPendingReference isNil ifTrue:[
- firstPendingReference := lastPendingReference := ref
+ self unregisterAt: index.
+ ref notNil ifTrue:[
+ firstPendingReference isNil ifTrue:[
+ firstPendingReference := lastPendingReference := ref
+ ] ifFalse:[
+ self setNextOf: lastPendingReference to: ref.
+ lastPendingReference := ref.
+ ].
+ self setNextOf: lastPendingReference to: lastPendingReference
] ifFalse:[
- self setNextOf: lastPendingReference to: ref.
- lastPendingReference := ref.
- ].
- self setNextOf: lastPendingReference to: lastPendingReference
+ Logger log: 'background finalizer: referee registered but reference gone' severity: #error facility: #JVM
+ ]
].
].
-
+ accessLock critical:[
+ "Copy new to referees, this somewhat delays finalization"
+ refereesTally + newTally > referees size ifTrue:[
+ referees := self grow: referees min: refereesTally + newTally.
+ ].
+ referees replaceFrom: refereesTally + 1 to: refereesTally + newTally with: new startingAt: 1.
+ new from: 1 to: newTally put: nil.
+ refereesTally := refereesTally + newTally.
+ newTally := 0.
].
self informReferenceHandler: firstPendingReference
@@ -143,30 +152,34 @@
"Invoked when a new instance is created."
"/ please change as required (and remove this comment)
- activeReferees := Array new: 200.
+
+ referees := Array new: 200.
+ refereesTally := 0.
+ new := Array new: 200.
+ newTally := 0.
accessLock := RecursionLock new.
"/ super initialize. -- commented since inherited method does nothing
- "Modified: / 24-07-2012 / 15:23:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 28-07-2012 / 01:32:34 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaFinalizationRegistry methodsFor:'private'!
-firstFreeIndex
- activeReferees withIndexDo:[:value :index|
- value isNil ifTrue:[
- ^index
+allObjectsIncludingContextsDo:aBlock
+
+ (ObjectMemory allObjectsDo:aBlock) ifFalse:[ ^ false ].
+ ProcessorScheduler knownProcesses do:[:p |
+ |con|
+
+ con := p suspendedContext.
+ [con notNil] whileTrue:[
+ aBlock value:con.
+ con := con sender.
].
].
- self grow.
- activeReferees withIndexDo:[:value :index|
- value isNil ifTrue:[
- ^index
- ].
- ].
- JavaVM internalError: 'No free finalization slot even after grow'.
+ ^ true
- "Created: / 24-07-2012 / 01:19:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Created: / 28-07-2012 / 02:14:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
getNextOf: reference
@@ -176,15 +189,20 @@
"Created: / 24-07-2012 / 11:22:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-grow
+grow: array
+ ^self grow: array min: 30
- | newActiveReferees |
+ "Created: / 28-07-2012 / 01:14:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
- newActiveReferees := Array new: activeReferees size * 2.
- newActiveReferees replaceFrom: 1 with: activeReferees.
- activeReferees := newActiveReferees
+grow: array min: min
+ | grown |
- "Created: / 24-07-2012 / 01:20:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ grown := Array new: ((array size * 2) max: min).
+ grown replaceFrom: 1 with: array.
+ ^grown
+
+ "Created: / 28-07-2012 / 01:27:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
informReferenceHandler: reference
@@ -207,7 +225,7 @@
"Created: / 24-07-2012 / 03:42:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
-references: object anyOf: aCollection
+references: object anyOf: aCollection tally: tally
"If object references any object in a collection, return
index of value which it references, zero otherwise"
@@ -219,8 +237,10 @@
}
if (__isArrayLike(aCollection)) {
- int nObjs = __arraySize(aCollection);
- char *minAddr = 0, *maxAddr = 0;
+ int sz = __arraySize(aCollection);
+ int tl = __intVal(tally);
+ int nObjs = sz < tl ? sz : tl;
+ char *minAddr = 0, *maxAddr = 0;
if (nObjs == 0) {
RETURN (__MKINT(0));
@@ -308,7 +328,7 @@
}
}
#endif
- RETURN (false);
+ RETURN ( __MKINT( 0 ) );
}
for (inst=0; inst<nInsts; inst++) {
@@ -330,12 +350,13 @@
}
%}.
- aCollection withIndexDo:[:each :eachi|
+ 1 to: (aCollection size min: tally) do:[:eachi| | each |
+ each := aCollection at: eachi.
(object references: each) ifTrue:[^eachi].
].
^0
- "Created: / 24-07-2012 / 01:49:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Created: / 28-07-2012 / 01:18:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
setNextOf: reference to: value
@@ -353,17 +374,17 @@
| index finalizedClass |
accessLock critical:[
-
- index := self firstFreeIndex.
- activeReferees at: index put: object.
- finalizedClass := Java classForName:'java.lang.ref.Finalizer'.
- finalizedClass classInit.
- (finalizedClass methodDictionary at: #'register(Ljava/lang/Object;)V')
- valueWithReceiver: finalizedClass arguments: (Array with: object).
+ newTally = new size ifTrue:[
+ new := self grow: new
+ ].
+ index := newTally := newTally + 1.
+ new at: index put: object.
+ finalizedClass := Java classForName:'java.lang.ref.Finalizer'.
+ finalizedClass classInit.
+ (finalizedClass methodDictionary at: #'register(Ljava/lang/Object;)V')
+ valueWithReceiver: finalizedClass arguments: (Array with: object).
].
-
-
"Created: / 24-07-2012 / 01:14:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
@@ -371,6 +392,18 @@
"/Nothing to do, to be polymprph with Registry"
"Created: / 24-07-2012 / 03:31:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+unregisterAt: index
+ "Unregister an object at index from being finalized"
+
+ refereesTally < index ifTrue:[
+ referees at: index put: (referees at: refereesTally).
+ ].
+ referees at: refereesTally put: nil.
+ refereesTally := refereesTally - 1.
+
+ "Created: / 28-07-2012 / 01:24:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaFinalizationRegistry methodsFor:'start & stop'!