-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Wasm executor should provide stubs for unknown externs (wasmi) #4550
Conversation
|
It looks like @cecton signed our Contributor License Agreement. 👍 Many thanks, Parity Technologies CLA Bot |
client/executor/wasmi/src/lib.rs
Outdated
| .map_err(wasmi::Trap::from) | ||
| .map(|v| v.map(Into::into)) | ||
| } else if self.enable_stub { | ||
| panic!("function {} does not exist", self.method); |
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.
There can be more than 1 function that does not exist.
And please return an Err
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.
If I return an Err it doesn't panic anymore and therefore it breaks my test. Does the test should panic?
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.
Done (now it unwrap() and catch the panic)
client/executor/wasmi/src/lib.rs
Outdated
| .map(|v| v.map(Into::into)) | ||
| } else if self.enable_stub { | ||
| Err(Error::from( | ||
| format!("functions do not exist: {}", self.missing_functions.join(", ")) |
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.
Please only print the actual function that was tried to be called (by using the unique index generated in resolve).
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.
If I don't print all the not existing functions, why am I gathering them in a Vec? This implementation here was printing the function that was tried: e19948e
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.
Because you only want to know which function exactly was called. It does not helps us to know that 50 functions are not provided ^^
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.
Ok so after discussion it finally 💡 in my mind. It's the name of the missing export we need, not the name of the function in the module. Will fix this
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.
done
client/executor/wasmi/src/lib.rs
Outdated
| })?; | ||
| call_in_wasm_module(ext, &self.instance, method, data, &self.host_functions) | ||
| call_in_wasm_module( | ||
| ext, &self.instance, method, data, &self.host_functions, self.enable_stub, |
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.
Please put each parameter it its own line.
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.
done
client/executor/wasmi/src/lib.rs
Outdated
| call_in_wasm_module(ext, &self.instance, method, data, &self.host_functions) | ||
| call_in_wasm_module( | ||
| ext, &self.instance, method, data, &self.host_functions, self.enable_stub, | ||
| &self.missing_functions) |
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.
) needs to go to a new line.
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.
done
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
client/executor/wasmi/src/lib.rs
Outdated
| /// The host functions registered for this instance. | ||
| host_functions: Vec<&'static dyn Function>, | ||
| /// Enable STUB for function called that are missing | ||
| enable_stub: bool, |
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.
Instead of enable_stub I'd like to suggest to use something like allow_missing_imports. The rationale is that in the wasm spec a missing import is specified an instantiation error, so allow_missing_imports would convey that this is a custom mode. enable_stub is on contrary a little bit vague since there might be different kinds of stubs out there.
Aside, expanding the role of this field in the doc would be great!
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.
Fine by me. @bkchr any remark?
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 like @pepyakin idea :) Sounds much better!
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.
done
a9caa1f to
79f4a2a
Compare
| ext, | ||
| code, | ||
| heap_pages, | ||
| false, |
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.
Won't the other tests fails because of missing imports? :D
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.
done (but I think wasmtime is failing at instantiation because of the missing function. I will fix that)
| &test_code[..], | ||
| 8, | ||
| ); | ||
| assert!(output.is_err()); |
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.
Please check for the exact error you expect. Otherwise it could happen that the error type returned changes and the test still finishes successfully.
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.
Done but I removed the test entirely as we test only with stub enabled
client/executor/wasmi/src/lib.rs
Outdated
| if self.enable_stub { | ||
| trace!("Could not find function {}, a stub will be provided instead.", name); | ||
| let id = self.missing_function_id.borrow().clone(); | ||
| self.missing_functions.borrow_mut().insert(id, name.to_string()); |
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 actually just require missing_functions to be a Vec.
The index for the function will be computed as:
self.host_functions.len() + self.missing_functions.len()
(before adding the new missing function name!)
And in invoke we do the following
if index >= host_functions.len() {
Err("{} not found whatever", self.missing_functions[index - host_functions.len())
}
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 that's what I implemented before as you can see here: 2333994
But I told you this looks way too clever and I should probably use a hashmap and you said you would have use a hashmap.
I don't mind reverting it but I'm not in favor of this because I find that it doesn't look like it brings performance improvement, maybe memory, but it certainly make the code harder to understand.
Now that I shared my humble opinion. What do you prefer? 😁
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.
Yeah, I wanted to use a hashmap because I did not thought about this solution 😅
It clearly will improve the performance, as we just need to access the memory by index and not need to look into a hashmap. Please revert, but also make sure that invoke does not tries to use an invalid 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.
done
|
This is ready to be merged. I don't know why that test failed but it doesn't seem related to my changes. |
| } | ||
| } | ||
|
|
||
| struct MissingExternalFunction; |
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.
You only need one of these structs. Just put the name into the struct as parameter.
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.
done
Co-Authored-By: Bastian Köcher <[email protected]>
bkchr
left a comment
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.
Last round and than we are good to go.
client/executor/wasmi/src/lib.rs
Outdated
|
|
||
| let mut fec = FunctionExecutor::new(memory.clone(), heap_base, table, host_functions)?; | ||
| let mut fec = FunctionExecutor::new( | ||
| memory.clone(), heap_base, table, host_functions, allow_missing_imports, missing_functions)?; |
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.
Please put every parameter on its own line.
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.
done
client/executor/wasmi/src/lib.rs
Outdated
| // Instantiate this module. | ||
| let instance = instantiate_module(heap_pages as usize, &module, &host_functions) | ||
| let (instance, missing_functions) = instantiate_module( | ||
| heap_pages as usize, &module, &host_functions, allow_missing_imports) |
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.
Each parameter on its own line.
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.
done
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
Co-Authored-By: Bastian Köcher <[email protected]>
This is part of the implementation for #4456, only for wasmi
(Let me squash merge so I can put a proper commit message)