Skip to content

Commit

Permalink
refactor(common): Mark some methods of Input unsafe (#7848)
Browse files Browse the repository at this point in the history
**Related issue:**

 - Closes #7709
  • Loading branch information
kdy1 committed Aug 24, 2023
1 parent a9a6928 commit c657324
Show file tree
Hide file tree
Showing 10 changed files with 360 additions and 102 deletions.
64 changes: 43 additions & 21 deletions crates/swc_common/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ impl<'a> StringInput<'a> {

#[inline]
pub fn bump_bytes(&mut self, n: usize) {
self.reset_to(self.last_pos + BytePos(n as u32));
unsafe {
// Safety: We only proceed, not go back.
self.reset_to(self.last_pos + BytePos(n as u32));
}
}
}

Expand Down Expand Up @@ -78,7 +81,7 @@ impl<'a> Input for StringInput<'a> {
}

#[inline]
fn bump(&mut self) {
unsafe fn bump(&mut self) {
if let Some((i, c)) = self.iter.next() {
self.last_pos = self.start_pos_of_iter + BytePos((i + c.len_utf8()) as u32);
} else {
Expand Down Expand Up @@ -115,7 +118,7 @@ impl<'a> Input for StringInput<'a> {
}

#[inline]
fn slice(&mut self, start: BytePos, end: BytePos) -> &str {
unsafe fn slice(&mut self, start: BytePos, end: BytePos) -> &str {
debug_assert!(start <= end, "Cannot slice {:?}..{:?}", start, end);
let s = self.orig;

Expand Down Expand Up @@ -184,7 +187,7 @@ impl<'a> Input for StringInput<'a> {
}

#[inline]
fn reset_to(&mut self, to: BytePos) {
unsafe fn reset_to(&mut self, to: BytePos) {
let orig = self.orig;
let idx = (to - self.orig_start).0 as usize;

Expand All @@ -197,12 +200,12 @@ impl<'a> Input for StringInput<'a> {

#[inline]
fn is_byte(&mut self, c: u8) -> bool {
if self.iter.as_str().is_empty() {
false
} else {
// Safety: We checked that `self.iter.as_str().len() > 0`
unsafe { *self.iter.as_str().as_bytes().get_unchecked(0) == c }
}
self.iter
.as_str()
.as_bytes()
.first()
.map(|b| *b == c)
.unwrap_or(false)
}

#[inline]
Expand Down Expand Up @@ -233,7 +236,12 @@ pub trait Input: Clone {
fn cur(&mut self) -> Option<char>;
fn peek(&mut self) -> Option<char>;
fn peek_ahead(&mut self) -> Option<char>;
fn bump(&mut self);

/// # Safety
///
/// This should be called only when `cur()` returns `Some`. i.e.
/// when the Input is not empty.
unsafe fn bump(&mut self);

/// Returns [None] if it's end of input **or** current character is not an
/// ascii character.
Expand All @@ -253,7 +261,11 @@ pub trait Input: Clone {

fn last_pos(&self) -> BytePos;

fn slice(&mut self, start: BytePos, end: BytePos) -> &str;
/// # Safety
///
/// - start should be less than or equal to end.
/// - start and end should be in the valid range of input.
unsafe fn slice(&mut self, start: BytePos, end: BytePos) -> &str;

/// Takes items from stream, testing each one with predicate. returns the
/// range of items which passed predicate.
Expand All @@ -266,7 +278,10 @@ pub trait Input: Clone {
where
F: FnMut(char) -> bool;

fn reset_to(&mut self, to: BytePos);
/// # Safety
///
/// - `to` be in the valid range of input.
unsafe fn reset_to(&mut self, to: BytePos);

/// Implementors can override the method to make it faster.
///
Expand All @@ -291,7 +306,10 @@ pub trait Input: Clone {
#[inline]
fn eat_byte(&mut self, c: u8) -> bool {
if self.is_byte(c) {
self.bump();
unsafe {
// Safety: We are sure that the input is not empty
self.bump();
}
true
} else {
false
Expand Down Expand Up @@ -319,13 +337,13 @@ mod tests {
#[test]
fn src_input_slice_1() {
with_test_sess("foo/d", |mut i| {
assert_eq!(i.slice(BytePos(1), BytePos(2)), "f");
assert_eq!(unsafe { i.slice(BytePos(1), BytePos(2)) }, "f");
assert_eq!(i.last_pos, BytePos(2));
assert_eq!(i.start_pos_of_iter, BytePos(2));
assert_eq!(i.cur(), Some('o'));

assert_eq!(i.slice(BytePos(2), BytePos(4)), "oo");
assert_eq!(i.slice(BytePos(1), BytePos(4)), "foo");
assert_eq!(unsafe { i.slice(BytePos(2), BytePos(4)) }, "oo");
assert_eq!(unsafe { i.slice(BytePos(1), BytePos(4)) }, "foo");
assert_eq!(i.last_pos, BytePos(4));
assert_eq!(i.start_pos_of_iter, BytePos(4));
assert_eq!(i.cur(), Some('/'));
Expand All @@ -335,11 +353,11 @@ mod tests {
#[test]
fn src_input_reset_to_1() {
with_test_sess("load", |mut i| {
assert_eq!(i.slice(BytePos(1), BytePos(3)), "lo");
assert_eq!(unsafe { i.slice(BytePos(1), BytePos(3)) }, "lo");
assert_eq!(i.last_pos, BytePos(3));
assert_eq!(i.start_pos_of_iter, BytePos(3));
assert_eq!(i.cur(), Some('a'));
i.reset_to(BytePos(1));
unsafe { i.reset_to(BytePos(1)) };

assert_eq!(i.cur(), Some('l'));
assert_eq!(i.last_pos, BytePos(1));
Expand All @@ -360,11 +378,15 @@ mod tests {
assert_eq!(i.start_pos_of_iter, BytePos(4));
assert_eq!(i.cur(), Some('/'));

i.bump();
unsafe {
i.bump();
}
assert_eq!(i.last_pos, BytePos(5));
assert_eq!(i.cur(), Some('d'));

i.bump();
unsafe {
i.bump();
}
assert_eq!(i.last_pos, BytePos(6));
assert_eq!(i.cur(), None);
});
Expand Down
16 changes: 13 additions & 3 deletions crates/swc_css_parser/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ where
}

fn reset(&mut self, state: &Self::State) {
self.input.reset_to(state.pos);
unsafe {
// Safety: state.pos is created from a valid position.
self.input.reset_to(state.pos);
}
}

fn take_errors(&mut self) -> Vec<Error> {
Expand Down Expand Up @@ -199,15 +202,22 @@ where
self.cur_pos = self.input.last_pos();

if cur.is_some() {
self.input.bump();
unsafe {
// Safety: cur is Some
self.input.bump();
}
}

cur
}

#[inline(always)]
fn reconsume(&mut self) {
self.input.reset_to(self.cur_pos);
unsafe {
// Safety: self.cur_pos is a position generated by self.input, meaning it is
// valid.
self.input.reset_to(self.cur_pos);
}
}

#[cold]
Expand Down

1 comment on commit c657324

@github-actions
Copy link

Choose a reason for hiding this comment

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

Benchmark

Benchmark suite Current: c657324 Previous: a34f359 Ratio
es/full/bugs-1 316864 ns/iter (± 13137) 290305 ns/iter (± 11202) 1.09
es/full/minify/libraries/antd 1564685608 ns/iter (± 42210113) 1368513636 ns/iter (± 7108874) 1.14
es/full/minify/libraries/d3 347915578 ns/iter (± 8210790) 288419539 ns/iter (± 4883346) 1.21
es/full/minify/libraries/echarts 1281631422 ns/iter (± 37246218) 1092609136 ns/iter (± 4095173) 1.17
es/full/minify/libraries/jquery 98557108 ns/iter (± 2446403) 84432628 ns/iter (± 600899) 1.17
es/full/minify/libraries/lodash 113785133 ns/iter (± 2890430) 98175010 ns/iter (± 1017714) 1.16
es/full/minify/libraries/moment 54893317 ns/iter (± 1530162) 49834529 ns/iter (± 330190) 1.10
es/full/minify/libraries/react 18208521 ns/iter (± 643854) 18016753 ns/iter (± 136967) 1.01
es/full/minify/libraries/terser 219861331 ns/iter (± 1141150) 224903620 ns/iter (± 2388830) 0.98
es/full/minify/libraries/three 392402845 ns/iter (± 2653927) 408366918 ns/iter (± 8078142) 0.96
es/full/minify/libraries/typescript 2682208195 ns/iter (± 11326855) 2703039681 ns/iter (± 25661620) 0.99
es/full/minify/libraries/victory 578755800 ns/iter (± 6068152) 591206521 ns/iter (± 8231464) 0.98
es/full/minify/libraries/vue 120683341 ns/iter (± 717050) 121047392 ns/iter (± 2619769) 1.00
es/full/codegen/es3 34867 ns/iter (± 275) 34292 ns/iter (± 73) 1.02
es/full/codegen/es5 34950 ns/iter (± 66) 34268 ns/iter (± 254) 1.02
es/full/codegen/es2015 35024 ns/iter (± 138) 34384 ns/iter (± 62) 1.02
es/full/codegen/es2016 35024 ns/iter (± 40) 34384 ns/iter (± 138) 1.02
es/full/codegen/es2017 34982 ns/iter (± 65) 34349 ns/iter (± 50) 1.02
es/full/codegen/es2018 34997 ns/iter (± 82) 34337 ns/iter (± 68) 1.02
es/full/codegen/es2019 34948 ns/iter (± 65) 34328 ns/iter (± 52) 1.02
es/full/codegen/es2020 34998 ns/iter (± 84) 34225 ns/iter (± 87) 1.02
es/full/all/es3 167329697 ns/iter (± 1659425) 168162650 ns/iter (± 993704) 1.00
es/full/all/es5 159502913 ns/iter (± 1025358) 160950274 ns/iter (± 1114552) 0.99
es/full/all/es2015 119580309 ns/iter (± 976041) 120347990 ns/iter (± 554776) 0.99
es/full/all/es2016 118238131 ns/iter (± 815654) 120141917 ns/iter (± 940380) 0.98
es/full/all/es2017 117437699 ns/iter (± 1126296) 118900330 ns/iter (± 1373891) 0.99
es/full/all/es2018 115876072 ns/iter (± 1041964) 116729431 ns/iter (± 1097422) 0.99
es/full/all/es2019 114622747 ns/iter (± 878856) 115736617 ns/iter (± 1019772) 0.99
es/full/all/es2020 110906752 ns/iter (± 1843487) 112096006 ns/iter (± 1075434) 0.99
es/full/parser 486394 ns/iter (± 4637) 490481 ns/iter (± 7816) 0.99
es/full/base/fixer 20544 ns/iter (± 355) 20027 ns/iter (± 169) 1.03
es/full/base/resolver_and_hygiene 81254 ns/iter (± 190) 80909 ns/iter (± 289) 1.00
serialization of serde 291 ns/iter (± 1) 297 ns/iter (± 2) 0.98
css/minify/libraries/bootstrap 28467062 ns/iter (± 37836) 28247475 ns/iter (± 94291) 1.01
css/visitor/compare/clone 1794068 ns/iter (± 3867) 1647660 ns/iter (± 2857) 1.09
css/visitor/compare/visit_mut_span 1916242 ns/iter (± 3056) 1774445 ns/iter (± 3220) 1.08
css/visitor/compare/visit_mut_span_panic 1991261 ns/iter (± 3846) 1846632 ns/iter (± 3559) 1.08
css/visitor/compare/fold_span 2748076 ns/iter (± 9293) 2580456 ns/iter (± 10278) 1.06
css/visitor/compare/fold_span_panic 2938029 ns/iter (± 13918) 2769726 ns/iter (± 20215) 1.06
css/lexer/bootstrap_5_1_3 4476781 ns/iter (± 2742) 4529510 ns/iter (± 21913) 0.99
css/lexer/foundation_6_7_4 3757306 ns/iter (± 4476) 3790061 ns/iter (± 5332) 0.99
css/lexer/tailwind_3_1_1 716565 ns/iter (± 1071) 724156 ns/iter (± 2295) 0.99
css/parser/bootstrap_5_1_3 19910838 ns/iter (± 33140) 19539408 ns/iter (± 120531) 1.02
css/parser/foundation_6_7_4 15801145 ns/iter (± 29867) 15233692 ns/iter (± 53513) 1.04
css/parser/tailwind_3_1_1 3054756 ns/iter (± 3921) 3013927 ns/iter (± 7560) 1.01
es/codegen/colors 733572 ns/iter (± 401093) 730595 ns/iter (± 398749) 1.00
es/codegen/large 3131580 ns/iter (± 1660751) 2921585 ns/iter (± 1535739) 1.07
es/codegen/with-parser/colors 45695 ns/iter (± 564) 45841 ns/iter (± 247) 1.00
es/codegen/with-parser/large 486355 ns/iter (± 465) 489581 ns/iter (± 1235) 0.99
es/minify/libraries/antd 1155517245 ns/iter (± 11786068) 1215299752 ns/iter (± 16101705) 0.95
es/minify/libraries/d3 240191741 ns/iter (± 1212614) 247988974 ns/iter (± 2586652) 0.97
es/minify/libraries/echarts 908247370 ns/iter (± 7261820) 967126350 ns/iter (± 8797090) 0.94
es/minify/libraries/jquery 73587117 ns/iter (± 221630) 74557075 ns/iter (± 708785) 0.99
es/minify/libraries/lodash 86998479 ns/iter (± 189112) 87721832 ns/iter (± 1022407) 0.99
es/minify/libraries/moment 43926845 ns/iter (± 172605) 43907185 ns/iter (± 536621) 1.00
es/minify/libraries/react 16066985 ns/iter (± 37878) 16104816 ns/iter (± 163460) 1.00
es/minify/libraries/terser 187329328 ns/iter (± 735563) 199399970 ns/iter (± 7568027) 0.94
es/minify/libraries/three 324601882 ns/iter (± 2265375) 342478544 ns/iter (± 9190935) 0.95
es/minify/libraries/typescript 2266629193 ns/iter (± 14479573) 2350882006 ns/iter (± 29448434) 0.96
es/minify/libraries/victory 485456172 ns/iter (± 3587933) 513011922 ns/iter (± 10099992) 0.95
es/minify/libraries/vue 105833192 ns/iter (± 306694) 107687412 ns/iter (± 1071216) 0.98
es/visitor/compare/clone 1925217 ns/iter (± 16832) 1960530 ns/iter (± 5545) 0.98
es/visitor/compare/visit_mut_span 2258494 ns/iter (± 6421) 2276188 ns/iter (± 5274) 0.99
es/visitor/compare/visit_mut_span_panic 2297341 ns/iter (± 7111) 2343398 ns/iter (± 5013) 0.98
es/visitor/compare/fold_span 3341785 ns/iter (± 7182) 3393473 ns/iter (± 9930) 0.98
es/visitor/compare/fold_span_panic 3468447 ns/iter (± 5700) 3478588 ns/iter (± 6366) 1.00
es/lexer/colors 13278 ns/iter (± 13) 13112 ns/iter (± 87) 1.01
es/lexer/angular 6203702 ns/iter (± 6761) 6028722 ns/iter (± 5704) 1.03
es/lexer/backbone 814852 ns/iter (± 354) 779541 ns/iter (± 253) 1.05
es/lexer/jquery 4599562 ns/iter (± 2894) 4459106 ns/iter (± 29346) 1.03
es/lexer/jquery mobile 6989156 ns/iter (± 4622) 6741439 ns/iter (± 6109) 1.04
es/lexer/mootools 3641033 ns/iter (± 4595) 3523563 ns/iter (± 1770) 1.03
es/lexer/underscore 683532 ns/iter (± 1176) 651332 ns/iter (± 434) 1.05
es/lexer/three 21738472 ns/iter (± 12666) 21095507 ns/iter (± 26693) 1.03
es/lexer/yui 3915541 ns/iter (± 3083) 3787994 ns/iter (± 2451) 1.03
es/parser/colors 27577 ns/iter (± 86) 27979 ns/iter (± 42) 0.99
es/parser/angular 13661005 ns/iter (± 94059) 13752924 ns/iter (± 154861) 0.99
es/parser/backbone 2000657 ns/iter (± 12256) 2038968 ns/iter (± 9564) 0.98
es/parser/jquery 10909670 ns/iter (± 30587) 11114495 ns/iter (± 78808) 0.98
es/parser/jquery mobile 16811189 ns/iter (± 105356) 17146582 ns/iter (± 222873) 0.98
es/parser/mootools 8457333 ns/iter (± 18883) 8496962 ns/iter (± 20776) 1.00
es/parser/underscore 1737595 ns/iter (± 9694) 1753233 ns/iter (± 11034) 0.99
es/parser/three 47138420 ns/iter (± 309971) 49388817 ns/iter (± 568681) 0.95
es/parser/yui 8330409 ns/iter (± 41206) 8451262 ns/iter (± 57848) 0.99
es/preset-env/usage/builtin_type 138274 ns/iter (± 32723) 138812 ns/iter (± 32867) 1.00
es/preset-env/usage/property 17342 ns/iter (± 59) 16548 ns/iter (± 112) 1.05
es/resolver/typescript 90385077 ns/iter (± 1603073) 89792400 ns/iter (± 1171744) 1.01
es/fixer/typescript 63793962 ns/iter (± 858217) 64538358 ns/iter (± 824428) 0.99
es/hygiene/typescript 130698523 ns/iter (± 661157) 132207326 ns/iter (± 1564435) 0.99
es/resolver_with_hygiene/typescript 246524916 ns/iter (± 955185) 245374895 ns/iter (± 3011469) 1.00
es/visitor/base-perf/module_clone 60079 ns/iter (± 712) 60324 ns/iter (± 399) 1.00
es/visitor/base-perf/fold_empty 64106 ns/iter (± 383) 64326 ns/iter (± 236) 1.00
es/visitor/base-perf/fold_noop_impl_all 64778 ns/iter (± 309) 64692 ns/iter (± 343) 1.00
es/visitor/base-perf/fold_noop_impl_vec 64424 ns/iter (± 170) 65449 ns/iter (± 373) 0.98
es/visitor/base-perf/boxing_boxed_clone 57 ns/iter (± 0) 57 ns/iter (± 0) 1
es/visitor/base-perf/boxing_unboxed_clone 38 ns/iter (± 0) 39 ns/iter (± 0) 0.97
es/visitor/base-perf/boxing_boxed 108 ns/iter (± 0) 105 ns/iter (± 0) 1.03
es/visitor/base-perf/boxing_unboxed 77 ns/iter (± 0) 74 ns/iter (± 0) 1.04
es/visitor/base-perf/visit_empty 0 ns/iter (± 0) 0 ns/iter (± 0) NaN
es/visitor/base-perf/visit_contains_this 2625 ns/iter (± 14) 2651 ns/iter (± 11) 0.99
es/base/parallel/resolver/typescript 3866067982 ns/iter (± 279749497) 3831258785 ns/iter (± 204382904) 1.01
es/base/parallel/hygiene/typescript 1452187751 ns/iter (± 16467754) 1453635239 ns/iter (± 13785203) 1.00
misc/visitors/time-complexity/time 5 137 ns/iter (± 0) 134 ns/iter (± 1) 1.02
misc/visitors/time-complexity/time 10 384 ns/iter (± 2) 397 ns/iter (± 8) 0.97
misc/visitors/time-complexity/time 15 675 ns/iter (± 16) 684 ns/iter (± 11) 0.99
misc/visitors/time-complexity/time 20 1047 ns/iter (± 51) 1073 ns/iter (± 6) 0.98
misc/visitors/time-complexity/time 40 3708 ns/iter (± 286) 3610 ns/iter (± 317) 1.03
misc/visitors/time-complexity/time 60 7456 ns/iter (± 88) 7268 ns/iter (± 6) 1.03
es/full-target/es2016 231697 ns/iter (± 843) 233935 ns/iter (± 739) 0.99
es/full-target/es2017 217660 ns/iter (± 575) 222378 ns/iter (± 982) 0.98
es/full-target/es2018 207197 ns/iter (± 349) 208854 ns/iter (± 691) 0.99
es2020_nullish_coalescing 69432 ns/iter (± 411) 70438 ns/iter (± 322) 0.99
es2020_optional_chaining 79033 ns/iter (± 389) 81871 ns/iter (± 191) 0.97
es2022_class_properties 112909 ns/iter (± 285) 114680 ns/iter (± 397) 0.98
es2018_object_rest_spread 73647 ns/iter (± 247) 75805 ns/iter (± 300) 0.97
es2019_optional_catch_binding 63541 ns/iter (± 315) 65557 ns/iter (± 224) 0.97
es2017_async_to_generator 63652 ns/iter (± 125) 63490 ns/iter (± 258) 1.00
es2016_exponentiation 67264 ns/iter (± 324) 68736 ns/iter (± 218) 0.98
es2015_arrow 70378 ns/iter (± 198) 71553 ns/iter (± 223) 0.98
es2015_block_scoped_fn 67297 ns/iter (± 190) 69008 ns/iter (± 334) 0.98
es2015_block_scoping 121747 ns/iter (± 352) 122495 ns/iter (± 356) 0.99

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.