Skip to content

Commit fe1307b

Browse files
authored
Add support for the custom-page-sizes proposal (#1489)
* wasmparser: Add support for the custom-page-sizes proposal * wasm-encoder: Add support for the custom-page-sizes proposal * wast: Add support for the custom-page-sizes proposal * wasm-smith: Add support for the custom-page-sizes proposal * wasmprinter: Add support for the custom-page-sizes proposal * Add support for the custom-page-sizes proposal to the roundtrip test * Get the workspace compiling again * Add roundtrip tests for the custom-page-sizes proposal * Fix compiler errors * More compiler errors and test expectation updates * Address review feedback * more review feedback * use module quote
1 parent 56a2963 commit fe1307b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1347
-100
lines changed

crates/wasm-encoder/src/core/data.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::{encode_section, encoding_size, ConstExpr, Encode, Section, SectionId
1818
/// maximum: None,
1919
/// memory64: false,
2020
/// shared: false,
21+
/// page_size_log2: None,
2122
/// });
2223
///
2324
/// let mut data = DataSection::new();

crates/wasm-encoder/src/core/imports.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ impl TryFrom<wasmparser::TypeRef> for EntityType {
103103
/// maximum: None,
104104
/// memory64: false,
105105
/// shared: false,
106+
/// page_size_log2: None,
106107
/// }
107108
/// );
108109
///

crates/wasm-encoder/src/core/memories.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::{encode_section, Encode, Section, SectionId};
1515
/// maximum: None,
1616
/// memory64: false,
1717
/// shared: false,
18+
/// page_size_log2: None,
1819
/// });
1920
///
2021
/// let mut module = Module::new();
@@ -75,26 +76,41 @@ pub struct MemoryType {
7576
pub memory64: bool,
7677
/// Whether or not this memory is shared.
7778
pub shared: bool,
79+
/// The log base 2 of a custom page size for this memory.
80+
///
81+
/// The default page size for Wasm memories is 64KiB, i.e. 2<sup>16</sup> or
82+
/// `65536`.
83+
///
84+
/// After the introduction of [the custom-page-sizes
85+
/// proposal](https://github.com/WebAssembly/custom-page-sizes), Wasm can
86+
/// customize the page size. It must be a power of two that is less than or
87+
/// equal to 64KiB. Attempting to encode an invalid page size may panic.
88+
pub page_size_log2: Option<u32>,
7889
}
7990

8091
impl Encode for MemoryType {
8192
fn encode(&self, sink: &mut Vec<u8>) {
8293
let mut flags = 0;
8394
if self.maximum.is_some() {
84-
flags |= 0b001;
95+
flags |= 0b0001;
8596
}
8697
if self.shared {
87-
flags |= 0b010;
98+
flags |= 0b0010;
8899
}
89100
if self.memory64 {
90-
flags |= 0b100;
101+
flags |= 0b0100;
102+
}
103+
if self.page_size_log2.is_some() {
104+
flags |= 0b1000;
91105
}
92-
93106
sink.push(flags);
94107
self.minimum.encode(sink);
95108
if let Some(max) = self.maximum {
96109
max.encode(sink);
97110
}
111+
if let Some(p) = self.page_size_log2 {
112+
p.encode(sink);
113+
}
98114
}
99115
}
100116

@@ -106,6 +122,7 @@ impl From<wasmparser::MemoryType> for MemoryType {
106122
maximum: memory_ty.maximum,
107123
memory64: memory_ty.memory64,
108124
shared: memory_ty.shared,
125+
page_size_log2: memory_ty.page_size_log2,
109126
}
110127
}
111128
}

crates/wasm-mutate/src/mutators/translate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ pub fn memory_type(
160160
minimum: ty.initial,
161161
maximum: ty.maximum,
162162
shared: ty.shared,
163+
page_size_log2: ty.page_size_log2,
163164
})
164165
}
165166

crates/wasm-shrink/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ impl ShrinkRun {
236236
component_model: false,
237237
function_references: false,
238238
gc: false,
239+
custom_page_sizes: false,
239240
component_model_values: false,
240241
component_model_nested_names: false,
241242

crates/wasm-smith/src/config.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,12 @@ define_config! {
313313
/// Defaults to `false`.
314314
pub gc_enabled: bool = false,
315315

316+
/// Determines whether the custom-page-sizes proposal is enabled when
317+
/// generating a Wasm module.
318+
///
319+
/// Defaults to `false`.
320+
pub custom_page_sizes_enabled: bool = false,
321+
316322
/// Returns whether we should generate custom sections or not. Defaults
317323
/// to false.
318324
pub generate_custom_sections: bool = false,
@@ -715,6 +721,7 @@ impl<'a> Arbitrary<'a> for Config {
715721
export_everything: false,
716722
tail_call_enabled: false,
717723
gc_enabled: false,
724+
custom_page_sizes_enabled: false,
718725
generate_custom_sections: false,
719726
allow_invalid_funcs: false,
720727
})

crates/wasm-smith/src/core.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,7 +2324,7 @@ impl Module {
23242324

23252325
// Interesting values related to memory bounds.
23262326
for m in self.memories.iter() {
2327-
let min = m.minimum.saturating_mul(crate::WASM_PAGE_SIZE);
2327+
let min = m.minimum.saturating_mul(crate::page_size(m).into());
23282328
interesting(min);
23292329
for i in 0..5 {
23302330
if let Some(x) = min.checked_add(1 << i) {
@@ -2336,7 +2336,7 @@ impl Module {
23362336
}
23372337

23382338
if let Some(max) = m.maximum {
2339-
let max = max.saturating_mul(crate::WASM_PAGE_SIZE);
2339+
let max = max.saturating_mul(crate::page_size(m).into());
23402340
interesting(max);
23412341
for i in 0..5 {
23422342
if let Some(x) = max.checked_add(1 << i) {
@@ -2518,6 +2518,11 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result
25182518
// We want to favor memories <= 1gb in size, allocate at most 16k pages,
25192519
// depending on the maximum number of memories.
25202520
let memory64 = config.memory64_enabled && u.arbitrary()?;
2521+
let page_size = if config.custom_page_sizes_enabled && u.arbitrary()? {
2522+
Some(1 << u.int_in_range(0..=16)?)
2523+
} else {
2524+
None
2525+
};
25212526
let max_inbounds = 16 * 1024 / u64::try_from(config.max_memories).unwrap();
25222527
let min_pages = if config.disallow_traps { Some(1) } else { None };
25232528
let max_pages = min_pages.unwrap_or(0).max(if memory64 {
@@ -2537,6 +2542,7 @@ pub(crate) fn arbitrary_memtype(u: &mut Unstructured, config: &Config) -> Result
25372542
maximum,
25382543
memory64,
25392544
shared,
2545+
page_size_log2: page_size,
25402546
})
25412547
}
25422548

crates/wasm-smith/src/core/code_builder.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5203,10 +5203,12 @@ fn memory_offset(u: &mut Unstructured, module: &Module, memory_index: u32) -> Re
52035203
assert!(a + b + c != 0);
52045204

52055205
let memory_type = &module.memories[memory_index as usize];
5206-
let min = memory_type.minimum.saturating_mul(crate::WASM_PAGE_SIZE);
5206+
let min = memory_type
5207+
.minimum
5208+
.saturating_mul(crate::page_size(memory_type).into());
52075209
let max = memory_type
52085210
.maximum
5209-
.map(|max| max.saturating_mul(crate::WASM_PAGE_SIZE))
5211+
.map(|max| max.saturating_mul(crate::page_size(memory_type).into()))
52105212
.unwrap_or(u64::MAX);
52115213

52125214
let (min, max, true_max) = match (memory_type.memory64, module.config.disallow_traps) {

crates/wasm-smith/src/core/code_builder/no_traps.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ pub(crate) fn load<'a>(
3737
// []
3838
insts.push(Instruction::MemorySize(memarg.memory_index));
3939
// [mem_size_in_pages:address_type]
40-
insts.push(int_const_inst(address_type, 65_536));
40+
insts.push(int_const_inst(
41+
address_type,
42+
crate::page_size(memory).into(),
43+
));
4144
// [mem_size_in_pages:address_type wasm_page_size:address_type]
4245
insts.push(int_mul_inst(address_type));
4346
// [mem_size_in_bytes:address_type]
@@ -116,7 +119,10 @@ pub(crate) fn store<'a>(
116119
// []
117120
insts.push(Instruction::MemorySize(memarg.memory_index));
118121
// [mem_size_in_pages:address_type]
119-
insts.push(int_const_inst(address_type, 65_536));
122+
insts.push(int_const_inst(
123+
address_type,
124+
crate::page_size(memory).into(),
125+
));
120126
// [mem_size_in_pages:address_type wasm_page_size:address_type]
121127
insts.push(int_mul_inst(address_type));
122128
// [mem_size_in_bytes:address_type]

crates/wasm-smith/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,15 @@ use arbitrary::{Result, Unstructured};
6363
pub use component::Component;
6464
pub use config::{Config, MemoryOffsetChoices};
6565
use std::{collections::HashSet, fmt::Write, str};
66+
use wasm_encoder::MemoryType;
6667

6768
#[cfg(feature = "_internal_cli")]
6869
pub use config::InternalOptionalConfig;
6970

70-
const WASM_PAGE_SIZE: u64 = 65_536;
71+
pub(crate) fn page_size(mem: &MemoryType) -> u32 {
72+
const DEFAULT_WASM_PAGE_SIZE: u32 = 65_536;
73+
mem.page_size_log2.unwrap_or(DEFAULT_WASM_PAGE_SIZE)
74+
}
7175

7276
/// Do something an arbitrary number of times.
7377
///

0 commit comments

Comments
 (0)