Skip to content

Conversation

@RReverser
Copy link
Collaborator

This streamlines the SAFE_HEAP transform in acorn-optimizer. I was going to send this as a separate cleanup PR as part of my other work on acorn-optimizer, but it happens to also be the easy fix for a regression mentioned in #24289 and caused by #24283 which added support for 64-bit integers to acorn-optimizer passes.

I could fix that issue separately by tweaking unSign, but this way we don't need to bother - the values with correct sign are now automatically retrieved by accessing the correct HEAP* array.

I've added a regression test for the linked issue as well, which fails before this PR and passes after.

RReverser added 2 commits May 9, 2025 19:21
This streamlines the `SAFE_HEAP` transform in acorn-optimizer. I was going
to send this as a separate cleanup PR as part of my other work on
acorn-optimizer, but it happens to also be the easy fix for a regression
mentioned in emscripten-core#24289
and caused by emscripten-core#24283
which added support for 64-bit integers to acorn-optimizer passes.

I could fix that issue separately by tweaking `unSign`, but this way we
don't need to bother - the values with correct sign are now
automatically retrieved by accessing the correct `HEAP*` array.

I've added a regression test for the linked issue as well, which
fails before this PR and passes after.
@RReverser RReverser requested review from kripken and sbc100 May 9, 2025 18:32
Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@sbc100
Copy link
Collaborator

sbc100 commented May 9, 2025

This seems like a clear improvement so I'm tempted to land it once that tests pass, but maybe we should wait for an approval from @kripken since he knows this code better then me.

RReverser added a commit to RReverser/emscripten that referenced this pull request May 9, 2025
Similar to emscripten-core#24291, but for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current sizes, and in the second you can see that this transform actually saves the total size in addition to making acorn-optimizer simpler.
@RReverser RReverser force-pushed the simplify-and-fix-safe-heap branch from 00de2cf to 507e209 Compare May 9, 2025 22:49
RReverser added a commit to RReverser/emscripten that referenced this pull request May 9, 2025
Similar to emscripten-core#24291, but for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current sizes, and in the second you can see that this transform actually saves the total size in addition to making acorn-optimizer simpler.
@RReverser RReverser force-pushed the simplify-and-fix-safe-heap branch from 507e209 to 7946613 Compare May 9, 2025 23:36
RReverser added a commit to RReverser/emscripten that referenced this pull request May 10, 2025
Similar to emscripten-core#24291, but for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current sizes, and in the second you can see that this transform actually saves the total size in addition to making acorn-optimizer simpler.
@RReverser
Copy link
Collaborator Author

@kripken Can you take a look please - this fixes a CI regression in emscripten-releases.

@sbc100
Copy link
Collaborator

sbc100 commented May 13, 2025

Is this the first in your series of patches to land? And ready to go?

@RReverser
Copy link
Collaborator Author

Either order is fine, they're pretty independent from each other. It's ready to go, I'm just waiting for @kripken's review since you suggested we should wait for his approval above.

sbc100 pushed a commit that referenced this pull request May 13, 2025
Leverages ASan's C API for arbitrary loads/stores instead of custom C
code with separate variants for each possible type.

Similar to #24295 and
#24291.
@RReverser
Copy link
Collaborator Author

I'm merging since this is a blocker. I'm happy to address follow-up comments if any in a separate PR.

@RReverser RReverser merged commit 976b43d into emscripten-core:main May 13, 2025
28 checks passed
@RReverser RReverser deleted the simplify-and-fix-safe-heap branch May 13, 2025 10:18
#if SAFE_HEAP == 1
if (dest % bytes !== 0) abort(`alignment error storing to address ${dest}, which was expected to be aligned to a multiple of ${bytes}`);
#else
if (dest % bytes !== 0) warnOnce(`alignment error in a memory store operation, alignment was a multiple of ${(((dest ^ (dest-1)) >> 1) + 1)}, but was was expected to be aligned to a multiple of ${bytes}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to the alignment checks?

Copy link
Collaborator Author

@RReverser RReverser May 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer necessary because we pass in an index in the corresponding array instead of pre-multiplied pointer.

Those were already guaranteed not to be hit since we always did transform like HEAP32[i] -> SAFE_HEAP_LOAD(i * 4, 4, ...) and then function would just check that i * 4 is divisible by 4, which is always true, but now it's just more obvious since we skip the premultiplication.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I was also concerned about directly-emitted SAFE_HEAP_* calls from parseTools (not from the acorn transform), but I see we removed those a while ago, which I forgot...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, I did also notice that

function SAFE_HEAP_CLEAR(dest)
function SAFE_HEAP_ACCESS(dest, type, store, ignore, storeValue)
function SAFE_HEAP_STORE(dest, value, type, ignore)
function SAFE_HEAP_LOAD(dest, type, unsigned, ignore)
function SAFE_HEAP_COPY_HISTORY(dest, src)
function SAFE_HEAP_FILL_HISTORY(from, to, type)
function getSafeHeapType(bytes, isFloat)
function SAFE_HEAP_STORE(dest, value, bytes, isFloat)
function SAFE_HEAP_LOAD(dest, bytes, isFloat, unsigned)
function SAFE_FT_MASK(value, mask)
function CHECK_OVERFLOW(value, bits, ignore, sig)
lists quite a few methods that don't (no longer?) exist, and probably misses bunch of new ones instead.

Maybe that section should be just removed at this point instead of trying in sync, since it's pretty outdated and not rendered in docs anyway?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, yeah, best to just remove that bit, good find.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, I think we saw that that JS-side bug is long-standing and never caused any issues, so it doesn't feel urgent to fix.

Fair enough. I was mainly curious in context of those no-op checks we are commenting on, as I assume they used to do something useful in the long past, so technically a regression happened at some point... but idk when. As you say, it's probably not urgent.

If the input code contains HEAP32[x] then by construction x must be 4-byte aligned, no?

Problem I'm thinking about, a lot of code has form like HEAP32[somePtr >> 2] and such, whether handcrafted or generated via makeGetValue, and in those cases there is no guarantee somePtr is already correctly aligned.

JS transform could detect at least this common form of access and check the alignment. Or maybe at least makeGetValue/getHeapOffset itself could insert those checks when SAFE_HEAP is enabled.

Copy link
Collaborator

@sbc100 sbc100 May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but what about this?

// a JS function that is called from wasm, and given a (maybe unaligned) pointer
function jsHelper(ptr) {
  return HEAP32[ptr >> 2];
}

But I don't think the old code handled this did it? It just checked the value of ptr >> 2 at runtime, right? So there is no regression here is there?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JS transform could detect at least this common form of access and check the alignment. Or maybe at least makeGetValue/getHeapOffset itself could insert those checks when SAFE_HEAP is enabled.

To be clear neither the old new the version the JS transform do this though do they?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear neither the old new the version the JS transform do this though do they?

If you mean before/after this PR, then yeah.

But judging by the removed code, it used to in the long past. And, well, even if it didn't, just saying it would be a useful addition.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this isn't a recent regression. But it may have regressed a long time ago, or never worked... Anyhow, alignment checks from JS are pretty minor, not worth worrying about.

RReverser added a commit to RReverser/emscripten that referenced this pull request May 13, 2025
Similar to emscripten-core#24291, but for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current sizes, and in the second you can see that this transform actually saves the total size in addition to making acorn-optimizer simpler.
RReverser added a commit to RReverser/emscripten that referenced this pull request May 14, 2025
Similar to emscripten-core#24291, but for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current sizes, and in the second you can see that this transform actually saves the total size in addition to making acorn-optimizer simpler.
RReverser added a commit to RReverser/emscripten that referenced this pull request May 15, 2025
Similar to emscripten-core#24291, but for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current sizes, and in the second you can see that this transform actually saves the total size in addition to making acorn-optimizer simpler.
RReverser added a commit to RReverser/emscripten that referenced this pull request May 16, 2025
Similar to emscripten-core#24291, but for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current sizes, and in the second you can see that this transform actually saves the total size in addition to making acorn-optimizer simpler.
RReverser added a commit to RReverser/emscripten that referenced this pull request May 16, 2025
Similar to emscripten-core#24291, but for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current sizes, and in the second you can see that this transform actually saves the total size in addition to making acorn-optimizer simpler.
RReverser added a commit that referenced this pull request May 16, 2025
Similar to #24291, but
for the transform handling `-pthread` + `-sALLOW_MEMORY_GROWTH`.

In the first commit I added a codesize variation to commit current
sizes, and in the second you can see that this transform actually saves
the total size in addition to making acorn-optimizer simpler.
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.

3 participants