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

wasm2c: parametrize memory bounds checks on a per-memory basis #2507

Merged
merged 1 commit into from
Dec 4, 2024

Conversation

keithw
Copy link
Member

@keithw keithw commented Nov 11, 2024

(Sequenced behind #2506)

This PR allows "software-bounds-checked" memories and "guard-page-checked" memories to coexist in the same module.

It creates two versions of every memory operation: an unrestricted version (that works with any memory) and a _default32 version (for memories with default page size and i32 indexing).

The unrestricted version calls MEMCHECK_GENERAL, which does a 64-bit software RANGE_CHECK to check that the operation reads/writes within the bounds of the memory.

The _default32 version calls MEMCHECK_DEFAULT32, which is the same as the old MEMCHECK: if the runtime declares WASM_RT_MEMCHECK_GUARD_PAGES, it will do nothing. Otherwise it will do a 32-bit software RANGE_CHECK (which seems to be one less instruction than the 64-bit RANGE_CHECK).

This is a stepping stone to supporting custom-page-sizes (which will need to be software bounds-checked) (#2508).

@keithw keithw requested review from sbc100 and shravanrn November 11, 2024 09:16
@keithw keithw force-pushed the w2c-per-memory-strategy branch 3 times, most recently from 167eae8 to 985d89d Compare November 11, 2024 09:48
@keithw keithw force-pushed the w2c-harmonize-types branch from 2ece28b to 176ec50 Compare November 11, 2024 09:57
@keithw keithw force-pushed the w2c-per-memory-strategy branch from 985d89d to 5604e96 Compare November 11, 2024 09:57
@keithw keithw force-pushed the w2c-harmonize-types branch from 176ec50 to 7bea8ee Compare November 11, 2024 10:01
@keithw keithw force-pushed the w2c-per-memory-strategy branch from 5604e96 to 4e60e9c Compare November 11, 2024 10:01
@keithw keithw force-pushed the w2c-harmonize-types branch 2 times, most recently from d15bfb9 to beb8809 Compare November 11, 2024 23:15

#define DEFINE_STORE(name, t1, t2) \
static inline void name(wasm_rt_memory_t* mem, u64 addr, t2 value) { \
MEMCHECK(mem, addr, t1); \
static inline void name##_unchecked(wasm_rt_memory_t* mem, u64 addr, \
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not a strong opinion, but would it be simpler to have something like?

#define DEFINE_STORE(name, t1, t2, MEMCHK, suffix)                                  \
  static inline void name##_##suffix(wasm_rt_memory_t* mem, u64 addr,  t2 value) {  \
    MEMCHK(mem, addr, t1);                                                          \
    t1 wrapped = (t1)value;                                                         \
    wasm_rt_memcpy(MEM_ADDR_MEMOP(mem, addr, sizeof(t1)), &wrapped, sizeof(t1));    \
  }

DEFINE_STORE(i32_store, u32, u32, MEMCHECK_DEFAULT32, _default32);
DEFINE_STORE(i32_store, u32, u32, MEMCHECK_GENERAL, _general);

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess I was trying to avoid the churn of duplicating every occurrence of DEFINE_LOAD/DEFINE_STORE/DEFINE_SIMD_LOAD_FUNC/DEFINE_SIMD_LOAD_LANE/DEFINE_SHARED_LOAD/etc. ... I think on balance the status quo is probably the less-bad but I don't feel that strongly either.

memory->data = addr;
#else
memory->data = calloc(byte_length, 1);
if (WASM_RT_USE_MMAP && !is64) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Might be cleaner to have

// Check if we should reallocate using mmap
#if WASM_RT_USE_MMAP
if(!is64) {
  ... // original code
  return;
}
#endif

// Fallback to malloc
memory->data = calloc(byte_length, 1);

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah... I agree this one is clearer but it seemed nice to have consistency with grow_memory_impl where the early-return is harder to do. :-/

@keithw keithw force-pushed the w2c-harmonize-types branch 2 times, most recently from 487cb8a to 326e3cb Compare November 12, 2024 18:17
@keithw keithw force-pushed the w2c-per-memory-strategy branch from 4e60e9c to 8abbc62 Compare November 12, 2024 18:41
@keithw
Copy link
Member Author

keithw commented Nov 18, 2024

@sbc100 Did you want to review this one? @shravanrn would prefer to land #2506 and #2507 together, so I was planning to wait until everybody is comfortable with this one before merging either.

@keithw
Copy link
Member Author

keithw commented Dec 4, 2024

@sbc100 I'm going to merge this with #2506; please let me know if you want to re-review.

@keithw keithw merged commit 6fd3383 into w2c-harmonize-types Dec 4, 2024
18 checks passed
@keithw keithw deleted the w2c-per-memory-strategy branch December 4, 2024 20:37
keithw added a commit that referenced this pull request Dec 4, 2024
(Sequenced behind #2506)

This PR allows "software-bounds-checked" memories and
"guard-page-checked" memories to coexist in the same module.

It creates two versions of every memory operation: an unrestricted
version (that works with any memory) and a `_default32` version (for
memories with default page size and i32 indexing).

The unrestricted version calls `MEMCHECK_GENERAL`, which does a 64-bit
software `RANGE_CHECK` to check that the operation reads/writes within
the bounds of the memory.

The `_default32` version calls `MEMCHECK_DEFAULT32`, which is the same
as the old `MEMCHECK`: if the runtime declares
`WASM_RT_MEMCHECK_GUARD_PAGES`, it will do nothing. Otherwise it will do
a 32-bit software `RANGE_CHECK` (which seems to be one less instruction
than the 64-bit `RANGE_CHECK`).

This is a stepping stone to supporting custom-page-sizes (which will
need to be software bounds-checked) (#2508).
keithw added a commit that referenced this pull request Dec 6, 2024
(Sequenced behind #2506)

This PR allows "software-bounds-checked" memories and
"guard-page-checked" memories to coexist in the same module.

It creates two versions of every memory operation: an unrestricted
version (that works with any memory) and a `_default32` version (for
memories with default page size and i32 indexing).

The unrestricted version calls `MEMCHECK_GENERAL`, which does a 64-bit
software `RANGE_CHECK` to check that the operation reads/writes within
the bounds of the memory.

The `_default32` version calls `MEMCHECK_DEFAULT32`, which is the same
as the old `MEMCHECK`: if the runtime declares
`WASM_RT_MEMCHECK_GUARD_PAGES`, it will do nothing. Otherwise it will do
a 32-bit software `RANGE_CHECK` (which seems to be one less instruction
than the 64-bit `RANGE_CHECK`).

This is a stepping stone to supporting custom-page-sizes (which will
need to be software bounds-checked) (#2508).
keithw added a commit that referenced this pull request Dec 18, 2024
…hecks per-memory (#2507)

The PR updates the bulk memory operations (memory.fill, memory.copy,
table.fill, etc.) to support 64-bit addresses and counts. Previously these functions
only took u32's, even with memory64 enabled. (#2506)

This PR also allows "software-bounds-checked" memories and "guard-page-checked"
memories to coexist in the same module. It creates two versions of every memory
operation: an unrestricted version (that works with any memory) and a _default32
version (for memories with default page size and i32 indexing). (#2507)

#2506 and #2507 have been squashed together to avoid a performance regression.

This is a stepping stone to supporting custom-page-sizes (which will need to be
software-bounds-checked) (#2508).
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