|
45 | 45 |
|
46 | 46 | import java.lang.ref.ReferenceQueue; |
47 | 47 | import java.lang.ref.WeakReference; |
| 48 | +import java.util.ArrayList; |
48 | 49 | import java.util.Arrays; |
49 | 50 | import java.util.HashMap; |
50 | 51 | import java.util.HashSet; |
@@ -166,7 +167,7 @@ public HandleContext(boolean useShadowTable) { |
166 | 167 | nativeStubLookupFreeStack.pushRange(1, DEFAULT_CAPACITY); |
167 | 168 | } |
168 | 169 |
|
169 | | - public final NativeObjectReferenceArrayWrapper referencesToBeFreed = new NativeObjectReferenceArrayWrapper(); |
| 170 | + public final ArrayList<Long> referencesToBeFreed = new ArrayList<>(); |
170 | 171 | public final HashMap<Long, IdReference<?>> nativeLookup = new HashMap<>(); |
171 | 172 | public final ConcurrentHashMap<Long, Long> nativeWeakRef = new ConcurrentHashMap<>(); |
172 | 173 | public final WeakHashMap<Object, WeakReference<Object>> managedNativeLookup = new WeakHashMap<>(); |
@@ -417,7 +418,7 @@ public static int pollReferenceQueue() { |
417 | 418 | ReferenceQueue<Object> queue = handleContext.referenceQueue; |
418 | 419 | int count = 0; |
419 | 420 | long start = 0; |
420 | | - NativeObjectReferenceArrayWrapper referencesToBeFreed = handleContext.referencesToBeFreed; |
| 421 | + ArrayList<Long> referencesToBeFreed = handleContext.referencesToBeFreed; |
421 | 422 | while (true) { |
422 | 423 | Object entry = queue.poll(); |
423 | 424 | if (entry == null) { |
@@ -509,7 +510,7 @@ public static int pollReferenceQueue() { |
509 | 510 | * to be freed. Therefore, this method neither frees any native memory nor runs any object |
510 | 511 | * destructor (guest code). |
511 | 512 | */ |
512 | | - private static void processNativeObjectReference(NativeObjectReference reference, NativeObjectReferenceArrayWrapper referencesToBeFreed) { |
| 513 | + private static void processNativeObjectReference(NativeObjectReference reference, ArrayList<Long> referencesToBeFreed) { |
513 | 514 | LOGGER.fine(() -> PythonUtils.formatJString("releasing %s", reference.toString())); |
514 | 515 | if (subNativeRefCount(reference.pointer, MANAGED_REFCNT) == 0) { |
515 | 516 | referencesToBeFreed.add(reference.pointer); |
@@ -548,26 +549,29 @@ private static void processPyCapsuleReference(PyCapsuleReference reference) { |
548 | 549 | * element. This method may therefore run arbitrary guest code and strictly requires the GIL to |
549 | 550 | * be held at the time of invocation. |
550 | 551 | */ |
551 | | - private static void releaseNativeObjects(PythonContext context, NativeObjectReferenceArrayWrapper referencesToBeFreed) { |
| 552 | + private static void releaseNativeObjects(PythonContext context, ArrayList<Long> referencesToBeFreed) { |
552 | 553 | if (!referencesToBeFreed.isEmpty()) { |
553 | 554 | /* |
554 | 555 | * This needs the GIL because this will call the native objects' destructors which can |
555 | 556 | * be arbitrary guest code. |
556 | 557 | */ |
557 | | - assert PythonContext.get(null).ownsGil(); |
| 558 | + assert context.ownsGil(); |
558 | 559 | PythonContext.PythonThreadState threadState = context.getThreadState(context.getLanguage()); |
559 | 560 | /* |
560 | 561 | * There can be an active exception. Since we might be calling arbitary python, we need |
561 | 562 | * to stash it. |
562 | 563 | */ |
563 | 564 | Object savedException = CExtCommonNodes.ReadAndClearNativeException.executeUncached(threadState); |
564 | 565 | try { |
565 | | - LOGGER.fine(() -> PythonUtils.formatJString("releasing %d NativeObjectReference instances", referencesToBeFreed.getArraySize())); |
566 | | - Object array = AllocateNode.allocUncached(referencesToBeFreed.getArraySize() * Long.BYTES); |
567 | | - CStructAccess.WriteLongNode.getUncached().writeLongArray(array, referencesToBeFreed.getArray(), (int) referencesToBeFreed.getArraySize(), 0, 0); |
568 | | - PCallCapiFunction.callUncached(NativeCAPISymbol.FUN_BULK_DEALLOC, array, referencesToBeFreed.getArraySize()); |
569 | | - FreeNode.executeUncached(array); |
570 | | - referencesToBeFreed.reset(); |
| 566 | + int size = referencesToBeFreed.size(); |
| 567 | + LOGGER.fine(() -> PythonUtils.formatJString("releasing %d NativeObjectReference instances", size)); |
| 568 | + long pointer = AllocateNode.allocUncachedPointer(size * Long.BYTES); |
| 569 | + for (int i = 0; i < size; i++) { |
| 570 | + CStructAccess.WriteLongNode.writeLong(pointer, i * Long.BYTES, referencesToBeFreed.get(i)); |
| 571 | + } |
| 572 | + PCallCapiFunction.callUncached(NativeCAPISymbol.FUN_BULK_DEALLOC, pointer, size); |
| 573 | + FreeNode.freeLong(pointer); |
| 574 | + referencesToBeFreed.clear(); |
571 | 575 | } finally { |
572 | 576 | CExtCommonNodes.ReadAndClearNativeException.executeUncached(threadState); |
573 | 577 | if (savedException != PNone.NO_VALUE) { |
|
0 commit comments