Add maximum threshold for number of blocks per function #951
To fix this case that may take forever to compile:
function %a(){
ebb477777777:
}
We decide to define a maximum threshold for the number of blocks in functions.
Based on a large WASM program (https://github.com/mozilla/perf-automation/blob/master/benchmarks/wasm-misc/AngryBots.wasm),
its IR functions does not exceed 1414 blocks. A number 100 times greater (100,000 blocks) seems (currently) enough to define our maximum threshold.
To make this quick benchmark the cranelift-wasm/src/func_translator.rs file has been modified like this:
static mut MAX: usize = 0;
pub fn translate_from_reader<FE: FuncEnvironment + ?Sized>(...) {
[...]
builder.finalize();
// the compiler is single threaded
unsafe {
if func.dfg.num_ebbs() > MAX {
MAX = func.dfg.num_ebbs();
println!("MAX {}", MAX);
}
}
Ok(())
}
This commit is contained in:
@@ -27,6 +27,9 @@ use std::str::FromStr;
|
||||
use std::{u16, u32};
|
||||
use target_lexicon::Triple;
|
||||
|
||||
/// After some quick benchmarks a program should never have more than 100,000 blocks.
|
||||
const MAX_BLOCKS_IN_A_FUNCTION: u32 = 100_000;
|
||||
|
||||
/// Parse the entire `text` into a list of functions.
|
||||
///
|
||||
/// Any test commands or target declarations are ignored.
|
||||
@@ -1768,6 +1771,10 @@ impl<'a> Parser<'a> {
|
||||
let block_num = self.match_block("expected block header")?;
|
||||
let block = ctx.add_block(block_num, self.loc)?;
|
||||
|
||||
if block_num.as_u32() >= MAX_BLOCKS_IN_A_FUNCTION {
|
||||
return Err(self.error("too many blocks"));
|
||||
}
|
||||
|
||||
if !self.optional(Token::Colon) {
|
||||
// block-header ::= Block(block) [ * block-params ] ":"
|
||||
self.parse_block_params(ctx, block)?;
|
||||
@@ -2979,6 +2986,24 @@ mod tests {
|
||||
assert!(!is_warning);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn number_of_blocks() {
|
||||
let ParseError {
|
||||
location,
|
||||
message,
|
||||
is_warning,
|
||||
} = Parser::new(
|
||||
"function %a() {
|
||||
block100000:",
|
||||
)
|
||||
.parse_function(None)
|
||||
.unwrap_err();
|
||||
|
||||
assert_eq!(location.line_number, 2);
|
||||
assert_eq!(message, "too many blocks");
|
||||
assert!(!is_warning);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_jt() {
|
||||
let ParseError {
|
||||
|
||||
Reference in New Issue
Block a user