Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: wasmx/fizzy
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 61cab4b1755447d14eb1659754023d199c2fe856
Choose a base ref
..
head repository: wasmx/fizzy
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1e311904a48b143cd8c4d42326bd96181828a0c4
Choose a head ref
Showing with 318 additions and 178 deletions.
  1. +15 −1 circle.yml
  2. +2 −2 cmake/cable.cmake
  3. +1 −0 lib/fizzy/CMakeLists.txt
  4. +5 −16 lib/fizzy/execute.cpp
  5. +1 −0 lib/fizzy/execute.hpp
  6. +66 −0 lib/fizzy/module.hpp
  7. +3 −4 lib/fizzy/parser.cpp
  8. +5 −5 lib/fizzy/parser.hpp
  9. +4 −4 lib/fizzy/parser_expr.cpp
  10. +0 −35 lib/fizzy/types.hpp
  11. +5 −14 test/bench/bench.cpp
  12. +0 −6 test/benchmarks/ecpairing.inputs
  13. BIN test/spectests/smoketest-failures/failures.0.wasm
  14. BIN test/spectests/smoketest-failures/failures.1.wasm
  15. BIN test/spectests/smoketest-failures/failures.10.wasm
  16. BIN test/spectests/smoketest-failures/failures.11.wasm
  17. BIN test/spectests/smoketest-failures/failures.12.wasm
  18. BIN test/spectests/smoketest-failures/failures.13.wasm
  19. BIN test/spectests/smoketest-failures/failures.14.wasm
  20. BIN test/spectests/smoketest-failures/failures.2.wasm
  21. BIN test/spectests/smoketest-failures/failures.3.wasm
  22. BIN test/spectests/smoketest-failures/failures.4.wasm
  23. BIN test/spectests/smoketest-failures/failures.5.wasm
  24. 0 test/spectests/smoketest-failures/failures.6.wasm
  25. BIN test/spectests/smoketest-failures/failures.7.wasm
  26. BIN test/spectests/smoketest-failures/failures.8.wasm
  27. 0 test/spectests/smoketest-failures/failures.9.wasm
  28. +26 −0 test/spectests/smoketest-failures/failures.json
  29. +53 −0 test/spectests/smoketest-failures/failures.wast
  30. BIN test/spectests/smoketest/smoketest.0.wasm
  31. BIN test/spectests/smoketest/smoketest.10.wasm
  32. BIN test/spectests/smoketest/smoketest.11.wasm
  33. BIN test/spectests/smoketest/smoketest.12.wasm
  34. 0 test/spectests/smoketest/smoketest.13.wat
  35. 0 test/spectests/smoketest/smoketest.14.wat
  36. BIN test/spectests/smoketest/smoketest.5.wasm
  37. BIN test/spectests/smoketest/smoketest.6.wasm
  38. BIN test/spectests/smoketest/smoketest.7.wasm
  39. BIN test/spectests/smoketest/smoketest.8.wasm
  40. BIN test/spectests/smoketest/smoketest.9.wasm
  41. +29 −18 test/spectests/smoketest/smoketest.json
  42. +34 −0 test/spectests/smoketest/smoketest.wast
  43. +2 −1 test/unittests/parser_expr_test.cpp
  44. +20 −26 test/unittests/wasm_engine_test.cpp
  45. +8 −12 test/utils/fizzy_engine.cpp
  46. +15 −15 test/utils/wabt_engine.cpp
  47. +18 −11 test/utils/wasm3_engine.cpp
  48. +6 −8 test/utils/wasm_engine.hpp
16 changes: 15 additions & 1 deletion circle.yml
Original file line number Diff line number Diff line change
@@ -66,10 +66,24 @@ commands:
name: "Test"
working_directory: ~/build
command: ctest -R ${TESTS_FILTER:-'.*'} -j4 --schedule-random --output-on-failure
- run:
name: "Run smoketest with fizzy-spectests --skip-validation"
working_directory: ~/build
environment:
LLVM_PROFILE_FILE: spectests-validation.profraw
command: bin/fizzy-spectests ~/project/test/spectests/smoketest --skip-validation
- run:
name: "Run smoketest with fizzy-spectests"
working_directory: ~/build
command: bin/fizzy-spectests --skip-validation ~/project/test/spectests/smoketest
environment:
LLVM_PROFILE_FILE: spectests-skipvalidation.profraw
command: bin/fizzy-spectests ~/project/test/spectests/smoketest
- run:
name: "Run smoketest failures with fizzy-spectests"
working_directory: ~/build
environment:
LLVM_PROFILE_FILE: spectests-failures.profraw
command: bin/fizzy-spectests ~/project/test/spectests/smoketest-failures || true

benchmark:
description: "Run benchmarks"
4 changes: 2 additions & 2 deletions cmake/cable.cmake
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/cmake -P
#!/usr/bin/env -S cmake -P

# Cable: CMake Bootstrap Library <https://github.com/ethereum/cable>
# Copyright 2019 Pawel Bylica.
# Copyright 2019-2020 Pawel Bylica.
# Licensed under the Apache License, Version 2.0.

# The cable command-line tool, version 1.0.0
1 change: 1 addition & 0 deletions lib/fizzy/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@ target_sources(
instructions.hpp
leb128.hpp
limits.hpp
module.hpp
parser.cpp
parser.hpp
parser_expr.cpp
21 changes: 5 additions & 16 deletions lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@

#include "execute.hpp"
#include "limits.hpp"
#include "module.hpp"
#include "stack.hpp"
#include "types.hpp"
#include <algorithm>
@@ -273,19 +274,6 @@ void branch(uint32_t label_idx, LabelStack& labels, Stack<uint64_t>& stack, cons
stack.resize(label.stack_height);
}

const FuncType& function_type(const Instance& instance, FuncIdx idx)
{
assert(idx < instance.imported_functions.size() + instance.module.funcsec.size());

if (idx < instance.imported_functions.size())
return instance.imported_functions[idx].type;

const auto type_idx = instance.module.funcsec[idx - instance.imported_functions.size()];
assert(type_idx < instance.module.typesec.size());

return instance.module.typesec[type_idx];
}

template <class F>
bool invoke_function(
const FuncType& func_type, const F& func, Instance& instance, Stack<uint64_t>& stack, int depth)
@@ -595,7 +583,8 @@ std::unique_ptr<Instance> instantiate(Module module,
return execute(instance_ref, idx, std::move(args), depth);
};

*it_table++ = ExternalFunction{std::move(func), function_type(*instance, idx)};
*it_table++ =
ExternalFunction{std::move(func), instance->module.get_function_type(idx)};
}
}

@@ -791,7 +780,7 @@ execution_result execute(
case Instr::call:
{
const auto called_func_idx = read<uint32_t>(immediates);
const auto& func_type = function_type(instance, called_func_idx);
const auto& func_type = instance.module.get_function_type(called_func_idx);

if (!invoke_function(func_type, called_func_idx, instance, stack, depth))
{
@@ -1581,7 +1570,7 @@ std::optional<ExternalFunction> find_exported_function(Instance& instance, std::
return execute(instance, idx, std::move(args), depth);
};

return ExternalFunction{std::move(func), function_type(instance, idx)};
return ExternalFunction{std::move(func), instance.module.get_function_type(idx)};
}

std::optional<ExternalGlobal> find_exported_global(Instance& instance, std::string_view name)
1 change: 1 addition & 0 deletions lib/fizzy/execute.hpp
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
#pragma once

#include "exceptions.hpp"
#include "module.hpp"
#include "types.hpp"
#include <cstdint>
#include <functional>
66 changes: 66 additions & 0 deletions lib/fizzy/module.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Fizzy: A fast WebAssembly interpreter
// Copyright 2020 The Fizzy Authors.
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "types.hpp"
#include <cassert>
#include <optional>
#include <vector>

namespace fizzy
{
struct Module
{
// https://webassembly.github.io/spec/core/binary/modules.html#type-section
std::vector<FuncType> typesec;
// https://webassembly.github.io/spec/core/binary/modules.html#import-section
std::vector<Import> importsec;
// https://webassembly.github.io/spec/core/binary/modules.html#function-section
std::vector<TypeIdx> funcsec;
// https://webassembly.github.io/spec/core/binary/modules.html#table-section
std::vector<Table> tablesec;
// https://webassembly.github.io/spec/core/binary/modules.html#memory-section
std::vector<Memory> memorysec;
// https://webassembly.github.io/spec/core/binary/modules.html#global-section
std::vector<Global> globalsec;
// https://webassembly.github.io/spec/core/binary/modules.html#export-section
std::vector<Export> exportsec;
// https://webassembly.github.io/spec/core/binary/modules.html#start-section
std::optional<FuncIdx> startfunc;
// https://webassembly.github.io/spec/core/binary/modules.html#element-section
std::vector<Element> elementsec;
// https://webassembly.github.io/spec/core/binary/modules.html#code-section
std::vector<Code> codesec;
// https://webassembly.github.io/spec/core/binary/modules.html#data-section
std::vector<Data> datasec;

// Types of functions defined in import section
std::vector<FuncType> imported_function_types;
// Types of tables defined in import section
std::vector<Table> imported_table_types;
// Types of memories defined in import section
std::vector<Memory> imported_memory_types;
// Mutability of globals defined in import section
std::vector<bool> imported_globals_mutability;

const FuncType& get_function_type(FuncIdx idx) const noexcept
{
assert(idx < imported_function_types.size() + funcsec.size());

if (idx < imported_function_types.size())
return imported_function_types[idx];

const auto type_idx = funcsec[idx - imported_function_types.size()];
assert(type_idx < typesec.size());

return typesec[type_idx];
}

bool has_memory() const noexcept
{
return !memorysec.empty() || !imported_memory_types.empty();
}
};
} // namespace fizzy
7 changes: 3 additions & 4 deletions lib/fizzy/parser.cpp
Original file line number Diff line number Diff line change
@@ -335,13 +335,13 @@ inline parser_result<code_view> parse(const uint8_t* pos, const uint8_t* end)
return {{code_begin, code_size}, code_end};
}

inline Code parse_code(code_view code_binary, bool have_memory)
inline Code parse_code(code_view code_binary, const Module& module)
{
const auto begin = code_binary.begin();
const auto end = code_binary.end();
const auto [locals_vec, pos1] = parse_vec<Locals>(begin, end);

auto [code, pos2] = parse_expr(pos1, end, have_memory);
auto [code, pos2] = parse_expr(pos1, end, module);

// Size is the total bytes of locals and expressions.
if (pos2 != end)
@@ -525,15 +525,14 @@ Module parse(bytes_view input)
if (module.startfunc && *module.startfunc >= total_func_count)
throw parser_error{"invalid start function index"};

const auto have_memory = !module.memorysec.empty() || !module.imported_memory_types.empty();
// Process code. TODO: This can be done lazily.
module.codesec.reserve(code_binaries.size());
for (size_t i = 0; i < code_binaries.size(); ++i)
{
const auto type_idx = module.funcsec[i];
if (type_idx >= module.typesec.size())
throw validation_error{"invalid function type index"};
module.codesec.emplace_back(parse_code(code_binaries[i], have_memory));
module.codesec.emplace_back(parse_code(code_binaries[i], module));
}

return module;
10 changes: 5 additions & 5 deletions lib/fizzy/parser.hpp
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@

#include "exceptions.hpp"
#include "leb128.hpp"
#include "types.hpp"
#include "module.hpp"
#include <tuple>

namespace fizzy
@@ -38,10 +38,10 @@ inline parser_result<uint8_t> parse_byte(const uint8_t* pos, const uint8_t* end)
/// Parse `expr`, i.e. a function's instructions residing in the code section.
/// https://webassembly.github.io/spec/core/binary/instructions.html#binary-expr
///
/// @param input The beginning of the expr binary input.
/// @param end The end of the binary input.
/// @param have_memory If the module (the context) contains imported or defined memory.
parser_result<Code> parse_expr(const uint8_t* input, const uint8_t* end, bool have_memory);
/// @param input The beginning of the expr binary input.
/// @param end The end of the binary input.
/// @param module Module that this code is part of.
parser_result<Code> parse_expr(const uint8_t* input, const uint8_t* end, const Module& module);

parser_result<std::string> parse_string(const uint8_t* pos, const uint8_t* end);

8 changes: 4 additions & 4 deletions lib/fizzy/parser_expr.cpp
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@ parser_result<uint8_t> parse_blocktype(const uint8_t* pos, const uint8_t* end)
}
} // namespace

parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, bool have_memory)
parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, const Module& module)
{
Code code;

@@ -102,7 +102,7 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, bool have
case Instr::f64_load:
case Instr::f32_store:
case Instr::f64_store:
if (!have_memory)
if (!module.has_memory())
throw validation_error{"memory instructions require imported or defined memory"};
// alignment
std::tie(std::ignore, pos) = leb128u_decode<uint32_t>(pos, end);
@@ -467,7 +467,7 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, bool have
std::tie(imm, pos) = leb128u_decode<uint32_t>(pos, end);
push(code.immediates, imm);

if (!have_memory)
if (!module.has_memory())
throw validation_error{"memory instructions require imported or defined memory"};
break;
}
@@ -481,7 +481,7 @@ parser_result<Code> parse_expr(const uint8_t* pos, const uint8_t* end, bool have
if (memory_idx != 0)
throw parser_error{"invalid memory index encountered"};

if (!have_memory)
if (!module.has_memory())
throw validation_error{"memory instructions require imported or defined memory"};
break;
}
35 changes: 0 additions & 35 deletions lib/fizzy/types.hpp
Original file line number Diff line number Diff line change
@@ -375,39 +375,4 @@ enum class SectionId : uint8_t
data = 11
};

struct Module
{
// https://webassembly.github.io/spec/core/binary/modules.html#type-section
std::vector<FuncType> typesec;
// https://webassembly.github.io/spec/core/binary/modules.html#import-section
std::vector<Import> importsec;
// https://webassembly.github.io/spec/core/binary/modules.html#function-section
std::vector<TypeIdx> funcsec;
// https://webassembly.github.io/spec/core/binary/modules.html#table-section
std::vector<Table> tablesec;
// https://webassembly.github.io/spec/core/binary/modules.html#memory-section
std::vector<Memory> memorysec;
// https://webassembly.github.io/spec/core/binary/modules.html#global-section
std::vector<Global> globalsec;
// https://webassembly.github.io/spec/core/binary/modules.html#export-section
std::vector<Export> exportsec;
// https://webassembly.github.io/spec/core/binary/modules.html#start-section
std::optional<FuncIdx> startfunc;
// https://webassembly.github.io/spec/core/binary/modules.html#element-section
std::vector<Element> elementsec;
// https://webassembly.github.io/spec/core/binary/modules.html#code-section
std::vector<Code> codesec;
// https://webassembly.github.io/spec/core/binary/modules.html#data-section
std::vector<Data> datasec;

// Types of functions defined in import section
std::vector<FuncType> imported_function_types;
// Types of tables defined in import section
std::vector<Table> imported_table_types;
// Types of memories defined in import section
std::vector<Memory> imported_memory_types;
// Mutability of globals defined in import section
std::vector<bool> imported_globals_mutability;
};

} // namespace fizzy
19 changes: 5 additions & 14 deletions test/bench/bench.cpp
Original file line number Diff line number Diff line change
@@ -67,16 +67,10 @@ void benchmark_instantiate(
{
const auto engine = create_fn();

if (!engine->parse(wasm_binary))
return state.SkipWithError("Parsing failed");

// Pre-run for validation
if (!engine->instantiate())
return state.SkipWithError("Instantiaton failed");

for ([[maybe_unused]] auto _ : state)
{
engine->instantiate();
if (!engine->instantiate(wasm_binary))
state.SkipWithError("Instantiation failed");
}
}

@@ -95,8 +89,8 @@ struct ExecutionBenchmarkCase
void validate_benchmark_case(benchmark::State& state, fizzy::test::WasmEngine& engine,
const ExecutionBenchmarkCase& benchmark_case)
{
if (!engine.parse(*benchmark_case.wasm_binary))
return state.SkipWithError("Parsing failed");
if (!engine.instantiate(*benchmark_case.wasm_binary))
return state.SkipWithError("Instantiation failed");

const auto func_ref = engine.find_function(benchmark_case.func_name);
if (!func_ref)
@@ -105,9 +99,6 @@ void validate_benchmark_case(benchmark::State& state, fizzy::test::WasmEngine& e
("Function \"" + benchmark_case.func_name + "\" not found").c_str());
}

if (!engine.instantiate())
return state.SkipWithError("Instantiation failed");

if (!benchmark_case.memory.empty())
{
if (!engine.init_memory(benchmark_case.memory))
@@ -148,12 +139,12 @@ void benchmark_execute(
validate_benchmark_case(state, *engine, benchmark_case);

const auto has_memory = !benchmark_case.memory.empty();
engine->instantiate(*benchmark_case.wasm_binary);
const auto func_ref = engine->find_function(benchmark_case.func_name);

for ([[maybe_unused]] auto _ : state)
{
state.PauseTiming();
engine->instantiate();
if (has_memory)
engine->init_memory(benchmark_case.memory);
state.ResumeTiming();
6 changes: 0 additions & 6 deletions test/benchmarks/ecpairing.inputs
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
empty
ecpairing_empty




onepoint
ecpairing_onepoint

Binary file added test/spectests/smoketest-failures/failures.0.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.1.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.10.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.11.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.12.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.13.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.14.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.2.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.3.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.4.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.5.wasm
Binary file not shown.
Empty file.
Binary file added test/spectests/smoketest-failures/failures.7.wasm
Binary file not shown.
Binary file added test/spectests/smoketest-failures/failures.8.wasm
Binary file not shown.
Empty file.
26 changes: 26 additions & 0 deletions test/spectests/smoketest-failures/failures.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{"source_filename": "failures.wast",
"commands": [
{"type": "assert_return", "line": 4, "action": {"type": "invoke", "field": "foo.i32", "args": []}, "expected": [{"type": "i32", "value": "2"}]},
{"type": "module", "line": 7, "filename": "failures.0.wasm"},
{"type": "module", "line": 10, "filename": "failures.1.wasm"},
{"type": "register", "line": 11, "as": "mod-empty"},
{"type": "module", "line": 12, "filename": "failures.2.wasm"},
{"type": "register", "line": 13, "as": "mod-empty"},
{"type": "module", "line": 16, "filename": "failures.3.wasm"},
{"type": "module", "line": 18, "filename": "failures.4.wasm"},
{"type": "assert_malformed", "line": 21, "filename": "failures.5.wasm", "text": "error", "module_type": "binary"},
{"type": "assert_invalid", "line": 23, "filename": "failures.6.wasm", "text": "error", "module_type": "binary"},
{"type": "assert_invalid", "line": 25, "filename": "failures.7.wasm", "text": "error", "module_type": "binary"},
{"type": "assert_unlinkable", "line": 27, "filename": "failures.8.wasm", "text": "error", "module_type": "binary"},
{"type": "assert_unlinkable", "line": 29, "filename": "failures.9.wasm", "text": "error", "module_type": "binary"},
{"type": "assert_unlinkable", "line": 32, "filename": "failures.10.wasm", "text": "error", "module_type": "binary"},
{"type": "assert_uninstantiable", "line": 35, "filename": "failures.11.wasm", "text": "error", "module_type": "binary"},
{"type": "assert_uninstantiable", "line": 36, "filename": "failures.12.wasm", "text": "error", "module_type": "binary"},
{"type": "assert_unlinkable", "line": 38, "filename": "failures.13.wasm", "text": "error", "module_type": "binary"},
{"type": "module", "line": 41, "filename": "failures.14.wasm"},
{"type": "assert_return", "line": 45, "action": {"type": "invoke", "field": "foo.i32", "args": []}, "expected": [{"type": "i32", "value": "2"}]},
{"type": "assert_return", "line": 46, "action": {"type": "invoke", "field": "trap", "args": []}, "expected": [{"type": "i32", "value": "2"}]},
{"type": "assert_return", "line": 47, "action": {"type": "invoke", "field": "foo.i32", "args": []}, "expected": []},
{"type": "assert_trap", "line": 48, "action": {"type": "invoke", "field": "foo.i32", "args": []}, "text": "error", "expected": [{"type": "i32"}]},
{"type": "assert_return", "line": 51, "action": {"type": "invoke", "field": "foo.unknown", "args": []}, "expected": [{"type": "i32", "value": "2"}]},
{"type": "assert_return", "line": 53, "action": {"type": "get", "field": "glob"}, "expected": [{"type": "i32", "value": "55"}]}]}
Loading