summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Mohammad Pur <mpfard@serenityos.org>2021-07-17 01:04:37 +0430
committerGitHub <noreply@github.com>2021-07-17 01:04:37 +0430
commit35394dbfaa23b44a293da85b20a63a10f73572c3 (patch)
tree152449f3fa61c4b32d70c6fb12896b32429aada2
parent3099a6bf2add35ac6a0c7ce4cbb6c794d6269d19 (diff)
downloadserenity-35394dbfaa23b44a293da85b20a63a10f73572c3.zip
LibWasm: Some more performance stuff (#8812)
* wasm: Don't try to print the function results if it traps * LibWasm: Inline some very hot functions These are mostly pretty small functions too, and they were about ~10% of runtime. * LibWasm+Everywhere: Make the instruction count limit configurable ...and enable it for LibWeb and test-wasm. Note that `wasm` will not be limited by this. * LibWasm: Remove a useless use of ScopeGuard There are no multiple exit paths in that function, so we can just put the ending logic right at the end of the function instead.
-rw-r--r--Tests/LibWasm/test-wasm.cpp1
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp10
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h13
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp27
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.h2
-rw-r--r--Userland/Libraries/LibWasm/AbstractMachine/Configuration.h4
-rw-r--r--Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp1
-rw-r--r--Userland/Utilities/wasm.cpp18
8 files changed, 49 insertions, 27 deletions
diff --git a/Tests/LibWasm/test-wasm.cpp b/Tests/LibWasm/test-wasm.cpp
index 2cb6abe619..d0b16d7d70 100644
--- a/Tests/LibWasm/test-wasm.cpp
+++ b/Tests/LibWasm/test-wasm.cpp
@@ -34,6 +34,7 @@ public:
explicit WebAssemblyModule(JS::Object& prototype)
: JS::Object(prototype)
{
+ m_machine.enable_instruction_count_limit();
}
static Wasm::AbstractMachine& machine() { return m_machine; }
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
index 07a81d7fe9..d923987bdc 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.cpp
@@ -128,6 +128,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
module.for_each_section_of_type<GlobalSection>([&](auto& global_section) {
for (auto& entry : global_section.entries()) {
Configuration config { m_store };
+ if (m_should_limit_instruction_count)
+ config.enable_instruction_count_limit();
config.set_frame(Frame {
auxiliary_instance,
Vector<Value> {},
@@ -153,6 +155,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
Vector<Reference> references;
for (auto& entry : segment.init) {
Configuration config { m_store };
+ if (m_should_limit_instruction_count)
+ config.enable_instruction_count_limit();
config.set_frame(Frame {
main_module_instance,
Vector<Value> {},
@@ -204,6 +208,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
return IterationDecision::Break;
}
Configuration config { m_store };
+ if (m_should_limit_instruction_count)
+ config.enable_instruction_count_limit();
config.set_frame(Frame {
main_module_instance,
Vector<Value> {},
@@ -262,6 +268,8 @@ InstantiationResult AbstractMachine::instantiate(Module const& module, Vector<Ex
segment.value().visit(
[&](DataSection::Data::Active const& data) {
Configuration config { m_store };
+ if (m_should_limit_instruction_count)
+ config.enable_instruction_count_limit();
config.set_frame(Frame {
main_module_instance,
Vector<Value> {},
@@ -439,6 +447,8 @@ Result AbstractMachine::invoke(FunctionAddress address, Vector<Value> arguments)
Result AbstractMachine::invoke(Interpreter& interpreter, FunctionAddress address, Vector<Value> arguments)
{
Configuration configuration { m_store };
+ if (m_should_limit_instruction_count)
+ configuration.enable_instruction_count_limit();
return configuration.call(interpreter, address, move(arguments));
}
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
index 29d3c414b8..659a3bae78 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
+++ b/Userland/Libraries/LibWasm/AbstractMachine/AbstractMachine.h
@@ -130,26 +130,26 @@ public:
}
}
- Value(Value const& value)
+ ALWAYS_INLINE Value(Value const& value)
: m_value(AnyValueType { value.m_value })
, m_type(value.m_type)
{
}
- Value(Value&& value)
+ ALWAYS_INLINE Value(Value&& value)
: m_value(move(value.m_value))
, m_type(move(value.m_type))
{
}
- Value& operator=(Value&& value)
+ ALWAYS_INLINE Value& operator=(Value&& value)
{
m_value = move(value.m_value);
m_type = move(value.m_type);
return *this;
}
- Value& operator=(Value const& value)
+ ALWAYS_INLINE Value& operator=(Value const& value)
{
m_value = value.m_value;
m_type = value.m_type;
@@ -157,7 +157,7 @@ public:
}
template<typename T>
- Optional<T> to()
+ ALWAYS_INLINE Optional<T> to()
{
Optional<T> result;
m_value.visit(
@@ -505,10 +505,13 @@ public:
auto& store() const { return m_store; }
auto& store() { return m_store; }
+ void enable_instruction_count_limit() { m_should_limit_instruction_count = true; }
+
private:
Optional<InstantiationError> allocate_all_initial_phase(Module const&, ModuleInstance&, Vector<ExternValue>&, Vector<Value>& global_values);
Optional<InstantiationError> allocate_all_final_phase(Module const&, ModuleInstance&, Vector<Vector<Reference>>& elements);
Store m_store;
+ bool m_should_limit_instruction_count { false };
};
class Linker {
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp b/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp
index 06a87b010d..dedde43160 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp
+++ b/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.cpp
@@ -37,12 +37,15 @@ void BytecodeInterpreter::interpret(Configuration& configuration)
auto& instructions = configuration.frame().expression().instructions();
auto max_ip_value = InstructionPointer { instructions.size() };
auto& current_ip_value = configuration.ip();
+ auto const should_limit_instruction_count = configuration.should_limit_instruction_count();
u64 executed_instructions = 0;
while (current_ip_value < max_ip_value) {
- if (executed_instructions++ >= Constants::max_allowed_executed_instructions_per_call) [[unlikely]] {
- m_trap = Trap { "Exceeded maximum allowed number of instructions" };
- return;
+ if (should_limit_instruction_count) {
+ if (executed_instructions++ >= Constants::max_allowed_executed_instructions_per_call) [[unlikely]] {
+ m_trap = Trap { "Exceeded maximum allowed number of instructions" };
+ return;
+ }
}
auto& instruction = instructions[current_ip_value.value()];
auto old_ip = current_ip_value;
@@ -1123,17 +1126,15 @@ void DebuggerBytecodeInterpreter::interpret(Configuration& configuration, Instru
}
}
- ScopeGuard guard { [&] {
- if (post_interpret_hook) {
- auto result = post_interpret_hook(configuration, ip, instruction, *this);
- if (!result) {
- m_trap = Trap { "Trapped by user request" };
- return;
- }
- }
- } };
-
BytecodeInterpreter::interpret(configuration, ip, instruction);
+
+ if (post_interpret_hook) {
+ auto result = post_interpret_hook(configuration, ip, instruction, *this);
+ if (!result) {
+ m_trap = Trap { "Trapped by user request" };
+ return;
+ }
+ }
}
}
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.h b/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.h
index 41d2caacdb..fc4bcb5c04 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.h
+++ b/Userland/Libraries/LibWasm/AbstractMachine/BytecodeInterpreter.h
@@ -50,7 +50,7 @@ protected:
T read_value(ReadonlyBytes data);
Vector<Value> pop_values(Configuration& configuration, size_t count);
- bool trap_if_not(bool value, StringView reason)
+ ALWAYS_INLINE bool trap_if_not(bool value, StringView reason)
{
if (!value)
m_trap = Trap { reason };
diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h
index 04cef62746..580ad526e5 100644
--- a/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h
+++ b/Userland/Libraries/LibWasm/AbstractMachine/Configuration.h
@@ -61,6 +61,9 @@ public:
Result call(Interpreter&, FunctionAddress, Vector<Value> arguments);
Result execute(Interpreter&);
+ void enable_instruction_count_limit() { m_should_limit_instruction_count = true; }
+ bool should_limit_instruction_count() const { return m_should_limit_instruction_count; }
+
void dump_stack();
private:
@@ -69,6 +72,7 @@ private:
Stack m_stack;
size_t m_depth { 0 };
InstructionPointer m_ip;
+ bool m_should_limit_instruction_count { false };
};
}
diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp
index 96654696eb..d383994ad1 100644
--- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp
+++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp
@@ -25,6 +25,7 @@ namespace Web::Bindings {
WebAssemblyObject::WebAssemblyObject(JS::GlobalObject& global_object)
: Object(*global_object.object_prototype())
{
+ s_abstract_machine.enable_instruction_count_limit();
}
void WebAssemblyObject::initialize(JS::GlobalObject& global_object)
diff --git a/Userland/Utilities/wasm.cpp b/Userland/Utilities/wasm.cpp
index 008bb2b273..3229aefb4b 100644
--- a/Userland/Utilities/wasm.cpp
+++ b/Userland/Utilities/wasm.cpp
@@ -512,14 +512,16 @@ int main(int argc, char* argv[])
if (debug)
launch_repl();
- if (result.is_trap())
- warnln("Execution trapped!");
- if (!result.values().is_empty())
- warnln("Returned:");
- for (auto& value : result.values()) {
- Wasm::Printer printer { stream };
- g_stdout.write(" -> "sv.bytes());
- g_printer.print(value);
+ if (result.is_trap()) {
+ warnln("Execution trapped: {}", result.trap().reason);
+ } else {
+ if (!result.values().is_empty())
+ warnln("Returned:");
+ for (auto& value : result.values()) {
+ Wasm::Printer printer { stream };
+ g_stdout.write(" -> "sv.bytes());
+ g_printer.print(value);
+ }
}
}
}