From 35dcc132a9302f697e2c1d1d620c295ba053e608 Mon Sep 17 00:00:00 2001 From: Ameer Hamza Date: Thu, 27 Jun 2024 11:48:08 +0500 Subject: [PATCH 1/2] fix:initial fix added using frame_size --- clar2wasm/src/wasm_generator.rs | 6 ++--- clar2wasm/src/words/sequences.rs | 44 +++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/clar2wasm/src/wasm_generator.rs b/clar2wasm/src/wasm_generator.rs index 29132964..42354da2 100644 --- a/clar2wasm/src/wasm_generator.rs +++ b/clar2wasm/src/wasm_generator.rs @@ -55,7 +55,7 @@ pub struct WasmGenerator { /// The locals for the current function. pub(crate) bindings: HashMap>, /// Size of the current function's stack frame. - frame_size: i32, + pub(crate) frame_size: u32, } #[derive(Hash, Eq, PartialEq)] @@ -261,7 +261,7 @@ impl WasmGenerator { .next() .ok_or_else(|| GeneratorError::InternalError("No Memory found".to_owned()))?; - let total_memory_bytes = self.literal_memory_end + (self.frame_size as u32); + let total_memory_bytes = self.literal_memory_end + self.frame_size; let pages_required = total_memory_bytes / (64 * 1024); let remainder = total_memory_bytes % (64 * 1024); @@ -773,7 +773,7 @@ impl WasmGenerator { // [ new_stack_ptr ] .global_set(self.stack_pointer); // [ ] - self.frame_size += size; + self.frame_size += size as u32; (offset, size) } diff --git a/clar2wasm/src/words/sequences.rs b/clar2wasm/src/words/sequences.rs index 95147cdf..63fddcc9 100644 --- a/clar2wasm/src/words/sequences.rs +++ b/clar2wasm/src/words/sequences.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeSet; + use clarity::vm::clarity_wasm::get_type_size; use clarity::vm::types::{ FunctionType, ListTypeData, SequenceSubtype, StringSubtype, TypeSignature, @@ -551,12 +553,13 @@ impl ComplexWord for Map { let mut input_offsets = vec![]; let mut input_element_types = vec![]; let mut input_element_sizes = vec![]; + let mut input_element_lengths = BTreeSet::new(); let mut input_num_elements = vec![]; for arg in args.iter().skip(1) { // get the type of the seq, and the sizes. - let (element_ty, element_size) = match generator + let (element_ty, element_size, element_length) = match generator .get_expr_type(arg) .ok_or_else(|| { GeneratorError::TypeError("sequence expression must be typed".to_owned()) @@ -565,16 +568,21 @@ impl ComplexWord for Map { { TypeSignature::SequenceType(SequenceSubtype::ListType(lt)) => { let element_ty = lt.get_list_item_type().clone(); + let max_length = lt.get_max_len(); let element_size = get_type_size(&element_ty); - (SequenceElementType::Other(element_ty), element_size) + ( + SequenceElementType::Other(element_ty), + element_size, + max_length, + ) } - TypeSignature::SequenceType(SequenceSubtype::BufferType(_)) + TypeSignature::SequenceType(SequenceSubtype::BufferType(length)) | TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::ASCII( - _, - ))) => (SequenceElementType::Byte, 1), + length, + ))) => (SequenceElementType::Byte, 1, length.into()), TypeSignature::SequenceType(SequenceSubtype::StringType(StringSubtype::UTF8( - _, - ))) => (SequenceElementType::UnicodeScalar, 4), + length, + ))) => (SequenceElementType::UnicodeScalar, 4, length.into()), _ => { return Err(GeneratorError::TypeError( "expected sequence type".to_string(), @@ -583,6 +591,7 @@ impl ComplexWord for Map { }; input_element_types.push(element_ty); input_element_sizes.push(element_size); + input_element_lengths.insert(element_length); generator.traverse_expr(builder, arg)?; // [ offset, length ] @@ -727,6 +736,14 @@ impl ComplexWord for Map { generator.visit_call_user_defined(&mut loop_, return_element_type, fname)?; } + let total_elements = if let Some(first) = input_element_lengths.iter().next() { + *first + } else { + 0 + }; + + generator.frame_size += return_element_size as u32 * total_elements; + // Write the result to the output sequence. generator.write_to_memory(&mut loop_, output_offset, 0, return_element_type)?; @@ -1533,6 +1550,7 @@ impl ComplexWord for Slice { #[cfg(test)] mod tests { + use clarity::vm::types::{ListData, ListTypeData, SequenceData, TypeSignature}; use clarity::vm::Value; use crate::tools::{crosscheck, evaluate}; @@ -1981,6 +1999,18 @@ mod tests { crosscheck("(map - (list 10 20 30))", evaluate("(list -10 -20 -30)")); } + #[test] + fn multiple_maps() { + let snippet = "(map + (list 1 2 3) (list 1 2 3) (list 1 2 3))".repeat(700); + + let expected = Value::Sequence(SequenceData::List(ListData { + data: vec![Value::Int(3), Value::Int(6), Value::Int(9)], + type_signature: ListTypeData::new_list(TypeSignature::IntType, 3).unwrap(), + })); + + crosscheck(&snippet, Ok(Some(expected))); + } + #[test] fn slice_right_lt_left() { crosscheck("(slice? \"abc\" u1 u0)", evaluate("none")); From 4a9b8350e48e74d32c7681d6ea833b6f477a1446 Mon Sep 17 00:00:00 2001 From: Ameer Hamza Date: Thu, 27 Jun 2024 18:17:18 +0500 Subject: [PATCH 2/2] refactor: replace BTreeSet with var --- clar2wasm/src/words/sequences.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/clar2wasm/src/words/sequences.rs b/clar2wasm/src/words/sequences.rs index 63fddcc9..dd2174c2 100644 --- a/clar2wasm/src/words/sequences.rs +++ b/clar2wasm/src/words/sequences.rs @@ -1,5 +1,3 @@ -use std::collections::BTreeSet; - use clarity::vm::clarity_wasm::get_type_size; use clarity::vm::types::{ FunctionType, ListTypeData, SequenceSubtype, StringSubtype, TypeSignature, @@ -553,7 +551,7 @@ impl ComplexWord for Map { let mut input_offsets = vec![]; let mut input_element_types = vec![]; let mut input_element_sizes = vec![]; - let mut input_element_lengths = BTreeSet::new(); + let mut smallest_sequence_length = u32::MAX; let mut input_num_elements = vec![]; for arg in args.iter().skip(1) { @@ -591,7 +589,10 @@ impl ComplexWord for Map { }; input_element_types.push(element_ty); input_element_sizes.push(element_size); - input_element_lengths.insert(element_length); + + if element_length < smallest_sequence_length { + smallest_sequence_length = element_length; + } generator.traverse_expr(builder, arg)?; // [ offset, length ] @@ -736,13 +737,13 @@ impl ComplexWord for Map { generator.visit_call_user_defined(&mut loop_, return_element_type, fname)?; } - let total_elements = if let Some(first) = input_element_lengths.iter().next() { - *first - } else { + smallest_sequence_length = if smallest_sequence_length == u32::MAX { 0 + } else { + smallest_sequence_length }; - generator.frame_size += return_element_size as u32 * total_elements; + generator.frame_size += return_element_size as u32 * smallest_sequence_length; // Write the result to the output sequence. generator.write_to_memory(&mut loop_, output_offset, 0, return_element_type)?; @@ -2001,7 +2002,7 @@ mod tests { #[test] fn multiple_maps() { - let snippet = "(map + (list 1 2 3) (list 1 2 3) (list 1 2 3))".repeat(700); + let snippet = "(map + (list 1 2 3) (list 1 2 3 4) (list 1 2 3 4 5))".repeat(700); let expected = Value::Sequence(SequenceData::List(ListData { data: vec![Value::Int(3), Value::Int(6), Value::Int(9)],