-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add the Verify
mode
#726
Add the Verify
mode
#726
Conversation
Verify
modeVerify
mode design
75024f7
to
5dd00cf
Compare
crates/interpreter/src/valid.rs
Outdated
// expected_target.parser += delta_ip; | ||
// expected_target.branch_table += delta_stp; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The remaining question is how to format and read the side table from the custom section of the WASM module.
In terms of the format, how about using the format that was intended for flash storage?
It may not be efficient to keep the whole side table in RAM. How about keeping a parser for it and reading the data on demand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More precisely,
[Section ID: 0]
[Section Size: ...]
[Section Name Length: 18]
[Section Name: "Wasefire-SideTable"]
[Indices Array Size (LEB128): num_functions + 1]
[Indices Array: (u16 * (num_functions + 1))]
[Metadata Array Size (LEB128): ...]
[Metadata Array: (u16 * ...)]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In terms of the format, how about using the format that was intended for flash storage?
Yes, that's the idea, even if we didn't have a proper parsing function yet. That's the format I wrote there (updated below):
side-table := index flatten-metadata (16-bits aligned)
index := u16 u16 ... u16 (N + 1 times where N is the number of functions in the module)
flatten-metadata := metadata metadata ... metadata (N times where `flatten-metadata[i]` starts at byte position `index[i]` and ends at `index[i + 1]`)
metadata := type:u16 parser:(u32 u32) branch-table
branch-table := branch branch ... branch (length is implicitly defined by `index[i + 1]` see above)
branch := delta-ip:u16 delta-stp:u16 val-cnt:u8 pop-cnt:u12
In particular, we shouldn't use LEB128 since u16
is enough and the benefit from using only one byte up to 127 is not worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've pushed a commit to better factorize end_label
and br_label
. It's not finished because similarly to the ValidMode::Branches
, we also need ValidMode::BranchTable
, which is either prepared or verified. In particular it must be read from ValidMode::patch_branch()
for Verify
.
6e65644
to
cda46ed
Compare
crates/interpreter/src/valid.rs
Outdated
// metadata | ||
Err(Invalid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems I couldn't return a mutable reference to metadata
(local). (I had a design for returning by value.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's because Verify::BranchTable<'m>
shouldn't be Metadata<'m>
but some BranchTableView<'m>
that contains a Metadata<'m>
and a current branch index.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand (the returned reference must be part of Self::SideTable
) but I have a different solution. PTAL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I think it's getting there.
crates/interpreter/src/valid.rs
Outdated
// metadata | ||
Err(Invalid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's because Verify::BranchTable<'m>
shouldn't be Metadata<'m>
but some BranchTableView<'m>
that contains a Metadata<'m>
and a current branch index.
crates/interpreter/src/valid.rs
Outdated
@@ -928,7 +1053,7 @@ impl<'a, 'm, M: ValidMode> Expr<'a, 'm, M> { | |||
fn branch(&self) -> SideTableBranch<'m> { | |||
SideTableBranch { | |||
parser: self.parser.save(), | |||
branch_table: self.branch_table.save(), | |||
branch_table: self.branch_table.as_ref().map_or(0, |x| x.next_index()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't work to unwrap? I would expect branch
to be only called outside const context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it could be None
. I guess it is because branch_target()
is called for Verify
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's because of the End instruction for consts. I'm fixing it in the review commit.
type Branches<'m> = Vec<SideTableBranch<'m>>; | ||
type BranchTable<'m> = Vec<BranchTableEntry>; | ||
type SideTable<'m> = Vec<MetadataEntry>; | ||
type Result = Vec<MetadataEntry>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could probably have this be Vec<u8>
ultimately (and represent the content of the custom section).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we convert it in merge()
in zhouwfang#8? Please also take a look at the design in that PR. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we could do it in merge too. Ideally this would be an opaque type to the user. Something called SideTable
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! We can do the rest in followup PRs.
pub struct SideTableView<'m> { | ||
pub func_idx: usize, | ||
pub indices: &'m [u16], // including 0 and the length of metadata_array | ||
pub metadata: &'m [u16], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should change those to u8
. We can't guarantee those will be aligned in flash. This could be done in another PR though. Let's add a TODO.
} | ||
|
||
fn parse_side_table_field<'m>(parser: &mut crate::valid::Parser<'m>) -> Result<&'m [u16], Error> { | ||
let len = parse_u16(parser.save()) as usize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't parse like WASM bytecode. The format can simply be #726 (comment). This assumes we know the number of functions, which we can cheaply get from the length of the function section. We could decide to store it in the side table though, but we only need this number. We don't need 2 lengths for each slice, and we don't need them to be in bytes since we know the size of the elements.
impl<'m> SideTable<'m> { | ||
fn metadata(&self, func_idx: usize) -> Metadata<'m> { | ||
impl<'m> SideTableView<'m> { | ||
pub fn new(parser: &mut crate::valid::Parser<'m>) -> Result<Self, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't take a parser as argument. See other comment. We should just take the binary data and the number of functions. We could simplify by not taking the number of functions and storing it in the binary data as the first field (u16 should be enough).
crates/interpreter/src/valid.rs
Outdated
fn stitch_branch( | ||
&mut self, source: SideTableBranch<'m>, target: SideTableBranch<'m>, | ||
) -> CheckResult; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: let's also pack those declarations by removing the empty lines
type Branches<'m> = Vec<SideTableBranch<'m>>; | ||
type BranchTable<'m> = Vec<BranchTableEntry>; | ||
type SideTable<'m> = Vec<MetadataEntry>; | ||
type Result = Vec<MetadataEntry>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we could do it in merge too. Ideally this would be an opaque type to the user. Something called SideTable
.
crates/interpreter/src/valid.rs
Outdated
side_table.func_idx += 1; | ||
check( | ||
side_table.branch_table_view.type_idx() == type_idx | ||
&& side_table.branch_table_view.parser_range() == parser_range, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: let's have 2 checks instead of a conjunction (simpler to read and more precise panic in debug mode)
crates/interpreter/src/valid.rs
Outdated
@@ -928,7 +1053,7 @@ impl<'a, 'm, M: ValidMode> Expr<'a, 'm, M> { | |||
fn branch(&self) -> SideTableBranch<'m> { | |||
SideTableBranch { | |||
parser: self.parser.save(), | |||
branch_table: self.branch_table.save(), | |||
branch_table: self.branch_table.as_ref().map_or(0, |x| x.next_index()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's because of the End instruction for consts. I'm fixing it in the review commit.
Ok(source) | ||
} | ||
|
||
fn allocate_branch(&mut self) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should do something here and below.
#46