Skip to content

Commit d094971

Browse files
committed
[GR-38705] Fix memory leak caused by MethDirectRoot.
PullRequest: graalpython/2259
2 parents 6566000 + 58bc1e8 commit d094971

File tree

18 files changed

+488
-296
lines changed

18 files changed

+488
-296
lines changed

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 79 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -122,19 +122,19 @@ void initialize_type_structure(PyTypeObject* structure, PyTypeObject* ptype, pol
122122
type_handle->tp_basicsize = basicsize;
123123
type_handle->tp_itemsize = itemsize;
124124
if (alloc_fun) {
125-
type_handle->tp_alloc = alloc_fun;
125+
type_handle->tp_alloc = alloc_fun;
126126
}
127127
if (dealloc_fun) {
128-
type_handle->tp_dealloc = dealloc_fun;
128+
type_handle->tp_dealloc = dealloc_fun;
129129
}
130130
if (free_fun) {
131-
type_handle->tp_free = free_fun;
131+
type_handle->tp_free = free_fun;
132132
}
133133
if (free_fun) {
134-
type_handle->tp_free = free_fun;
134+
type_handle->tp_free = free_fun;
135135
}
136136
if (vectorcall_offset) {
137-
type_handle->tp_vectorcall_offset = vectorcall_offset;
137+
type_handle->tp_vectorcall_offset = vectorcall_offset;
138138
}
139139
if (as_buffer) {
140140
type_handle->tp_as_buffer = as_buffer;
@@ -151,12 +151,12 @@ static void initialize_builtin_type(PyTypeObject* structure, const char* typname
151151
#define init_hidden(a, b) initialize ## a ## _ ## b ## _gen
152152
#define init(a, b) init_hidden(a, b)
153153

154-
#define initialize_type(typeobject, typename, struct) \
155-
ctor(__COUNTER__) \
156-
static void init(__COUNTER__, typeobject)(void) { \
157-
initialize_builtin_type(&typeobject, \
158-
#typename, \
159-
polyglot_ ## struct ## _typeid()); \
154+
#define initialize_type(typeobject, typename, struct) \
155+
ctor(__COUNTER__) \
156+
static void init(__COUNTER__, typeobject)(void) { \
157+
initialize_builtin_type(&typeobject, \
158+
#typename, \
159+
polyglot_ ## struct ## _typeid()); \
160160
}
161161

162162
#define declare_struct(typeobject, typename, struct) \
@@ -224,7 +224,7 @@ POLYGLOT_DECLARE_TYPE(Py_buffer);
224224
#define REGISTER_BASIC_TYPE(typename) \
225225
POLYGLOT_DECLARE_TYPE(typename); \
226226
NO_INLINE polyglot_typeid get_ ## typename ## _typeid(void) { \
227-
return polyglot_ ## typename ## _typeid(); \
227+
return polyglot_ ## typename ## _typeid(); \
228228
}
229229

230230
/* just a renaming to avoid name clash with Java types */
@@ -269,8 +269,8 @@ REGISTER_BASIC_TYPE(PyThreadState);
269269
#define REGISTER_POINTER_TYPE(basetype, ptrtype) \
270270
typedef basetype* ptrtype; \
271271
POLYGLOT_DECLARE_TYPE(ptrtype); \
272-
NO_INLINE polyglot_typeid get_ ## ptrtype ## _typeid(void) { \
273-
return polyglot_array_typeid(polyglot_ ## basetype ## _typeid(), 1); \
272+
NO_INLINE polyglot_typeid get_ ## ptrtype ## _typeid(void) { \
273+
return polyglot_array_typeid(polyglot_ ## basetype ## _typeid(), 1); \
274274
}
275275

276276
REGISTER_POINTER_TYPE(int64_t, int64_ptr_t);
@@ -396,77 +396,77 @@ Py_ssize_t get_ob_refcnt(PyObject* obj) {
396396

397397
/** to be used from Java code only; reads native 'tp_dict' field */
398398
PyObject* get_tp_dict(PyTypeObject* obj) {
399-
return native_to_java(obj->tp_dict);
399+
return native_to_java(obj->tp_dict);
400400
}
401401

402402
/** to be used from Java code only; reads native 'tp_base' field */
403403
PyObject* get_tp_base(PyTypeObject* obj) {
404-
return native_to_java((PyObject*) obj->tp_base);
404+
return native_to_java((PyObject*) obj->tp_base);
405405
}
406406

407407
/** to be used from Java code only; reads native 'tp_bases' field */
408408
PyObject* get_tp_bases(PyTypeObject* obj) {
409-
return native_to_java(obj->tp_bases);
409+
return native_to_java(obj->tp_bases);
410410
}
411411

412412
/** to be used from Java code only; reads native 'tp_name' field */
413413
const char* get_tp_name(PyTypeObject* obj) {
414-
return obj->tp_name;
414+
return obj->tp_name;
415415
}
416416

417417
/** to be used from Java code only; reads native 'tp_mro' field */
418418
PyObject* get_tp_mro(PyTypeObject* obj) {
419-
return native_to_java(obj->tp_mro);
419+
return native_to_java(obj->tp_mro);
420420
}
421421

422422
/** to be used from Java code only; reads native 'tp_subclasses' field */
423423
PyObject* get_tp_subclasses(PyTypeObject* obj) {
424-
return native_to_java(obj->tp_subclasses);
424+
return native_to_java(obj->tp_subclasses);
425425
}
426426

427427
/** to be used from Java code only; reads native 'tp_dictoffset' field */
428428
Py_ssize_t get_tp_dictoffset(PyTypeObject* obj) {
429-
return obj->tp_dictoffset;
429+
return obj->tp_dictoffset;
430430
}
431431

432432
/** to be used from Java code only; reads native 'tp_weaklistoffset' field */
433433
Py_ssize_t get_tp_weaklistoffset(PyTypeObject* obj) {
434-
return obj->tp_weaklistoffset;
434+
return obj->tp_weaklistoffset;
435435
}
436436

437437
/** to be used from Java code only; reads native 'tp_itemsize' field */
438438
Py_ssize_t get_tp_itemsize(PyTypeObject* obj) {
439-
return obj->tp_itemsize;
439+
return obj->tp_itemsize;
440440
}
441441

442442
/** to be used from Java code only; reads native 'tp_basicsize' field */
443443
Py_ssize_t get_tp_basicsize(PyTypeObject* obj) {
444-
return obj->tp_basicsize;
444+
return obj->tp_basicsize;
445445
}
446446

447447
/** to be used from Java code only; reads native 'tp_alloc' field */
448448
allocfunc get_tp_alloc(PyTypeObject* obj) {
449-
return obj->tp_alloc;
449+
return obj->tp_alloc;
450450
}
451451

452452
/** to be used from Java code only; reads native 'tp_dealloc' field */
453453
destructor get_tp_dealloc(PyTypeObject* obj) {
454-
return obj->tp_dealloc;
454+
return obj->tp_dealloc;
455455
}
456456

457457
/** to be used from Java code only; reads native 'tp_free' field */
458458
freefunc get_tp_free(PyTypeObject* obj) {
459-
return obj->tp_free;
459+
return obj->tp_free;
460460
}
461461

462462
/** to be used from Java code only; reads native 'tp_as_buffer' field */
463463
PyBufferProcs* get_tp_as_buffer(PyTypeObject* obj) {
464-
return obj->tp_as_buffer;
464+
return obj->tp_as_buffer;
465465
}
466466

467467
/** to be used from Java code only; reads native 'tp_flags' field */
468468
unsigned long get_tp_flags(PyTypeObject* obj) {
469-
return obj->tp_flags;
469+
return obj->tp_flags;
470470
}
471471

472472
POLYGLOT_DECLARE_TYPE(PyMethodDef);
@@ -530,17 +530,17 @@ polyglot_typeid get_newfunc_typeid() {
530530

531531
/** to be used from Java code only; calls INCREF */
532532
void PyTruffle_INCREF(PyObject* obj) {
533-
Py_INCREF(obj);
533+
Py_INCREF(obj);
534534
}
535535

536536
/** to be used from Java code only; calls DECREF */
537537
void PyTruffle_DECREF(PyObject* obj) {
538-
Py_DECREF(obj);
538+
Py_DECREF(obj);
539539
}
540540

541541
/** to be used from Java code only; calls DECREF */
542542
Py_ssize_t PyTruffle_ADDREF(PyObject* obj, Py_ssize_t value) {
543-
return (obj->ob_refcnt += value);
543+
return (obj->ob_refcnt += value);
544544
}
545545

546546
/** to be used from Java code only; calls DECREF */
@@ -558,27 +558,27 @@ Py_ssize_t PyTruffle_SUBREF(PyObject* obj, Py_ssize_t value) {
558558
}
559559

560560
/** to be used from Java code only; calls DECREF */
561-
Py_ssize_t PyTruffle_bulk_SUBREF(PyObject* ptrArray[], Py_ssize_t values[], int64_t len) {
562-
int64_t i;
563-
PyObject* obj;
564-
Py_ssize_t value;
565-
566-
for (i=0; i < len; i++) {
567-
obj = ptrArray[i];
568-
value = values[i];
569-
/* IMPORTANT: 'value == 0' indicates we should not process the reference at all */
570-
if (value > 0) {
571-
Py_ssize_t new_value = ((obj->ob_refcnt) -= value);
572-
if (new_value == 0) {
573-
_Py_Dealloc(obj);
574-
}
561+
Py_ssize_t PyTruffle_bulk_SUBREF(PyObject *ptrArray[], Py_ssize_t values[], int64_t len) {
562+
int64_t i;
563+
PyObject *obj;
564+
Py_ssize_t value;
565+
566+
for (i = 0; i < len; i++) {
567+
obj = ptrArray[i];
568+
value = values[i];
569+
/* IMPORTANT: 'value == 0' indicates we should not process the reference at all */
570+
if (value > 0) {
571+
Py_ssize_t new_value = ((obj->ob_refcnt) -= value);
572+
if (new_value == 0) {
573+
_Py_Dealloc(obj);
574+
}
575575
#ifdef Py_REF_DEBUG
576-
else if (new_value < 0) {
577-
_Py_NegativeRefcount(filename, lineno, op);
578-
}
576+
else if (new_value < 0) {
577+
_Py_NegativeRefcount(filename, lineno, op);
578+
}
579579
#endif
580-
}
581-
}
580+
}
581+
}
582582
return 0;
583583
}
584584

@@ -591,12 +591,12 @@ uint64_t PyTruffle_Wchar_Size() {
591591
}
592592

593593
/** free's a native pointer or releases a Sulong handle; DO NOT CALL WITH MANAGED POINTERS ! */
594-
void PyTruffle_Free(void* obj) {
595-
if(points_to_handle_space(obj) && is_handle(obj)) {
596-
release_handle(obj);
597-
} else {
598-
PyMem_RawFree(obj);
599-
}
594+
void PyTruffle_Free(void *obj) {
595+
if (points_to_handle_space(obj) && is_handle(obj)) {
596+
release_handle(obj);
597+
} else {
598+
PyMem_RawFree(obj);
599+
}
600600
}
601601

602602
/** to be used from Java code only; creates the deref handle for a sequence wrapper */
@@ -706,10 +706,10 @@ void* ReadStringInPlaceMember(PyObject* object, Py_ssize_t offset) {
706706
PyObject* ReadObjectMember(PyObject* object, Py_ssize_t offset) {
707707
PyObject* member = ReadMember(object, offset, PyObject*);
708708
if (member == NULL) {
709-
return Py_None;
710-
} else {
711-
return native_to_java(member);
709+
member = Py_None;
712710
}
711+
Py_INCREF(member);
712+
return native_to_java(member);
713713
}
714714

715715
int ReadCharMember(PyObject* object, Py_ssize_t offset) {
@@ -738,6 +738,7 @@ PyObject* ReadObjectExMember(PyObject* object, Py_ssize_t offset) {
738738
PyErr_SetString(PyExc_ValueError, "member must not be NULL");
739739
return NULL;
740740
} else {
741+
Py_INCREF(member);
741742
return native_to_java(member);
742743
}
743744
}
@@ -788,21 +789,23 @@ int WriteStringMember(PyObject* object, Py_ssize_t offset, char* value) {
788789
}
789790

790791
int WriteStringInPlaceMember(PyObject* object, Py_ssize_t offset, char* value) {
791-
char *addr = (char*) (((char*)object) + offset);
792-
size_t n;
793-
if (polyglot_has_array_elements(value)) {
794-
n = polyglot_get_array_size(value);
795-
} else {
796-
n = strlen(value);
797-
}
798-
memcpy(addr, value, n);
799-
return 0;
792+
char *addr = (char*) (((char*) object) + offset);
793+
size_t n;
794+
if (polyglot_has_array_elements(value)) {
795+
n = polyglot_get_array_size(value);
796+
} else {
797+
n = strlen(value);
798+
}
799+
memcpy(addr, value, n);
800+
return 0;
800801
}
801802

802803
int WriteObjectMember(PyObject* object, Py_ssize_t offset, PyObject* value) {
803-
/* We first need to decref the old value. */
804-
Py_XDECREF(ReadMember(object, offset, PyObject*));
804+
/* We first need to decref the old value. */
805+
PyObject *oldv = ReadMember(object, offset, PyObject*);
806+
Py_XINCREF(value);
805807
WriteMember(object, offset, value, PyObject*);
808+
Py_XDECREF(oldv);
806809
return 0;
807810
}
808811

@@ -837,12 +840,13 @@ int WriteULongMember(PyObject* object, Py_ssize_t offset, unsigned long value) {
837840
}
838841

839842
int WriteObjectExMember(PyObject* object, Py_ssize_t offset, PyObject* value) {
840-
PyObject *oldv = ReadMember(object, offset, PyObject*);
843+
PyObject *oldv = ReadMember(object, offset, PyObject*);
841844
if (oldv == NULL) {
842845
return 1;
843846
}
844-
Py_XDECREF(oldv);
847+
Py_XINCREF(value);
845848
WriteMember(object, offset, value, PyObject*);
849+
Py_XDECREF(oldv);
846850
return 0;
847851
}
848852

@@ -905,7 +909,7 @@ void* truffle_ptr_add(void* x, Py_ssize_t y) {
905909
}
906910

907911
double truffle_read_ob_fval(PyFloatObject* fobj) {
908-
return fobj->ob_fval;
912+
return fobj->ob_fval;
909913
}
910914

911915
void truffle_memcpy_bytes(void *dest, size_t dest_offset, void *src, size_t src_offset, size_t len) {
@@ -914,7 +918,7 @@ void truffle_memcpy_bytes(void *dest, size_t dest_offset, void *src, size_t src_
914918

915919
/* called from Java to get number of bits per long digit */
916920
int32_t get_long_bits_in_digit() {
917-
return PYLONG_BITS_IN_DIGIT;
921+
return PYLONG_BITS_IN_DIGIT;
918922
}
919923

920924
void register_native_slots(PyTypeObject* managed_class, PyGetSetDef* getsets, PyMemberDef* members) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,11 @@ public static TruffleLogger getLogger(Class<?> clazz) {
826826
return TruffleLogger.getLogger(ID, clazz);
827827
}
828828

829+
@TruffleBoundary
830+
public static TruffleLogger getLogger(String name) {
831+
return TruffleLogger.getLogger(ID, name);
832+
}
833+
829834
/**
830835
* Loggers that should report any known incompatibility with CPython, which is silently ignored
831836
* in order to be able to continue the execution. Example is setting the stack size limit: it

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,9 @@
122122
import com.oracle.truffle.api.source.Source.SourceBuilder;
123123

124124
public final class CApiContext extends CExtContext {
125+
public static final String LOGGER_CAPI_NAME = "capi";
125126
protected static final String RUN_CAPI_LOADED_HOOKS = "run_capi_loaded_hooks";
126-
private static final TruffleLogger LOGGER = PythonLanguage.getLogger(CApiContext.class);
127+
private static final TruffleLogger LOGGER = PythonLanguage.getLogger(LOGGER_CAPI_NAME);
127128

128129
/**
129130
* A dummy context to disambiguate between <it>context not yet created</it> and <it>context
@@ -185,6 +186,10 @@ public final class CApiContext extends CExtContext {
185186
*/
186187
private AtomicLong nextTssKey = new AtomicLong();
187188

189+
public static TruffleLogger getLogger(Class<?> clazz) {
190+
return PythonLanguage.getLogger(LOGGER_CAPI_NAME + "." + clazz.getSimpleName());
191+
}
192+
188193
/**
189194
* Private dummy constructor just for {@link #LAZY_CONTEXT}.
190195
*/
@@ -417,7 +422,7 @@ public void markAsResurrected() {
417422
*/
418423
private static final class CApiReferenceCleanerRootNode extends PRootNode {
419424
private static final Signature SIGNATURE = new Signature(-1, false, -1, false, new String[]{"ptr", "managedRefCount"}, PythonUtils.EMPTY_STRING_ARRAY);
420-
private static final TruffleLogger LOGGER = PythonLanguage.getLogger(CApiReferenceCleanerRootNode.class);
425+
private static final TruffleLogger LOGGER = CApiContext.getLogger(CApiReferenceCleanerRootNode.class);
421426

422427
@Child private CalleeContext calleeContext;
423428
@Child private InteropLibrary pointerObjectLib;
@@ -487,8 +492,8 @@ public Object execute(VirtualFrame frame) {
487492
}
488493

489494
if (loggable) {
490-
final long countDuration = middleTime - startTime;
491-
final long duration = System.currentTimeMillis() - middleTime;
495+
final long countDuration = System.currentTimeMillis() - middleTime;
496+
final long duration = middleTime - startTime;
492497
final int finalCleaned = cleaned;
493498
final long freedNativeMemory = allocatedNativeMem - cApiContext.allocatedMemory;
494499
LOGGER.fine(() -> "Total queued references: " + n);
@@ -964,7 +969,7 @@ public static CApiContext ensureCapiWasLoaded(Node node, PythonContext context,
964969
*/
965970
throw e.getExceptionForReraise();
966971
} catch (RuntimeException e) {
967-
if (!context.getEnv().isNativeAccessAllowed()) {
972+
if (!context.isNativeAccessAllowed()) {
968973
throw new ImportException(null, name, path, ErrorMessages.NATIVE_ACCESS_NOT_ALLOWED);
969974
}
970975
throw new ApiInitException(wrapJavaException(e, node), name, ErrorMessages.CAPI_LOAD_ERROR, capiFile.getAbsoluteFile().getPath());

0 commit comments

Comments
 (0)