@@ -42,31 +42,24 @@ impl ValueStack {
4242 self . top
4343 }
4444
45- #[ inline]
46- pub ( crate ) fn _truncate ( & mut self , n : usize ) {
47- assert ! ( self . top <= self . stack. len( ) ) ;
48- self . top -= n;
49- self . stack . truncate ( self . top ) ;
50- }
51-
52- #[ inline]
53- // example: [1, 2, 3] n=1, end_keep=1 => [1, 3]
54- // example: [1] n=1, end_keep=1 => [1]
5545 pub ( crate ) fn truncate_keep ( & mut self , n : usize , end_keep : usize ) {
56- if n == end_keep || n == 0 {
57- return ;
46+ let total_to_keep = n + end_keep;
47+ assert ! (
48+ self . top >= total_to_keep,
49+ "Total to keep should be less than or equal to self.top"
50+ ) ;
51+
52+ let current_size = self . stack . len ( ) ;
53+ if current_size <= total_to_keep {
54+ return ; // No need to truncate if the current size is already less than or equal to total_to_keep
5855 }
5956
60- assert ! ( self . top <= self . stack. len( ) ) ;
61- info ! ( "removing from {} to {}" , self . top - n, self . top - end_keep) ;
62- self . stack . drain ( self . top - n..self . top - end_keep) ;
63- self . top -= n - end_keep;
64- }
57+ let items_to_remove = current_size - total_to_keep;
58+ let remove_start_index = self . top - items_to_remove - end_keep;
59+ let remove_end_index = self . top - end_keep;
6560
66- #[ inline]
67- pub ( crate ) fn _extend ( & mut self , values : impl IntoIterator < Item = RawWasmValue > + ExactSizeIterator ) {
68- self . top += values. len ( ) ;
69- self . stack . extend ( values) ;
61+ self . stack . drain ( remove_start_index..remove_end_index) ;
62+ self . top = total_to_keep; // Update top to reflect the new size
7063 }
7164
7265 #[ inline]
@@ -92,6 +85,21 @@ impl ValueStack {
9285 self . stack . pop ( ) . ok_or ( Error :: StackUnderflow )
9386 }
9487
88+ pub ( crate ) fn break_to ( & mut self , new_stack_size : usize , result_count : usize ) {
89+ self . stack
90+ . copy_within ( ( self . top - result_count) ..self . top , new_stack_size) ;
91+ self . top = new_stack_size + result_count;
92+ self . stack . truncate ( self . top ) ;
93+ }
94+
95+ #[ inline]
96+ pub ( crate ) fn last_n ( & self , n : usize ) -> Result < & [ RawWasmValue ] > {
97+ if self . top < n {
98+ return Err ( Error :: StackUnderflow ) ;
99+ }
100+ Ok ( & self . stack [ self . top - n..self . top ] )
101+ }
102+
95103 #[ inline]
96104 pub ( crate ) fn pop_n ( & mut self , n : usize ) -> Result < Vec < RawWasmValue > > {
97105 if self . top < n {
@@ -120,39 +128,6 @@ impl ValueStack {
120128#[ cfg( test) ]
121129mod tests {
122130 use super :: * ;
123- use crate :: std:: panic;
124-
125- fn crate_stack < T : Into < RawWasmValue > + Copy > ( data : & [ T ] ) -> ValueStack {
126- let mut stack = ValueStack :: default ( ) ;
127- stack. _extend ( data. iter ( ) . map ( |v| ( * v) . into ( ) ) ) ;
128- stack
129- }
130-
131- fn assert_truncate_keep < T : Into < RawWasmValue > + Copy > ( data : & [ T ] , n : usize , end_keep : usize , expected : & [ T ] ) {
132- let mut stack = crate_stack ( data) ;
133- stack. truncate_keep ( n, end_keep) ;
134- assert_eq ! (
135- stack. data( ) ,
136- expected. iter( ) . map( |v| ( * v) . into( ) ) . collect:: <Vec <_>>( ) . as_slice( )
137- ) ;
138- }
139-
140- fn catch_unwind_silent < F : FnOnce ( ) -> R + panic:: UnwindSafe , R > ( f : F ) -> crate :: std:: thread:: Result < R > {
141- let prev_hook = panic:: take_hook ( ) ;
142- panic:: set_hook ( alloc:: boxed:: Box :: new ( |_| { } ) ) ;
143- let result = panic:: catch_unwind ( f) ;
144- panic:: set_hook ( prev_hook) ;
145- result
146- }
147-
148- #[ test]
149- fn test_truncate_keep ( ) {
150- assert_truncate_keep ( & [ 1 , 2 , 3 ] , 1 , 1 , & [ 1 , 2 , 3 ] ) ;
151- assert_truncate_keep ( & [ 1 ] , 1 , 1 , & [ 1 ] ) ;
152- assert_truncate_keep ( & [ 1 , 2 , 3 ] , 2 , 1 , & [ 1 , 3 ] ) ;
153- assert_truncate_keep :: < i32 > ( & [ ] , 0 , 0 , & [ ] ) ;
154- catch_unwind_silent ( || assert_truncate_keep ( & [ 1 , 2 , 3 ] , 4 , 1 , & [ 1 , 3 ] ) ) . expect_err ( "should panic" ) ;
155- }
156131
157132 #[ test]
158133 fn test_value_stack ( ) {
0 commit comments