Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPEX: Store pointers to current gmp objects in archive. #714

Merged
merged 1 commit into from
Jan 8, 2024

Conversation

mmuetzel
Copy link
Contributor

@mmuetzel mmuetzel commented Jan 7, 2024

I've been staring at that part of the code for a while. And I think this is a correct change.
IIUC, x in those preprocessor macros is of type mpz_t (or other types). Casting it to mpz_t * (or the other pointer types) is a bit confusing.
Instead, store the addresses to those values in the *_archive variables.

Because mpz_t, mpq_t and mpfr_t "happen" to be array types, this probably doesn't affect the actual code execution.

@DrTimothyAldenDavis
Copy link
Owner

Yes, that's the intent. The change makes sense, and I see it passes the CI, but I'll double check it first.

@DrTimothyAldenDavis
Copy link
Owner

The change doesn't work. I tried adding two statements: one is the original one and the other is the revised one with &x. The pointers are different.

This doesn't trigger a failure in the basic tests ("make demos") because the 'archive' is only used when an out-of-memory failure occurs. That only happens in the SPEX/*/Tcov tests, run by "make cov".

The pointer itself is not dereferenced. It's only used to test if the parameter "x" is about to be freed, and the test is "are these 2 pointers the same".

So I think I still need the same value of the pointer, as x, not &x.

But the type of the pointer might be wrong; I suppose spex_gmpz_archive should be an mpz_t type, not mpz_t *.

The pointer type could be a void * since it's not deferenced, but just checked for equality. I think I just need to change the type of spec_gmpz_archive, from mpz_t * to just mpz_t. Then there would be no typecast at all, but just this:

spex_gmpz_archive = x ; // option 1

Or maybe declaring these archive pointers as void * is the best thing to do. That would denote the fact that we do not do anything with these pointers (except check for equality with them); the spex_gmpz_archive pointer is never dereferenced. In that case, I should just declare

void * spec_gmpz_archive ;

and then assign it with this:

spec_gmpz_archive = (void *) x ; // option 2

I need to think over which option is best (option 1 or 2).

I do recognize that this "archive" thing is very strange. The only purpose of this "archive" pointer is the test in SPEX_GMP_SAFE_FREE, so that spex_gmp_free does not accidentally free its input argument when a memory failure occurs. If GMP itself (and MPFR too) handled memory-failure conditions properly, then none of this would be needed. GMP just aborts the entire application if any memory allocation fails. We can't do that in SPEX, so that's why we never return a NULL pointer to GMP, but catch it ourselves with setjmp / longjmp.

@DrTimothyAldenDavis
Copy link
Owner

DrTimothyAldenDavis commented Jan 8, 2024

Your point with this PR is well-taken, though. This statement:

spex_gmpz_archive = (mpz_t *) x ;
is odd. It works, because I get the right pointer. It's confusing because the pointer is the wrong type, but its type doesn't actually matter since spex_gmpz_archive is never dereferenced.

But the confusion can be removed with option (1) or (2). I just need to think through which is best.

@mmuetzel
Copy link
Contributor Author

mmuetzel commented Jan 8, 2024

The change doesn't work. I tried adding two statements: one is the original one and the other is the revised one with &x. The pointers are different.

I might have missed your point. But of course they will be different pointers. One is the pointer to the mpz_t object (an array type). The other is the pointer to the first (and only) __mpz_struct in that array.

The pointer itself is not dereferenced.

Afaict, it is derefenced. E.g., here:

if (p == SPEX_MPZ_PTR(*spex_gmpz_archive)) \

And then that is dereferenced again here:

#define SPEX_MPZ_PTR(x) ((x)->_mp_d)

So, your option 2 won't work.

And I'm not sure if your option 1 would work either...

@DrTimothyAldenDavis
Copy link
Owner

Oops ... your right, I do dereference those variables. It's because a call to a GMP function can revise the content of its input parameters (like x->_mp_d) and I have to ensure those aren't freed.

@mmuetzel
Copy link
Contributor Author

mmuetzel commented Jan 8, 2024

Looking at this in more detail, you really need to make this change (or an equivalent one). Or you might end up overriding random parts of the memory.

Could you please re-open?

@DrTimothyAldenDavis
Copy link
Owner

GMP defines its objects as arrays of size 1; see https://gmplib.org/gmp-man-6.3.0.pdf on page 18:

image

I should probably use mpz_ptr for the type of spec_gmpz_archive.

Perhaps the safest thing is to revise our manipulation of the internals of an mpz_t data type, to mimic how GMP does it: using "pointer decay" in a small function that accesses the contents of the variable (the _mp_d component).

@mmuetzel
Copy link
Contributor Author

mmuetzel commented Jan 8, 2024

I should probably use mpz_ptr for the type of spec_gmpz_archive.

Good idea. I did that in the last commit.

@DrTimothyAldenDavis
Copy link
Owner

This looks right to me. I'll check it out.

@DrTimothyAldenDavis
Copy link
Owner

OK, this works great. I tested it in the SPEX/SPEX_Left_LU/Tcov. As an extra check, I added printf's to both the old and new versions, and it's finding the same special cases in both versions.

So the functionality is the same but this update is cleaner than the original.

@DrTimothyAldenDavis DrTimothyAldenDavis merged commit b871dd2 into DrTimothyAldenDavis:dev2 Jan 8, 2024
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants