Skip to content

Commit

Permalink
Upgrade WAVM. (envoyproxy#220)
Browse files Browse the repository at this point in the history
Signed-off-by: John Plevyak <jplevyak@gmail.com>
  • Loading branch information
jplevyak authored Sep 28, 2019
1 parent 70f5927 commit 10bb731
Show file tree
Hide file tree
Showing 21 changed files with 50 additions and 47 deletions.
3 changes: 2 additions & 1 deletion bazel/foreign_cc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ envoy_cmake_external(
static_libraries = select({
"//conditions:default": [
"libWAVM.a",
"WAVM/libWAVMUnwind.a",
"libWAVMUnwind.a",
"libWAVMgdtoa.a",
],
}),
deps = [":llvm"],
Expand Down
6 changes: 3 additions & 3 deletions bazel/repository_locations.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ REPOSITORY_LOCATIONS = dict(
urls = ["http://releases.llvm.org/6.0.1/llvm-6.0.1.src.tar.xz"],
),
com_github_wavm_wavm = dict(
sha256 = "1acb11681657a0f32bb8c3d78117c742318c139d43eae70c6d34bbd9d9638135",
strip_prefix = "WAVM-95dbf08c8695b8941e7020c557d8612f9d2af895",
urls = ["https://github.com/WAVM/WAVM/archive/95dbf08c8695b8941e7020c557d8612f9d2af895.tar.gz"],
sha256 = "abebfba303958999ba82aa67075ea7ae1e38388632803d387c6aafbaf67f24c5",
strip_prefix = "WAVM-33f4240d44848c52a817730884572d3b4ae39733",
urls = ["https://github.com/WAVM/WAVM/archive/33f4240d44848c52a817730884572d3b4ae39733.tar.gz"],
),
com_googlesource_chromium_v8 = dict(
# This archive was created using https://storage.googleapis.com/envoyproxy-wee8/wee8-archive.sh
Expand Down
Binary file modified examples/wasm/envoy_filter_http_wasm_example.wasm
Binary file not shown.
8 changes: 1 addition & 7 deletions source/extensions/common/wasm/wavm/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@ envoy_cc_library(
srcs = ["wavm.cc"],
hdrs = ["wavm.h"],
copts = [
'-DEMSCRIPTEN_API=""',
'-DPLATFORM_API=""',
'-DRUNTIME_API=""',
'-DLOGGING_API=""',
'-DWASM_API=""',
'-DWASTPARSE_API=""',
'-DIR_API=""',
'-DWAVM_API=""',
"-Wno-non-virtual-dtor",
"-Wno-old-style-cast",
],
Expand Down
80 changes: 44 additions & 36 deletions source/extensions/common/wasm/wavm/wavm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
#include "WAVM/Inline/IndexMap.h"
#include "WAVM/Inline/IntrusiveSharedPtr.h"
#include "WAVM/Inline/Lock.h"
#include "WAVM/Inline/Serialization.h"
#include "WAVM/Platform/Mutex.h"
#include "WAVM/Platform/Thread.h"
#include "WAVM/Runtime/Intrinsics.h"
#include "WAVM/Runtime/Linker.h"
#include "WAVM/Runtime/Runtime.h"
#include "WAVM/Runtime/RuntimeData.h"
#include "WAVM/WASM/WASM.h"
#include "WAVM/WASTParse/WASTParse.h"
#include "absl/container/node_hash_map.h"
Expand Down Expand Up @@ -73,6 +73,7 @@ struct Wavm;
namespace {

struct WasmUntaggedValue : public WAVM::IR::UntaggedValue {
WasmUntaggedValue() = default;
WasmUntaggedValue(I32 inI32) { i32 = inI32; }
WasmUntaggedValue(I64 inI64) { i64 = inI64; }
WasmUntaggedValue(U32 inU32) { u32 = inU32; }
Expand All @@ -97,19 +98,6 @@ const Logger::Id wasmId = Logger::Id::wasm;
}); \
} while (0)

#define CALL_WITH_CONTEXT_RETURN(_x, _context, _T, _member) \
do { \
SaveRestoreContext _saved_context(static_cast<Context*>(_context)); \
_T _return_value; \
WAVM::Runtime::catchRuntimeExceptions([&] { _return_value = static_cast<_T>(_x[0]._member); }, \
[&](WAVM::Runtime::Exception* exception) { \
auto description = describeException(exception); \
destroyException(exception); \
throw WasmException(description); \
}); \
return _return_value; \
} while (0)

class RootResolver : public WAVM::Runtime::Resolver, public Logger::Loggable<wasmId> {
public:
RootResolver(WAVM::Runtime::Compartment*) {}
Expand Down Expand Up @@ -142,11 +130,16 @@ class RootResolver : public WAVM::Runtime::Resolver, public Logger::Loggable<was
throw WasmException(fmt::format(
"Failed to load WASM module due to a type mismatch in an import: {}.{} {}, "
"but was expecting type: {}",
module_name, export_name, asString(getObjectType(out_object)), asString(type)));
module_name, export_name, asString(WAVM::Runtime::getExternType(out_object)),
asString(type)));
}
}
}

for (auto r : resolvers_) {
if (r->resolve(module_name, export_name, type, out_object)) {
return true;
}
}
throw WasmException(fmt::format("Failed to load WASM module due to a missing import: {}.{} {}",
module_name, export_name, asString(type)));
}
Expand All @@ -155,8 +148,11 @@ class RootResolver : public WAVM::Runtime::Resolver, public Logger::Loggable<was
return module_name_to_instance_map_;
}

void addResolver(WAVM::Runtime::Resolver* r) { resolvers_.push_back(r); }

private:
HashMap<std::string, WAVM::Runtime::ModuleInstance*> module_name_to_instance_map_;
std::vector<WAVM::Runtime::Resolver*> resolvers_;
};

const uint64_t WasmPageSize = 1 << 16;
Expand All @@ -165,7 +161,8 @@ bool loadModule(const std::string& code, IR::Module& out_module) {
// If the code starts with the WASM binary magic number, load it as a binary IR::Module.
static const uint8_t WasmMagicNumber[4] = {0x00, 0x61, 0x73, 0x6d};
if (code.size() >= 4 && !memcmp(code.data(), WasmMagicNumber, 4)) {
return WASM::loadBinaryModule(code.data(), code.size(), out_module);
WAVM::Serialization::MemoryInputStream input(code.data(), code.size());
return WASM::loadBinaryModule(input, out_module);
} else {
// Load it as a text IR::Module.
std::vector<WAST::Error> parseErrors;
Expand Down Expand Up @@ -194,7 +191,7 @@ struct WavmGlobal : Global<T>,
WavmGlobalBase {
WavmGlobal(Common::Wasm::Wavm::Wavm* wavm, Intrinsics::Module& module, const std::string& name,
T value)
: Intrinsics::GenericGlobal<typename NativeWord<T>::type>(module, name.c_str(),
: Intrinsics::GenericGlobal<typename NativeWord<T>::type>(&module, name.c_str(),
ToNative(value)),
wavm_(wavm) {}
virtual ~WavmGlobal() {}
Expand All @@ -220,7 +217,8 @@ struct Wavm : public WasmVm {
bool cloneable() override { return true; };
std::unique_ptr<WasmVm> clone() override;
bool load(const std::string& code, bool allow_precompiled) override;
void setMemoryLayout(uint64_t, uint64_t, uint64_t) override {}
void setMemoryLayout(uint64_t stack_base, uint64_t heap_base,
uint64_t heap_base_pointer) override;
void link(absl::string_view debug_name, bool needs_emscripten) override;
void start(Context* context) override;
uint64_t getMemorySize() override;
Expand Down Expand Up @@ -263,7 +261,7 @@ struct Wavm : public WasmVm {
WAVM::Runtime::ModuleRef module_ = nullptr;
WAVM::Runtime::GCPointer<WAVM::Runtime::ModuleInstance> module_instance_;
WAVM::Runtime::Memory* memory_;
Emscripten::Instance* emscripten_instance_ = nullptr;
std::shared_ptr<Emscripten::Instance> emscripten_instance_;
WAVM::Runtime::GCPointer<WAVM::Runtime::Compartment> compartment_;
WAVM::Runtime::GCPointer<WAVM::Runtime::Context> context_;
absl::node_hash_map<std::string, Intrinsics::Module> intrinsic_modules_;
Expand All @@ -274,20 +272,18 @@ struct Wavm : public WasmVm {
std::unordered_map<std::pair<std::string, std::string>, WavmGlobalBase*, PairHash>
intrinsic_globals_;
uint8_t* memory_base_ = nullptr;
uint32_t memory_stack_base_;
uint32_t memory_heap_base_;
uint32_t memory_heap_base_pointer_;
};

Wavm::~Wavm() {
module_instance_ = nullptr;
if (emscripten_instance_) {
emscripten_instance_->env = nullptr;
emscripten_instance_->global = nullptr;
emscripten_instance_->memory = nullptr;
delete emscripten_instance_;
}
context_ = nullptr;
intrinsic_module_instances_.clear();
intrinsic_modules_.clear();
envoyFunctions_.clear();
emscripten_instance_ = nullptr;
if (compartment_) {
ASSERT(tryCollectCompartment(std::move(compartment_)));
}
Expand Down Expand Up @@ -335,17 +331,23 @@ bool Wavm::load(const std::string& code, bool allow_precompiled) {
return true;
}

void Wavm::setMemoryLayout(uint64_t stack_base, uint64_t heap_base, uint64_t heap_base_pointer) {
memory_stack_base_ = stack_base;
memory_heap_base_ = heap_base;
memory_heap_base_pointer_ = heap_base_pointer;
}

void Wavm::link(absl::string_view debug_name, bool needs_emscripten) {
RootResolver rootResolver(compartment_);
for (auto& p : intrinsic_modules_) {
auto instance = Intrinsics::instantiateModule(compartment_, intrinsic_modules_[p.first],
auto instance = Intrinsics::instantiateModule(compartment_, {&intrinsic_modules_[p.first]},
std::string(p.first));
intrinsic_module_instances_.emplace(p.first, instance);
rootResolver.moduleNameToInstanceMap().set(p.first, instance);
}
if (needs_emscripten) {
emscripten_instance_ = Emscripten::instantiate(compartment_, ir_module_);
rootResolver.moduleNameToInstanceMap().set("env", emscripten_instance_->env);
rootResolver.addResolver(&WAVM::Emscripten::getInstanceResolver(emscripten_instance_));
}
WAVM::Runtime::LinkResult link_result = linkModule(ir_module_, rootResolver);
module_instance_ = instantiateModule(
Expand Down Expand Up @@ -373,10 +375,13 @@ void Wavm::makeModule(absl::string_view name) {
}

void Wavm::start(Context* context) {
if (emscripten_instance_) {
setMemory(memory_heap_base_pointer_, sizeof(uint32_t), &memory_heap_base_);
}
try {
auto f = getStartFunction(module_instance_);
if (f) {
CALL_WITH_CONTEXT(invokeFunctionChecked(context_, f, {}), context);
CALL_WITH_CONTEXT(invokeFunction(context_, f, getFunctionType(f)), context);
}

if (emscripten_instance_) {
Expand All @@ -387,15 +392,15 @@ void Wavm::start(Context* context) {

f = asFunctionNullable(getInstanceExport(module_instance_, "__post_instantiate"));
if (f) {
CALL_WITH_CONTEXT(invokeFunctionChecked(context_, f, {}), context);
CALL_WITH_CONTEXT(invokeFunction(context_, f, getFunctionType(f)), context);
}

f = asFunctionNullable(getInstanceExport(module_instance_, "main"));
if (!f) {
f = asFunctionNullable(getInstanceExport(module_instance_, "_main"));
}
if (f) {
CALL_WITH_CONTEXT(invokeFunctionChecked(context_, f, {}), context);
CALL_WITH_CONTEXT(invokeFunction(context_, f, getFunctionType(f)), context);
}
} catch (const std::exception& e) {
std::cerr << "Caught exception \"" << e.what() << "\" in WASM\n";
Expand Down Expand Up @@ -477,7 +482,7 @@ void registerCallbackWavm(WasmVm* vm, absl::string_view module_name,
absl::string_view function_name, R (*f)(Args...)) {
auto wavm = static_cast<Common::Wasm::Wavm::Wavm*>(vm);
wavm->envoyFunctions_.emplace_back(new Intrinsics::Function(
wavm->intrinsic_modules_[module_name], function_name.data(), reinterpret_cast<void*>(f),
&wavm->intrinsic_modules_[module_name], function_name.data(), reinterpret_cast<void*>(f),
inferEnvoyFunctionType(f), IR::CallingConvention::intrinsic));
}

Expand Down Expand Up @@ -589,9 +594,12 @@ void getFunctionWavmReturn(WasmVm* vm, absl::string_view function_name,
}
*function = [wavm, f](Context* context, Args... args) -> R {
WasmUntaggedValue values[] = {args...};
WasmUntaggedValue return_value;
try {
CALL_WITH_CONTEXT_RETURN(invokeFunctionUnchecked(wavm->context_, f, &values[0]), context,
uint32_t, i32);
CALL_WITH_CONTEXT(
invokeFunction(wavm->context_, f, getFunctionType(f), &values[0], &return_value),
context);
return static_cast<uint32_t>(return_value.i32);
} catch (const std::exception& e) {
std::cerr << "Caught exception \"" << e.what() << "\" in WASM\n";
throw;
Expand Down Expand Up @@ -619,7 +627,7 @@ void getFunctionWavmReturn(WasmVm* vm, absl::string_view function_name,
*function = [wavm, f](Context* context, Args... args) -> R {
WasmUntaggedValue values[] = {args...};
try {
CALL_WITH_CONTEXT(invokeFunctionUnchecked(wavm->context_, f, &values[0]), context);
CALL_WITH_CONTEXT(invokeFunction(wavm->context_, f, getFunctionType(f), &values[0]), context);
} catch (const std::exception& e) {
std::cerr << "Caught exception \"" << e.what() << "\" in WASM\n";
throw;
Expand Down Expand Up @@ -724,7 +732,7 @@ template <typename T> void WavmGlobal<T>::set(const T& t) {
}

template <> void WavmGlobal<Word>::set(const Word& t) {
setGlobalValue(wavm_->context_, global_, IR::Value(t.u64_));
setGlobalValue(wavm_->context_, global_, IR::Value(t.u32()));
}

template <typename T>
Expand Down
Binary file modified test/extensions/access_loggers/wasm/test_data/logging.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/async_call_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/grpc_call_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/grpc_callout_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/headers_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/http_callout_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/metadata_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/queue_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/filters/http/wasm/test_data/shared_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/wasm/test_data/asm2wasm_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/wasm/test_data/bad_signature_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/wasm/test_data/emscripten_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/wasm/test_data/logging_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/wasm/test_data/missing_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/wasm/test_data/segv_cpp.wasm
Binary file not shown.
Binary file modified test/extensions/wasm/test_data/stats_cpp.wasm
Binary file not shown.

0 comments on commit 10bb731

Please sign in to comment.