JavaFinalizationRegistry refactored: jk_new_structure
authorvranyj1
Sat, 28 Jul 2012 01:26:25 +0000
branchjk_new_structure
changeset 1563 20048accea65
parent 1562 f63a0fd6a378
child 1564 48e14e6b3eab
JavaFinalizationRegistry refactored: - registry array access optimization - delayed finalization (hope it helps) - catches unfinished allObjectsDo: due to oldspace compress
src/JavaFinalizationRegistry.st
--- 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'!