Skip to content

Commit fb29638

Browse files
committed
Improve primitive upgrade check performance
1 parent 6a78acb commit fb29638

File tree

2 files changed

+158
-45
lines changed

2 files changed

+158
-45
lines changed

crates/dojo/core-cairo-test/src/tests/meta/introspect.cairo

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,11 @@ fn test_primitive_upgrade() {
411411
};
412412

413413
assert_eq!(
414-
Ty::Primitive(*dest).is_an_upgrade_of(@Ty::Primitive(*src)), expected,
414+
Ty::Primitive(*dest).is_an_upgrade_of(@Ty::Primitive(*src)),
415+
expected,
416+
"src: {} dest: {}",
417+
*src,
418+
*dest,
415419
);
416420
}
417421
},
@@ -586,15 +590,9 @@ fn test_array_upgrade() {
586590
}
587591

588592
#[test]
589-
#[available_gas(330000)]
593+
#[available_gas(259000)]
590594
fn test_primitive_upgrade_performance() {
591-
// the worst case should be an upgrade from ContractAddress to ClassHash,
592-
// as ContractAddress is the last source type and ClassHash the last dest type for
593-
// ContractAddress, in the table used by `is_an_upgrade_of`.
594-
let x = Ty::Primitive('ContractAddress');
595-
let upgraded = Ty::Primitive('ClassHash');
596-
597595
let gas = GasCounterTrait::start();
598-
let _ = upgraded.is_an_upgrade_of(@x);
599-
gas.end("ContractAddress to ClassHash");
596+
let _ = Ty::Primitive('ClassHash').is_an_upgrade_of(@Ty::Primitive('ContractAddress'));
597+
gas.end("Upgrade from ContractAddress to ClassHash");
600598
}

crates/dojo/core/src/meta/introspect.cairo

Lines changed: 150 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,151 @@
11
use dojo::meta::Layout;
22
use dojo::storage::packing;
33

4+
// Each index matches with a primitive types in both arrays (main and nested):
5+
// 'bool': 0
6+
// 'u8': 1
7+
// 'u16': 2
8+
// 'u32' / 'usize': 3
9+
// 'u64': 4
10+
// 'u128': 5
11+
// 'u256': 6
12+
// 'i8': 7
13+
// 'i16': 8
14+
// 'i32': 9
15+
// 'i64': 10
16+
// 'i128': 11
17+
// 'felt252': 12
18+
// 'ClassHash': 13
19+
// 'ContractAddress': 14
20+
const ALLOWED_PRIMITIVE_UPGRADES: [[bool; 15]; 15] = [
21+
// bool
22+
[
23+
false, false, false, false, false, false, false, false, false, false, false, false, false,
24+
false, false,
25+
],
26+
// u8
27+
[
28+
false, true, true, true, true, true, false, false, false, false, false, false, true, false,
29+
false,
30+
],
31+
// u16
32+
[
33+
false, false, true, true, true, true, false, false, false, false, false, false, true, false,
34+
false,
35+
],
36+
// u32
37+
[
38+
false, false, false, true, true, true, false, false, false, false, false, false, true,
39+
false, false,
40+
],
41+
// u64
42+
[
43+
false, false, false, false, true, true, false, false, false, false, false, false, true,
44+
false, false,
45+
],
46+
// u128
47+
[
48+
false, false, false, false, false, true, false, false, false, false, false, false, true,
49+
false, false,
50+
],
51+
// u256
52+
[
53+
false, false, false, false, false, false, true, false, false, false, false, false, false,
54+
false, false,
55+
],
56+
// i8
57+
[
58+
false, false, false, false, false, false, false, true, true, true, true, true, true, false,
59+
false,
60+
],
61+
// i16
62+
[
63+
false, false, false, false, false, false, false, false, true, true, true, true, true, false,
64+
false,
65+
],
66+
// i32
67+
[
68+
false, false, false, false, false, false, false, false, false, true, true, true, true,
69+
false, false,
70+
],
71+
// i64
72+
[
73+
false, false, false, false, false, false, false, false, false, false, true, true, true,
74+
false, false,
75+
],
76+
// i128
77+
[
78+
false, false, false, false, false, false, false, false, false, false, false, true, true,
79+
false, false,
80+
],
81+
// felt252
82+
[
83+
false, false, false, false, false, false, false, false, false, false, false, false, true,
84+
true, true,
85+
],
86+
// ClassHash
87+
[
88+
false, false, false, false, false, false, false, false, false, false, false, false, true,
89+
true, true,
90+
],
91+
// ContractAddress
92+
[
93+
false, false, false, false, false, false, false, false, false, false, false, false, true,
94+
true, true,
95+
],
96+
];
97+
98+
#[inline(always)]
99+
fn primitive_to_index(primitive: felt252) -> u32 {
100+
if primitive == 'bool' {
101+
return 0;
102+
}
103+
if primitive == 'u8' {
104+
return 1;
105+
}
106+
if primitive == 'u16' {
107+
return 2;
108+
}
109+
if primitive == 'u32' || primitive == 'usize' {
110+
return 3;
111+
}
112+
if primitive == 'u64' {
113+
return 4;
114+
}
115+
if primitive == 'u128' {
116+
return 5;
117+
}
118+
if primitive == 'u256' {
119+
return 6;
120+
}
121+
if primitive == 'i8' {
122+
return 7;
123+
}
124+
if primitive == 'i16' {
125+
return 8;
126+
}
127+
if primitive == 'i32' {
128+
return 9;
129+
}
130+
if primitive == 'i64' {
131+
return 10;
132+
}
133+
if primitive == 'i128' {
134+
return 11;
135+
}
136+
if primitive == 'felt252' {
137+
return 12;
138+
}
139+
if primitive == 'ClassHash' {
140+
return 13;
141+
}
142+
if primitive == 'ContractAddress' {
143+
return 14;
144+
}
145+
146+
return 0xFFFFFFFF;
147+
}
148+
4149
#[derive(Copy, Drop, Serde, Debug, PartialEq)]
5150
pub enum Ty {
6151
Primitive: felt252,
@@ -45,42 +190,12 @@ impl PrimitiveCompareImpl of TyCompareTrait<felt252> {
45190
return true;
46191
}
47192

48-
let mut allowed_upgrades: Span<(felt252, Span<felt252>)> = [
49-
('bool', [].span()), ('u8', ['u16', 'u32', 'usize', 'u64', 'u128', 'felt252'].span()),
50-
('u16', ['u32', 'usize', 'u64', 'u128', 'felt252'].span()),
51-
('u32', ['usize', 'u64', 'u128', 'felt252'].span()),
52-
('usize', ['u32', 'u64', 'u128', 'felt252'].span()),
53-
('u64', ['u128', 'felt252'].span()), ('u128', ['felt252'].span()), ('u256', [].span()),
54-
('i8', ['i16', 'i32', 'i64', 'i128', 'felt252'].span()),
55-
('i16', ['i32', 'i64', 'i128', 'felt252'].span()),
56-
('i32', ['i64', 'i128', 'felt252'].span()), ('i64', ['i128', 'felt252'].span()),
57-
('i128', ['felt252'].span()), ('felt252', ['ClassHash', 'ContractAddress'].span()),
58-
('ClassHash', ['felt252', 'ContractAddress'].span()),
59-
('ContractAddress', ['felt252', 'ClassHash'].span()),
60-
]
61-
.span();
193+
let new_index = primitive_to_index(*self);
194+
let old_index = primitive_to_index(*old);
62195

63-
loop {
64-
match allowed_upgrades.pop_front() {
65-
Option::Some((
66-
src, allowed,
67-
)) => {
68-
if src == old {
69-
let mut i = 0;
70-
break loop {
71-
if i >= (*allowed).len() {
72-
break false;
73-
}
74-
if (*allowed).at(i) == self {
75-
break true;
76-
}
77-
i += 1;
78-
};
79-
}
80-
},
81-
Option::None => { break false; },
82-
}
83-
}
196+
let allowed_upgrades = ALLOWED_PRIMITIVE_UPGRADES.span();
197+
let allowed_upgrades = allowed_upgrades[old_index].span();
198+
*allowed_upgrades[new_index]
84199
}
85200
}
86201

0 commit comments

Comments
 (0)