Skip to content

Commit 53d02ba

Browse files
committed
[GR-44606] Remove unused NativeObjectReference and related.
PullRequest: graalpython/2661
2 parents a779c9d + 1b82667 commit 53d02ba

File tree

2 files changed

+0
-392
lines changed

2 files changed

+0
-392
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiContext.java

Lines changed: 0 additions & 271 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,17 @@
4646
import static com.oracle.graal.python.nodes.StringLiterals.J_GET_;
4747
import static com.oracle.graal.python.nodes.StringLiterals.J_LLVM_LANGUAGE;
4848
import static com.oracle.graal.python.nodes.StringLiterals.J_TYPE_ID;
49-
import static com.oracle.graal.python.util.PythonUtils.EMPTY_TRUFFLESTRING_ARRAY;
5049
import static com.oracle.graal.python.util.PythonUtils.tsArray;
5150

5251
import java.io.IOException;
53-
import java.lang.ref.Reference;
54-
import java.lang.ref.ReferenceQueue;
55-
import java.lang.ref.WeakReference;
5652
import java.util.ArrayList;
5753
import java.util.Arrays;
5854
import java.util.HashMap;
5955
import java.util.HashSet;
60-
import java.util.List;
6156
import java.util.Map;
6257
import java.util.Objects;
6358
import java.util.concurrent.ConcurrentHashMap;
6459
import java.util.concurrent.atomic.AtomicLong;
65-
import java.util.logging.Level;
6660

6761
import org.graalvm.collections.EconomicMap;
6862
import org.graalvm.collections.Pair;
@@ -75,14 +69,11 @@
7569
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiCallPath;
7670
import com.oracle.graal.python.builtins.objects.PNone;
7771
import com.oracle.graal.python.builtins.objects.PNotImplemented;
78-
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
7972
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodes.PCallCapiFunction;
8073
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.CreateModuleNodeGen;
8174
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.ToJavaNodeGen;
8275
import com.oracle.graal.python.builtins.objects.cext.capi.CExtNodesFactory.ToNewRefNodeGen;
8376
import com.oracle.graal.python.builtins.objects.cext.capi.DynamicObjectNativeWrapper.PrimitiveNativeWrapper;
84-
import com.oracle.graal.python.builtins.objects.cext.capi.NativeObjectReferenceArrayWrapper.PointerArrayWrapper;
85-
import com.oracle.graal.python.builtins.objects.cext.capi.NativeObjectReferenceArrayWrapper.RefCountArrayWrapper;
8677
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions;
8778
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.HandleTester;
8879
import com.oracle.graal.python.builtins.objects.cext.capi.transitions.CApiTransitions.JavaStringToTruffleString;
@@ -91,25 +82,18 @@
9182
import com.oracle.graal.python.builtins.objects.cext.common.CExtContext;
9283
import com.oracle.graal.python.builtins.objects.cext.common.LoadCExtException.ApiInitException;
9384
import com.oracle.graal.python.builtins.objects.cext.common.LoadCExtException.ImportException;
94-
import com.oracle.graal.python.builtins.objects.cext.common.ReferenceStack;
9585
import com.oracle.graal.python.builtins.objects.cext.hpy.GraalHPyContext;
9686
import com.oracle.graal.python.builtins.objects.dict.PDict;
9787
import com.oracle.graal.python.builtins.objects.ellipsis.PEllipsis;
9888
import com.oracle.graal.python.builtins.objects.frame.PFrame;
99-
import com.oracle.graal.python.builtins.objects.function.PArguments;
100-
import com.oracle.graal.python.builtins.objects.function.Signature;
10189
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
10290
import com.oracle.graal.python.builtins.objects.module.PythonModule;
10391
import com.oracle.graal.python.builtins.objects.thread.PLock;
10492
import com.oracle.graal.python.nodes.ErrorMessages;
10593
import com.oracle.graal.python.nodes.IndirectCallNode;
10694
import com.oracle.graal.python.nodes.PRaiseNode;
107-
import com.oracle.graal.python.nodes.PRootNode;
10895
import com.oracle.graal.python.nodes.call.CallNode;
109-
import com.oracle.graal.python.nodes.call.GenericInvokeNode;
11096
import com.oracle.graal.python.nodes.object.InlinedGetClassNodeGen;
111-
import com.oracle.graal.python.runtime.AsyncHandler;
112-
import com.oracle.graal.python.runtime.ExecutionContext.CalleeContext;
11397
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
11498
import com.oracle.graal.python.runtime.PythonContext;
11599
import com.oracle.graal.python.runtime.PythonContext.GetThreadStateNode;
@@ -157,24 +141,18 @@ public final class CApiContext extends CExtContext {
157141
*/
158142
static final CApiContext LAZY_CONTEXT = new CApiContext();
159143

160-
public static final long REFERENCE_COUNT_BITS = Integer.SIZE;
161-
public static final long REFERENCE_COUNT_MARKER = (1L << REFERENCE_COUNT_BITS);
162144
/* a random number between 1 and 20 */
163145
private static final int MAX_COLLECTION_RETRIES = 17;
164146

165147
/** Total amount of allocated native memory (in bytes). */
166148
private long allocatedMemory = 0;
167149

168-
private final ReferenceQueue<Object> nativeObjectsQueue;
169150
private Map<Object, AllocInfo> allocatedNativeMemory;
170-
private final ReferenceStack<NativeObjectReference> nativeObjectWrapperList;
171151
private TraceMallocDomain[] traceMallocDomains;
172152

173153
/** Container of pointers that have seen to be free'd. */
174154
private Map<Object, AllocInfo> freedNativeMemory;
175155

176-
@CompilationFinal private RootCallTarget referenceCleanerCallTarget;
177-
178156
/**
179157
* This cache is used to cache native wrappers for frequently used primitives. This is strictly
180158
* defined to be the range {@code [-5, 256]}. CPython does exactly the same (see
@@ -226,20 +204,12 @@ public static TruffleLogger getLogger(Class<?> clazz) {
226204
*/
227205
private CApiContext() {
228206
super(null, null, null);
229-
nativeObjectsQueue = null;
230-
nativeObjectWrapperList = null;
231207
primitiveNativeWrapperCache = null;
232208
llvmTypeCache = null;
233209
}
234210

235211
public CApiContext(PythonContext context, Object hpyLibrary) {
236212
super(context, hpyLibrary, CAPIConversionNodeSupplier.INSTANCE);
237-
nativeObjectsQueue = new ReferenceQueue<>();
238-
nativeObjectWrapperList = new ReferenceStack<>();
239-
240-
// avoid 0 to be used as ID
241-
int nullID = nativeObjectWrapperList.reserve();
242-
assert nullID == 0;
243213

244214
// initialize primitive and pointer type cache
245215
llvmTypeCache = new Object[LLVMType.values().length];
@@ -251,34 +221,6 @@ public CApiContext(PythonContext context, Object hpyLibrary) {
251221
CApiTransitions.incRef(nativeWrapper, PythonNativeWrapper.IMMORTAL_REFCNT);
252222
primitiveNativeWrapperCache[i] = nativeWrapper;
253223
}
254-
255-
context.registerAsyncAction(() -> {
256-
Reference<?> reference = null;
257-
if (PythonOptions.AUTOMATIC_ASYNC_ACTIONS) {
258-
try {
259-
reference = nativeObjectsQueue.remove();
260-
} catch (InterruptedException e) {
261-
Thread.currentThread().interrupt();
262-
}
263-
} else {
264-
reference = nativeObjectsQueue.poll();
265-
}
266-
267-
ArrayList<NativeObjectReference> refs = new ArrayList<>();
268-
do {
269-
if (reference instanceof NativeObjectReference) {
270-
refs.add((NativeObjectReference) reference);
271-
}
272-
// consume all
273-
reference = nativeObjectsQueue.poll();
274-
} while (reference != null);
275-
276-
if (!refs.isEmpty()) {
277-
return new CApiReferenceCleanerAction(refs.toArray(new NativeObjectReference[0]));
278-
}
279-
280-
return null;
281-
});
282224
}
283225

284226
public int getPyLongBitsInDigit() {
@@ -325,14 +267,6 @@ public static Object asPointer(Object ptr, InteropLibrary lib) {
325267
return ptr;
326268
}
327269

328-
private RootCallTarget getReferenceCleanerCallTarget() {
329-
if (referenceCleanerCallTarget == null) {
330-
CompilerDirectives.transferToInterpreterAndInvalidate();
331-
referenceCleanerCallTarget = PythonLanguage.get(null).createCachedCallTarget(l -> new CApiReferenceCleanerRootNode(l), CApiReferenceCleanerRootNode.class);
332-
}
333-
return referenceCleanerCallTarget;
334-
}
335-
336270
public TraceMallocDomain getTraceMallocDomain(int domainIdx) {
337271
return traceMallocDomains[domainIdx];
338272
}
@@ -413,185 +347,6 @@ public Object getModuleByIndex(int i) {
413347
return null;
414348
}
415349

416-
static class NativeObjectReference extends WeakReference<PythonAbstractNativeObject> {
417-
418-
/**
419-
* The associated native pointer object that needs to be released if this reference dies.
420-
*/
421-
final Object ptrObject;
422-
423-
/** The ID of this reference, i.e., the index of the ref in the global reference list. */
424-
final int id;
425-
426-
/**
427-
* If {@code true}, the native object should not be released because a new managed ref was
428-
* created.
429-
*/
430-
boolean resurrect;
431-
432-
/**
433-
* When stealing references, this is the number of stolen reference counts (need to be
434-
* subtracted in the end).
435-
*/
436-
long managedRefCount;
437-
438-
public NativeObjectReference(PythonAbstractNativeObject referent, ReferenceQueue<? super PythonAbstractNativeObject> q, long managedRefCount, int id) {
439-
super(referent, q);
440-
this.ptrObject = referent.getPtr();
441-
this.managedRefCount = managedRefCount;
442-
this.id = id;
443-
}
444-
445-
public Object getPtrObject() {
446-
return ptrObject;
447-
}
448-
449-
public void markAsResurrected() {
450-
resurrect = true;
451-
}
452-
}
453-
454-
/**
455-
* Simple root node that executes a reference decrease.
456-
*/
457-
private static final class CApiReferenceCleanerRootNode extends PRootNode {
458-
private static final Signature SIGNATURE = new Signature(-1, false, -1, false, tsArray("ptr", "managedRefCount"), EMPTY_TRUFFLESTRING_ARRAY);
459-
private static final TruffleLogger LOGGER = CApiContext.getLogger(CApiReferenceCleanerRootNode.class);
460-
461-
@Child private CalleeContext calleeContext;
462-
@Child private InteropLibrary pointerObjectLib;
463-
@Child private PCallCapiFunction callBulkSubref;
464-
465-
protected CApiReferenceCleanerRootNode(PythonLanguage language) {
466-
super(language);
467-
this.calleeContext = CalleeContext.create();
468-
this.callBulkSubref = PCallCapiFunction.create();
469-
}
470-
471-
@Override
472-
public Object execute(VirtualFrame frame) {
473-
calleeContext.enter(frame);
474-
try {
475-
NativeObjectReference[] nativeObjectReferences = (NativeObjectReference[]) PArguments.getArgument(frame, 0);
476-
int cleaned = 0;
477-
CApiContext cApiContext = PythonContext.get(this).getCApiContext();
478-
long allocatedNativeMem = cApiContext.allocatedMemory;
479-
long startTime = 0;
480-
long middleTime = 0;
481-
final int n = nativeObjectReferences.length;
482-
boolean loggable = LOGGER.isLoggable(Level.FINE);
483-
484-
if (loggable) {
485-
startTime = System.currentTimeMillis();
486-
}
487-
488-
/*
489-
* Note about the order of operations - we need to call the finalizers first before
490-
* removing the objects from the wrapper list because the finalizers may still make
491-
* upcalls and those need the wrappers to work correctly.
492-
*/
493-
494-
callBulkSubref.call(NativeCAPISymbol.FUN_BULK_SUBREF, new PointerArrayWrapper(nativeObjectReferences), new RefCountArrayWrapper(nativeObjectReferences), (long) n);
495-
496-
if (loggable) {
497-
middleTime = System.currentTimeMillis();
498-
}
499-
500-
if (LOGGER.isLoggable(Level.FINER)) {
501-
// it's not an OSR loop, so we do this before the loop
502-
if (n > 0 && pointerObjectLib == null) {
503-
CompilerDirectives.transferToInterpreterAndInvalidate();
504-
pointerObjectLib = insert(InteropLibrary.getFactory().create(nativeObjectReferences[0].ptrObject));
505-
}
506-
507-
for (int i = 0; i < n; i++) {
508-
NativeObjectReference nativeObjectReference = nativeObjectReferences[i];
509-
Object pointerObject = nativeObjectReference.ptrObject;
510-
if (!nativeObjectReference.resurrect) {
511-
cApiContext.nativeObjectWrapperList.remove(nativeObjectReference.id);
512-
if (!nativeObjectReference.resurrect && !pointerObjectLib.isNull(pointerObject)) {
513-
cApiContext.checkAccess(pointerObject, pointerObjectLib);
514-
LOGGER.finer(() -> "Cleaning native object reference to " + CApiContext.asHex(pointerObject));
515-
cleaned++;
516-
}
517-
}
518-
}
519-
} else {
520-
for (int i = 0; i < n; i++) {
521-
NativeObjectReference nativeObjectReference = nativeObjectReferences[i];
522-
if (!nativeObjectReference.resurrect) {
523-
cApiContext.nativeObjectWrapperList.remove(nativeObjectReference.id);
524-
}
525-
}
526-
}
527-
528-
if (loggable) {
529-
final long countDuration = System.currentTimeMillis() - middleTime;
530-
final long duration = middleTime - startTime;
531-
final int finalCleaned = cleaned;
532-
final long freedNativeMemory = allocatedNativeMem - cApiContext.allocatedMemory;
533-
LOGGER.fine(() -> "Total queued references: " + n);
534-
LOGGER.fine(() -> "Cleaned references: " + finalCleaned);
535-
LOGGER.fine(() -> "Free'd native memory: " + freedNativeMemory);
536-
LOGGER.fine(() -> "Count duration: " + countDuration);
537-
LOGGER.fine(() -> "Duration: " + duration);
538-
}
539-
} finally {
540-
calleeContext.exit(frame, this);
541-
}
542-
return PNone.NONE;
543-
}
544-
545-
@Override
546-
public Signature getSignature() {
547-
return SIGNATURE;
548-
}
549-
550-
@Override
551-
public String getName() {
552-
return "native_reference_cleaner";
553-
}
554-
555-
@Override
556-
public boolean isInternal() {
557-
return false;
558-
}
559-
560-
@Override
561-
public boolean isPythonInternal() {
562-
return false;
563-
}
564-
}
565-
566-
/**
567-
* Reference cleaner action that will be executed by the {@link AsyncHandler}.
568-
*/
569-
private static final class CApiReferenceCleanerAction implements AsyncHandler.AsyncAction {
570-
571-
private final NativeObjectReference[] nativeObjectReferences;
572-
573-
public CApiReferenceCleanerAction(NativeObjectReference[] nativeObjectReferences) {
574-
this.nativeObjectReferences = nativeObjectReferences;
575-
}
576-
577-
@Override
578-
public void execute(PythonContext context) {
579-
Object[] pArguments = PArguments.create(1);
580-
PArguments.setArgument(pArguments, 0, nativeObjectReferences);
581-
GenericInvokeNode.getUncached().execute(context.getCApiContext().getReferenceCleanerCallTarget(), pArguments);
582-
}
583-
}
584-
585-
public NativeObjectReference lookupNativeObjectReference(int idx) {
586-
return nativeObjectWrapperList.get(idx);
587-
}
588-
589-
static long idToRefCnt(int id) {
590-
long nativeRefCnt = (long) id << REFERENCE_COUNT_BITS;
591-
assert nativeRefCnt >= REFERENCE_COUNT_MARKER;
592-
return nativeRefCnt;
593-
}
594-
595350
@TruffleBoundary
596351
public AllocInfo traceFree(Object ptr, @SuppressWarnings("unused") PFrame.Reference curFrame, @SuppressWarnings("unused") TruffleString clazzName) {
597352
if (allocatedNativeMemory == null) {
@@ -728,32 +483,6 @@ public void checkAccess(Object pointerObject, InteropLibrary lib) {
728483
}
729484
}
730485

731-
/**
732-
* Internal method for debugging purposes. This method looks up how many phantom references are
733-
* currently in the escaped references list. This is useful to check if the current reference
734-
* count of a native object is consistent with the upcoming decrements.
735-
*/
736-
@SuppressWarnings("unused")
737-
public List<Integer> containsAddress(long l) {
738-
CompilerAsserts.neverPartOfCompilation();
739-
int i = 0;
740-
List<Integer> indx = new ArrayList<>();
741-
InteropLibrary lib = InteropLibrary.getFactory().getUncached();
742-
for (NativeObjectReference nor : nativeObjectWrapperList) {
743-
Object obj = nor.ptrObject;
744-
745-
try {
746-
if (lib.isPointer(obj) && lib.asPointer(obj) == l) {
747-
indx.add(i);
748-
}
749-
} catch (UnsupportedMessageException e) {
750-
// ignore
751-
}
752-
i++;
753-
}
754-
return indx;
755-
}
756-
757486
public static final class AllocInfo {
758487
public final TruffleString typeName;
759488
public final PFrame.Reference allocationSite;

0 commit comments

Comments
 (0)