Skip to main content

failed_speculation_profile/
failed_speculation_profile.rs

1//! Frozen driver for immutable-source failure-sharing audits.
2use std::{env, fs, hint::black_box, time::Instant};
3
4use oxc_allocator::Allocator;
5use oxc_parser::{ParseOptions, Parser, config::RuntimeParserConfig};
6use oxc_span::SourceType;
7
8fn main() {
9    let mut args = env::args().skip(1);
10    let mode = args.next().expect("mode: time or packets");
11    let path = args.next().expect("UTF-8 input path");
12    let source = fs::read_to_string(path).unwrap();
13    if mode == "packets" {
14        assert!(args.next().is_none());
15        packets(&source);
16        return;
17    }
18    assert_eq!(mode, "time");
19    let iterations: usize = args.next().map_or(1, |n| n.parse().unwrap());
20    assert!((1..=100_000).contains(&iterations));
21    assert!(args.next().is_none());
22    let start = Instant::now();
23    let mut rejected = 0;
24    let mut peak_arena_used_bytes = 0;
25    for _ in 0..iterations {
26        let allocator = Allocator::default();
27        rejected += usize::from(
28            black_box(
29                Parser::new(&allocator, black_box(&source), SourceType::ts()).parse_expression(),
30            )
31            .is_err(),
32        );
33        peak_arena_used_bytes = peak_arena_used_bytes.max(allocator.used_bytes());
34    }
35    println!(
36        "{{\"iterations\":{iterations},\"rejected\":{rejected},\"elapsed_ns\":{},\"peak_arena_used_bytes\":{peak_arena_used_bytes}}}",
37        start.elapsed().as_nanos()
38    );
39}
40
41fn packets(source: &str) {
42    for source_type in [
43        SourceType::ts(),
44        SourceType::tsx(),
45        SourceType::jsx(),
46        SourceType::ts().with_script(true),
47        SourceType::ts().with_unambiguous(true),
48    ] {
49        for tokens in [false, true] {
50            for parse_regular_expression in [false, true] {
51                let options = ParseOptions { parse_regular_expression, ..ParseOptions::default() };
52                let allocator = Allocator::default();
53                let result = Parser::new(&allocator, source, source_type)
54                    .with_config(RuntimeParserConfig::new(tokens))
55                    .with_options(options)
56                    .parse();
57                println!(
58                    "program {source_type:?} tokens={tokens} regexp={parse_regular_expression}: {:?}\n{:?}\n{:?}\n{:?}\n{:?}\n{:?}",
59                    result.program,
60                    result.diagnostics,
61                    result.tokens,
62                    result.module_record,
63                    result.irregular_whitespaces,
64                    (result.panicked, result.is_flow_language),
65                );
66                let allocator = Allocator::default();
67                let observation = Parser::new(&allocator, source, source_type)
68                    .with_config(RuntimeParserConfig::new(tokens))
69                    .with_options(options)
70                    .parse_observed();
71                let facts = observation.admitted().map(|admitted| {
72                    (admitted.has_legacy_literals(), admitted.has_jsdoc_comments())
73                });
74                println!("original admitted source facts: {facts:?}");
75                let allocator = Allocator::default();
76                let result = Parser::new(&allocator, source, source_type)
77                    .with_config(RuntimeParserConfig::new(tokens))
78                    .with_options(options)
79                    .parse_expression();
80                println!(
81                    "expression {source_type:?} tokens={tokens} regexp={parse_regular_expression}: {result:?}"
82                );
83            }
84        }
85    }
86}