Skip to content

Commit 62f7022

Browse files
committed
improve method selection on contracts
1 parent d614ca1 commit 62f7022

File tree

7 files changed

+250
-94
lines changed

7 files changed

+250
-94
lines changed

sway-core/src/semantic_analysis/ast_node/declaration/auto_impl/abi_encoding.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use crate::{
99
Engines, TypeInfo, TypeParameter,
1010
};
1111
use std::collections::BTreeMap;
12+
use hashbrown::HashMap;
13+
use itertools::{join, Itertools};
1214
use sway_error::{
1315
error::CompileError,
1416
handler::{ErrorEmitted, Handler},
@@ -312,15 +314,16 @@ where
312314
fallback_fn: Option<DeclId<TyFunctionDecl>>,
313315
handler: &Handler,
314316
) -> Result<TyAstNode, ErrorEmitted> {
315-
let mut code = String::new();
316-
317317
let mut reads = false;
318318
let mut writes = false;
319319

320320
// used to check for name collisions
321321
let mut contract_methods: BTreeMap<String, Vec<Span>> = <_>::default();
322322

323+
let mut arm_by_size = BTreeMap::<usize, String>::default();
324+
323325
// generate code
326+
let mut method_names = String::new();
324327
for r in contract_fns {
325328
let decl = engines.de().get(r);
326329

@@ -382,8 +385,20 @@ where
382385
};
383386

384387
let method_name = decl.name.as_str();
388+
let offset = if let Some(offset) = method_names.find(method_name) {
389+
offset
390+
} else {
391+
let offset = method_names.len();
392+
method_names.push_str(method_name);
393+
offset
394+
};
395+
396+
let method_name_len = method_name.len();
397+
let code = arm_by_size.entry(method_name.len()).or_default();
385398

386-
code.push_str(&format!("if _method_name == \"{method_name}\" {{\n"));
399+
code.push_str(&format!("
400+
let is_this_method = asm(r, ptr: _method_name_ptr, name: _method_names_ptr, len: {method_name_len}) {{ addi r name i{offset}; meq r ptr r len; r: bool }};
401+
if is_this_method {{\n"));
387402

388403
if args_types == "()" {
389404
code.push_str(&format!(
@@ -454,10 +469,18 @@ where
454469
(false, false) => "",
455470
};
456471

472+
let code = arm_by_size.iter().map(|(len, code)| {
473+
format!("if _method_len == {len} {{ {code} }}")
474+
}).join("");
457475
let code = format!(
458476
"{att} pub fn __entry() {{
477+
let _method_names = \"{method_names}\";
459478
let mut _buffer = BufferReader::from_second_parameter();
460-
let _method_name = decode_first_param::<str>();
479+
480+
let mut _first_param_buffer = BufferReader::from_first_parameter();
481+
let _method_len = _first_param_buffer.read::<u64>();
482+
let _method_name_ptr = _first_param_buffer.ptr();
483+
let _method_names_ptr = _method_names.as_ptr();
461484
{code}
462485
{fallback}
463486
}}"

sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl ty::TyMatchExpression {
112112
let typed_if_exp =
113113
handler.scope(
114114
|handler| match &*ctx.engines().te().get(self.value_type_id) {
115-
TypeInfo::StringSlice => self.desugar_to_radix_trie(ctx),
115+
//TypeInfo::StringSlice => self.desugar_to_radix_trie(ctx),
116116
_ => self.desugar_to_typed_if_expression(instantiate, ctx, handler),
117117
},
118118
)?;

sway-ir/src/parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,7 @@ mod ir_builder {
12611261
},
12621262
)
12631263
.collect();
1264-
let md_idx = meta_idx.map(|mdi| self.md_map.get(&mdi).unwrap()).copied();
1264+
let md_idx = meta_idx.and_then(|mdi| self.md_map.get(&mdi)).copied();
12651265
let return_type = return_type.to_ir_type(context);
12661266
block
12671267
.append(context)

sway-lib-std/src/codec.sw

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ impl BufferReader {
156156
{
157157
T::abi_decode(self)
158158
}
159+
160+
pub fn ptr(self) -> raw_ptr {
161+
self.ptr
162+
}
159163
}
160164

161165
// Encode
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
cmds = [
2+
"forc build --path {root}",
3+
"forc build --path {root} --ir final --asm final | filter-fn {name} return_match_on_str_slice"
4+
]
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
---
2+
source: test/src/snapshot/mod.rs
3+
---
4+
> forc build --path test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_all
5+
exit status: 0
6+
output:
7+
Building test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_all
8+
Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-assert)
9+
Compiling script match_expressions_all (test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_all)
10+
let packed_string = "get_a_b"
11+
if str.len() == 5
12+
if str[0..4] == "get_" at packed_string[0]
13+
if str[4..5] == "b" at packed_string[6]
14+
return branch 2
15+
if str[4..5] == "a" at packed_string[4]
16+
return branch 0
17+
return wildcard branch
18+
return wildcard branch
19+
if str.len() == 7
20+
if str[0..7] == "get_a_b" at packed_string[0]
21+
return branch 1
22+
return wildcard branch
23+
return wildcard branch
24+
let packed_string = "get_a_b"
25+
if str.len() == 5
26+
if str[0..4] == "get_" at packed_string[0]
27+
if str[4..5] == "b" at packed_string[6]
28+
return branch 2
29+
if str[4..5] == "a" at packed_string[4]
30+
return branch 0
31+
return wildcard branch
32+
return wildcard branch
33+
if str.len() == 7
34+
if str[0..7] == "get_a_b" at packed_string[0]
35+
return branch 1
36+
return wildcard branch
37+
return wildcard branch
38+
Finished debug [unoptimized + fuel] target(s) [2.736 KB] in ???
39+
40+
> forc build --path test/src/e2e_vm_tests/test_programs/should_pass/language/match_expressions_all --ir final --asm final | filter-fn match_expressions_all return_match_on_str_slice
41+
42+
pshl i15 ; save registers 16..40
43+
pshh i524288 ; save registers 40..64
44+
move $$locbase $sp ; save locals base register for function return_match_on_str_slice_8
45+
cfei i144 ; allocate 144 bytes for locals and 0 slots for call arguments
46+
move $r3 $$reta ; save return address
47+
addi $r0 $$locbase i128 ; get offset to local __ptr slice
48+
mcpi $r0 $$arg0 i16 ; copy memory
49+
movi $r1 i7 ; initialize constant into register
50+
lw $r0 $$locbase i17
51+
eq $r0 $r0 $r1
52+
jnzf $r0 $zero i55
53+
movi $r1 i5 ; initialize constant into register
54+
lw $r0 $$locbase i17
55+
eq $r0 $r0 $r1
56+
movi $r1 i1000 ; initialize constant into register
57+
jnzf $r0 $zero i1
58+
jmpf $zero i48
59+
addr $r0 data_NonConfigurable_9; get __const_global0's address in data section
60+
addi $r1 $$locbase i32 ; get offset to local __ptr { ptr, u64 }
61+
sw $$locbase $r0 i4 ; store word
62+
movi $r0 i7 ; initialize constant into register
63+
sw $$locbase $r0 i5 ; store word
64+
addi $r0 $$locbase i48 ; get offset to local __ptr slice
65+
mcpi $r0 $r1 i16 ; copy memory
66+
movi $r2 i4 ; initialize constant into register
67+
lw $r0 $$locbase i16
68+
addi $r0 $r0 i0
69+
lw $r1 $$locbase i6
70+
addi $r1 $r1 i0
71+
meq $r0 $r0 $r1 $r2
72+
movi $r1 i1000 ; initialize constant into register
73+
jnzf $r0 $zero i1
74+
jmpf $zero i31
75+
addr $r0 data_NonConfigurable_9; get __const_global1's address in data section
76+
addi $r1 $$locbase i64 ; get offset to local __ptr { ptr, u64 }
77+
sw $$locbase $r0 i8 ; store word
78+
movi $r0 i7 ; initialize constant into register
79+
sw $$locbase $r0 i9 ; store word
80+
addi $r0 $$locbase i80 ; get offset to local __ptr slice
81+
mcpi $r0 $r1 i16 ; copy memory
82+
lw $r0 $$locbase i16
83+
addi $r0 $r0 i4
84+
lw $r1 $$locbase i10
85+
addi $r1 $r1 i4
86+
meq $r0 $r0 $r1 $one
87+
move $r1 $one ; move parameter from branch to block argument
88+
jnzf $r0 $zero i16
89+
addr $r0 data_NonConfigurable_9; get __const_global2's address in data section
90+
addi $r1 $$locbase i96 ; get offset to local __ptr { ptr, u64 }
91+
sw $$locbase $r0 i12 ; store word
92+
movi $r0 i7 ; initialize constant into register
93+
sw $$locbase $r0 i13 ; store word
94+
addi $r0 $$locbase i112 ; get offset to local __ptr slice
95+
mcpi $r0 $r1 i16 ; copy memory
96+
lw $r0 $$locbase i16
97+
addi $r0 $r0 i4
98+
lw $r1 $$locbase i14
99+
addi $r1 $r1 i6
100+
meq $r0 $r0 $r1 $one
101+
movi $r1 i3 ; initialize constant into register
102+
jnzf $r0 $zero i1
103+
movi $r1 i1000 ; initialize constant into register
104+
jmpf $zero i16
105+
addr $r0 data_NonConfigurable_9; get __const_global's address in data section
106+
sw $$locbase $r0 i0 ; store word
107+
movi $r0 i7 ; initialize constant into register
108+
sw $$locbase $r0 i1 ; store word
109+
addi $r0 $$locbase i16 ; get offset to local __ptr slice
110+
mcpi $r0 $$locbase i16 ; copy memory
111+
movi $r2 i7 ; initialize constant into register
112+
lw $r0 $$locbase i16
113+
addi $r0 $r0 i0
114+
lw $r1 $$locbase i2
115+
addi $r1 $r1 i0
116+
meq $r0 $r0 $r1 $r2
117+
movi $r1 i2 ; initialize constant into register
118+
jnzf $r0 $zero i1
119+
movi $r1 i1000 ; initialize constant into register
120+
move $$retv $r1 ; set return value
121+
cfsi i144 ; free 144 bytes for locals and 0 slots for extra call arguments
122+
move $$reta $r3 ; restore return address
123+
poph i524288 ; restore registers 40..64
124+
popl i15 ; restore registers 16..40
125+
jal $zero $$reta i0 ; return from call

0 commit comments

Comments
 (0)