@@ -89,7 +89,7 @@ public void initialize(Python3Core core) {
89
89
@ GenerateNodeFactory
90
90
abstract static class GcCollectNode extends PythonBuiltinNode {
91
91
@ Specialization
92
- static int collect (VirtualFrame frame , PythonModule self , @ SuppressWarnings ("unused" ) Object level ,
92
+ static PNone collect (VirtualFrame frame , PythonModule self , @ SuppressWarnings ("unused" ) Object level ,
93
93
@ Bind ("this" ) Node inliningTarget ,
94
94
@ Cached PyObjectGetAttr getAttr ,
95
95
@ Cached PyObjectGetIter getIter ,
@@ -105,30 +105,35 @@ static int collect(VirtualFrame frame, PythonModule self, @SuppressWarnings("unu
105
105
if (cb != null ) {
106
106
phase = START ;
107
107
info = factory .createDict (new PKeyword []{
108
- new PKeyword (GENERATION , 2 ),
109
- new PKeyword (COLLECTED , 0 ),
110
- new PKeyword (UNCOLLECTABLE , 0 ),
108
+ new PKeyword (GENERATION , 2 ),
109
+ new PKeyword (COLLECTED , 0 ),
110
+ new PKeyword (UNCOLLECTABLE , 0 ),
111
111
});
112
112
do {
113
113
call .executeObject (frame , cb , phase , info );
114
114
} while ((cb = next .execute (frame , iter )) != null );
115
115
}
116
- try {
117
- return javaCollect (inliningTarget , gil );
118
- } finally {
119
- if (phase != null ) {
120
- phase = STOP ;
121
- iter = getIter .execute (frame , inliningTarget , callbacks );
122
- while ((cb = next .execute (frame , iter )) != null ) {
123
- call .executeObject (frame , cb , phase , info );
124
- }
116
+ long freedMemory = javaCollect (inliningTarget , gil );
117
+ if (phase != null ) {
118
+ phase = STOP ;
119
+ info = factory .createDict (new PKeyword []{
120
+ new PKeyword (GENERATION , 2 ),
121
+ new PKeyword (COLLECTED , freedMemory ),
122
+ new PKeyword (UNCOLLECTABLE , 0 ),
123
+ });
124
+ iter = getIter .execute (frame , inliningTarget , callbacks );
125
+ while ((cb = next .execute (frame , iter )) != null ) {
126
+ call .executeObject (frame , cb , phase , info );
125
127
}
126
128
}
129
+ return PNone .NONE ;
127
130
}
128
131
129
132
@ TruffleBoundary
130
- static int javaCollect (Node inliningTarget , GilNode gil ) {
133
+ static long javaCollect (Node inliningTarget , GilNode gil ) {
131
134
gil .release (true );
135
+ Runtime runtime = Runtime .getRuntime ();
136
+ long freeMemory = runtime .freeMemory ();
132
137
try {
133
138
PythonUtils .forceFullGC ();
134
139
try {
@@ -142,7 +147,12 @@ static int javaCollect(Node inliningTarget, GilNode gil) {
142
147
// collect some weak references now
143
148
PythonContext .triggerAsyncActions (inliningTarget );
144
149
CApiTransitions .pollReferenceQueue ();
145
- return 0 ;
150
+ /*
151
+ * CPython's GC returns the number of collected cycles. This is not something we can
152
+ * determine, but to return some useful info to the Python program, we return the amount
153
+ * of memory gained.
154
+ */
155
+ return Math .max (0 , runtime .freeMemory () - freeMemory );
146
156
}
147
157
}
148
158
0 commit comments