Closed Bug 1374218 Opened 7 years ago Closed 7 years ago

Incorrect alignment assertion in js/src/wasm/WasmInstance.cpp, GlobalSegment::create

Categories

(Core :: JavaScript Engine: JIT, enhancement)

enhancement
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla56
Tracking Status
firefox56 --- fixed

People

(Reporter: jseward, Assigned: luke)

Details

Attachments

(2 files)

GlobalSegment::create(uint32_t globalDataLength) has this

  TlsData* tlsData =
      reinterpret_cast<TlsData*>(js_calloc(offsetof(TlsData, globalArea) + globalDataLength));
  ..
  MOZ_RELEASE_ASSERT((uintptr_t(tlsData) % 16) == 0);

js_calloc is a wrapper around plain calloc.  On x86-linux (32 bit),
the system calloc only returns 8-aligned memory.  So a build using
--disable-jemalloc will assert here (and I have observed it doing so.)
Clearly we need 16-alignment here really.  The "obvious" fix would be to
use js_memalign followed by memset-zero .. except .. we don't have a 
js_memalign, AFAICS.  We could perhaps create one as a wrapper around
posix_memalign, assuming that that's available on all targets and that
our mozjemalloc also provides that.  Mike, is that the right thing to do?
Flags: needinfo?(mh+mozilla)
A possible fix, per comment 1.
Even jemalloc doesn't guarantee more than 8 bytes alignment without using memalign or equivalent.
Flags: needinfo?(mh+mozilla)
(In reply to Mike Hommey [:glandium] from comment #3)
> Even jemalloc doesn't guarantee more than 8 bytes alignment without using
> memalign or equivalent.

Well, there's no guarantee, but since the allocation is larger than 8 bytes, in practice it's aligned to malloc_good_size(size), which is why we're probably never seeing this in the wild. However, that's an implementation detail of jemalloc, not a guarantee. Theoretically, we could hit this assertion on asan builds, too, although maybe the asan allocator has implementation details that make it work somehow too.
(In reply to Julian Seward [:jseward] from comment #1)
> We could perhaps create one as a wrapper around
> posix_memalign, assuming that that's available on all targets and that
> our mozjemalloc also provides that.  Mike, is that the right thing to do?

Mike, what's the officially approved way to do aligned allocation in our
universe?  My patch in comment 2 uses posix_memalign as I thought that
sounded the most portable, but a try build with that fails on Windows.
Flags: needinfo?(mh+mozilla)
We unfortunately don't /really/ have one. The truth is we kind of do, but only when mozjemalloc is enabled (it's posix_memalign, it's available on windows too, although there's no header defining it). (Yes, we really need to unify all that, and I'm partly doing this for other reasons, and *memalign is on my radar too)
Flags: needinfo?(mh+mozilla)
If sizeof(std::max_align_t) >= 16 on all systems (which we could static_assert), then if I read 3.7.4.1 and 3.11.2 correctly, the C++ std guarantees the returned memory is sufficiently aligned.  sizeof(max_align_t) = 32 on my system, but I don't know if this is true across tier 1.
You need to look at alignof(), not sizeof()
Oops, right.  I had expected those to be the same, but apparently not: alignof(max_align_t) = 16.
(In reply to Mike Hommey [:glandium] from comment #4)
> (In reply to Mike Hommey [:glandium] from comment #3)
> > Even jemalloc doesn't guarantee more than 8 bytes alignment without using
> > memalign or equivalent.
> 
> Well, there's no guarantee, but since the allocation is larger than 8 bytes,
> in practice it's aligned to malloc_good_size(size), which is why we're
> probably never seeing this in the wild. However, that's an implementation
> detail of jemalloc, not a guarantee. Theoretically, we could hit this
> assertion on asan builds, too, although maybe the asan allocator has
> implementation details that make it work somehow too.

ASan doesn't run on 32 bit targets, and I'd guess its 64 bit allocators
guarantee 16 alignment, which is why it never fails there.

How can we fix this in the short term?  Right now, 32 bit Linux builds done
with --disable-jemalloc (that is, configured to run on valgrind) often
segfault here because they get only 8-aligned memory.  I thought of the
usual horrible hack of allocating 8 more bytes than we actually need and
bumping the pointer along by 8 if required to make it 16-aligned.  But then
we can't free the block later unless we also store the original pointer
somewhere.
Flags: needinfo?(mh+mozilla)
There are not many of these objects and they are usually fairly large anyway, so we can embed the "memory pointer" inside the TlsData object, if we want to.  The GlobalSegment destructor should be the only place where we delete a tls, so there's no particular hardship.
Oh sorry, I missed that this was actually crashing somewhere; I thought this was theoretical.  Yeah, comment 11 sounds good.
(In reply to Luke Wagner [:luke] from comment #9)
> Oops, right.  I had expected those to be the same, but apparently not:
> alignof(max_align_t) = 16.

and it's 8 on 32 bits, which is what Julian is complaining about.

It's funny how in 2017, with SIMD, this alignment problem hasn't been solved in C++... there are a bunch of things in the standard to declare field alignments, etc. but nothing to actually deal with it for heap allocations...

This whole issue makes me want to write a replace-malloc lib that purposefully returns unaligned pointers to see what breaks...
Flags: needinfo?(mh+mozilla)
Attached patch align-tls-dataSplinter Review
Setting aside whether we should have our own posix_memalign (which sounds great), this patch just does that Lars suggested.
Assignee: nobody → luke
Attachment #8880959 - Flags: review?(lhansen)
Comment on attachment 8880959 [details] [diff] [review]
align-tls-data

Review of attachment 8880959 [details] [diff] [review]:
-----------------------------------------------------------------

Short and sweet.
Attachment #8880959 - Flags: review?(lhansen) → review+
Pushed by lwagner@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/ba901f83a5fd
Baldr: ensure alignment of TlsData (r=lth)
https://hg.mozilla.org/mozilla-central/rev/ba901f83a5fd
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: