Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion bazel/external/wee8.genrule_cmd
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ WEE8_BUILD_ARGS+=" v8_use_external_startup_data=false"
WEE8_BUILD_ARGS+=" v8_enable_shared_ro_heap=false"

# Build wee8.
third_party/depot_tools/gn gen out/wee8 --args="$$WEE8_BUILD_ARGS"
if [[ `uname` == "Darwin" ]]; then
buildtools/mac/gn gen out/wee8 --args="$$WEE8_BUILD_ARGS"
else
buildtools/linux64/gn gen out/wee8 --args="$$WEE8_BUILD_ARGS"
Comment thread
jmarantz marked this conversation as resolved.
fi
third_party/depot_tools/ninja -C out/wee8 wee8

# Move compiled library to the expected destinations.
Expand Down
8 changes: 8 additions & 0 deletions source/extensions/common/wasm/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ envoy_cc_library(
],
)

envoy_cc_library(
name = "wasm_vm_base",
hdrs = ["wasm_vm_base.h"],
deps = [
"//source/common/stats:stats_lib",
],
)

envoy_cc_library(
name = "wasm_vm_lib",
srcs = ["wasm_vm.cc"],
Expand Down
1 change: 1 addition & 0 deletions source/extensions/common/wasm/null/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ envoy_cc_library(
"//external:abseil_node_hash_map",
"//include/envoy/registry",
"//source/common/common:assert_lib",
"//source/extensions/common/wasm:wasm_vm_base",
"//source/extensions/common/wasm:wasm_vm_interface",
"//source/extensions/common/wasm:well_known_names",
],
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/common/wasm/null/null.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace Common {
namespace Wasm {
namespace Null {

WasmVmPtr createVm() { return std::make_unique<NullVm>(); }
WasmVmPtr createVm(const Stats::ScopeSharedPtr& scope) { return std::make_unique<NullVm>(scope); }

} // namespace Null
} // namespace Wasm
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/common/wasm/null/null.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Common {
namespace Wasm {
namespace Null {

WasmVmPtr createVm();
WasmVmPtr createVm(const Stats::ScopeSharedPtr& scope);

} // namespace Null
} // namespace Wasm
Expand Down
10 changes: 6 additions & 4 deletions source/extensions/common/wasm/null/null_vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "common/common/assert.h"

#include "extensions/common/wasm/null/null_vm_plugin.h"
#include "extensions/common/wasm/wasm_vm_base.h"
#include "extensions/common/wasm/well_known_names.h"

namespace Envoy {
Expand All @@ -20,13 +21,14 @@ namespace Null {
// The NullVm wraps a C++ WASM plugin which has been compiled with the WASM API
// and linked directly into the Envoy process. This is useful for development
// in that it permits the debugger to set breakpoints in both Envoy and the plugin.
struct NullVm : public WasmVm {
NullVm() = default;
NullVm(const NullVm& other) : plugin_name_(other.plugin_name_) {}
struct NullVm : public WasmVmBase {
NullVm(const Stats::ScopeSharedPtr& scope) : WasmVmBase(scope, WasmRuntimeNames::get().Null) {}
NullVm(const NullVm& other)
: WasmVmBase(other.scope_, WasmRuntimeNames::get().Null), plugin_name_(other.plugin_name_) {}

// WasmVm
absl::string_view runtime() override { return WasmRuntimeNames::get().Null; }
bool cloneable() override { return true; };
Cloneable cloneable() override { return Cloneable::InstantiatedModule; };
WasmVmPtr clone() override;
bool load(const std::string& code, bool allow_precompiled) override;
void link(absl::string_view debug_name) override;
Expand Down
1 change: 1 addition & 0 deletions source/extensions/common/wasm/v8/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ envoy_cc_library(
],
deps = [
"//source/common/common:assert_lib",
"//source/extensions/common/wasm:wasm_vm_base",
"//source/extensions/common/wasm:wasm_vm_interface",
"//source/extensions/common/wasm:well_known_names",
],
Expand Down
31 changes: 23 additions & 8 deletions source/extensions/common/wasm/v8/v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "common/common/assert.h"

#include "extensions/common/wasm/wasm_vm_base.h"
#include "extensions/common/wasm/well_known_names.h"

#include "absl/container/flat_hash_map.h"
Expand Down Expand Up @@ -33,9 +34,9 @@ struct FuncData {

using FuncDataPtr = std::unique_ptr<FuncData>;

class V8 : public WasmVm {
class V8 : public WasmVmBase {
public:
V8() = default;
V8(const Stats::ScopeSharedPtr& scope) : WasmVmBase(scope, WasmRuntimeNames::get().V8) {}

// Extensions::Common::Wasm::WasmVm
absl::string_view runtime() override { return WasmRuntimeNames::get().V8; }
Expand All @@ -44,9 +45,8 @@ class V8 : public WasmVm {
absl::string_view getCustomSection(absl::string_view name) override;
void link(absl::string_view debug_name) override;

// V8 is currently not cloneable.
bool cloneable() override { return false; }
WasmVmPtr clone() override { return nullptr; }
Cloneable cloneable() override { return Cloneable::CompiledBytecode; }
WasmVmPtr clone() override;

uint64_t getMemorySize() override;
absl::optional<absl::string_view> getMemory(uint64_t pointer, uint64_t size) override;
Expand Down Expand Up @@ -89,6 +89,7 @@ class V8 : public WasmVm {
wasm::vec<byte_t> source_ = wasm::vec<byte_t>::invalid();
wasm::own<wasm::Store> store_;
wasm::own<wasm::Module> module_;
wasm::own<wasm::Shared<wasm::Module>> shared_module_;
wasm::own<wasm::Instance> instance_;
wasm::own<wasm::Memory> memory_;
wasm::own<wasm::Table> table_;
Expand Down Expand Up @@ -241,15 +242,30 @@ template <typename T, typename U> constexpr T convertValTypesToArgsTuple(const U
bool V8::load(const std::string& code, bool /* allow_precompiled */) {
ENVOY_LOG(trace, "load()");
store_ = wasm::Store::make(engine());
RELEASE_ASSERT(store_ != nullptr, "");

source_ = wasm::vec<byte_t>::make_uninitialized(code.size());
::memcpy(source_.get(), code.data(), code.size());

module_ = wasm::Module::make(store_.get(), source_);
if (module_) {
shared_module_ = module_->share();
}

return module_ != nullptr;
}

WasmVmPtr V8::clone() {
ENVOY_LOG(trace, "clone()");
ASSERT(shared_module_ != nullptr);

auto clone = std::make_unique<V8>(scope_);
clone->store_ = wasm::Store::make(engine());

clone->module_ = wasm::Module::obtain(clone->store_.get(), shared_module_.get());

return clone;
}

absl::string_view V8::getCustomSection(absl::string_view name) {
ENVOY_LOG(trace, "getCustomSection(\"{}\")", name);
ASSERT(source_.get() != nullptr);
Expand Down Expand Up @@ -356,7 +372,6 @@ void V8::link(absl::string_view debug_name) {
ASSERT(import_types.size() == imports.size());

instance_ = wasm::Instance::make(store_.get(), module_.get(), imports.data());
RELEASE_ASSERT(instance_ != nullptr, "");

const auto export_types = module_.get()->exports();
const auto exports = instance_.get()->exports();
Expand Down Expand Up @@ -562,7 +577,7 @@ void V8::getModuleFunctionImpl(absl::string_view function_name,
};
}

WasmVmPtr createVm() { return std::make_unique<V8>(); }
WasmVmPtr createVm(const Stats::ScopeSharedPtr& scope) { return std::make_unique<V8>(scope); }

} // namespace V8
} // namespace Wasm
Expand Down
2 changes: 1 addition & 1 deletion source/extensions/common/wasm/v8/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Common {
namespace Wasm {
namespace V8 {

WasmVmPtr createVm();
WasmVmPtr createVm(const Stats::ScopeSharedPtr& scope);

} // namespace V8
} // namespace Wasm
Expand Down
6 changes: 3 additions & 3 deletions source/extensions/common/wasm/wasm_vm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ namespace Wasm {
thread_local Envoy::Extensions::Common::Wasm::Context* current_context_ = nullptr;
thread_local uint32_t effective_context_id_ = 0;

WasmVmPtr createWasmVm(absl::string_view runtime) {
WasmVmPtr createWasmVm(absl::string_view runtime, const Stats::ScopeSharedPtr& scope) {
if (runtime.empty()) {
throw WasmVmException("Failed to create WASM VM with unspecified runtime.");
} else if (runtime == WasmRuntimeNames::get().Null) {
return Null::createVm();
return Null::createVm(scope);
} else if (runtime == WasmRuntimeNames::get().V8) {
return V8::createVm();
return V8::createVm(scope);
} else {
throw WasmVmException(fmt::format(
"Failed to create WASM VM using {} runtime. Envoy was compiled without support for it.",
Expand Down
22 changes: 15 additions & 7 deletions source/extensions/common/wasm/wasm_vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <memory>

#include "envoy/common/exception.h"
#include "envoy/stats/scope.h"

#include "common/common/logger.h"

Expand Down Expand Up @@ -98,8 +99,7 @@ template <size_t N> using WasmCallWord = std::function<WasmFuncType<N, Word, Con

#define FOR_ALL_WASM_VM_EXPORTS(_f) \
_f(WasmCallVoid<0>) _f(WasmCallVoid<1>) _f(WasmCallVoid<2>) _f(WasmCallVoid<3>) \
_f(WasmCallVoid<4>) _f(WasmCallVoid<5>) _f(WasmCallVoid<8>) _f(WasmCallWord<0>) \
_f(WasmCallWord<1>) _f(WasmCallWord<2>) _f(WasmCallWord<3>)
_f(WasmCallVoid<5>) _f(WasmCallWord<1>) _f(WasmCallWord<2>) _f(WasmCallWord<3>)

// Calls out of the WASM VM.
// 1st arg is always a pointer to raw_context (void*).
Expand All @@ -111,6 +111,7 @@ template <size_t N> using WasmCallbackWord = WasmFuncType<N, Word, void*, Word>*
// Extended with W = Word
// Z = void, j = uint32_t, l = int64_t, m = uint64_t
using WasmCallback_WWl = Word (*)(void*, Word, int64_t);
using WasmCallback_WWlWW = Word (*)(void*, Word, int64_t, Word, Word);
using WasmCallback_WWm = Word (*)(void*, Word, uint64_t);
using WasmCallback_dd = double (*)(void*, double);

Expand All @@ -119,8 +120,15 @@ using WasmCallback_dd = double (*)(void*, double);
_f(WasmCallbackVoid<4>) _f(WasmCallbackWord<0>) _f(WasmCallbackWord<1>) \
_f(WasmCallbackWord<2>) _f(WasmCallbackWord<3>) _f(WasmCallbackWord<4>) \
_f(WasmCallbackWord<5>) _f(WasmCallbackWord<6>) _f(WasmCallbackWord<7>) \
_f(WasmCallbackWord<8>) _f(WasmCallbackWord<9>) _f(WasmCallback_WWl) \
_f(WasmCallback_WWm) _f(WasmCallback_dd)
_f(WasmCallbackWord<8>) _f(WasmCallbackWord<9>) _f(WasmCallbackWord<10>) \
_f(WasmCallback_WWl) _f(WasmCallback_WWlWW) _f(WasmCallback_WWm) \
_f(WasmCallback_dd)

enum class Cloneable {
NotCloneable, // VMs can not be cloned and should be created from scratch.
CompiledBytecode, // VMs can be cloned with compiled bytecode.
InstantiatedModule // VMs can be cloned from an instantiated module.
};

// Wasm VM instance. Provides the low level WASM interface.
class WasmVm : public Logger::Loggable<Logger::Id::wasm> {
Expand All @@ -141,9 +149,9 @@ class WasmVm : public Logger::Loggable<Logger::Id::wasm> {
* compilation. Then, if cloning is supported, we clone that VM for each worker, potentially
* copying and sharing the initialized data structures for efficiency. Otherwise we create an new
* VM from scratch for each worker.
* @return true if the VM is cloneable.
* @return one of enum Cloneable with the VMs cloneability.
*/
virtual bool cloneable() PURE;
virtual Cloneable cloneable() PURE;
Comment thread
jmarantz marked this conversation as resolved.

/**
* Make a worker/thread-specific copy if supported by the underlying VM system (see cloneable()
Expand Down Expand Up @@ -287,7 +295,7 @@ struct SaveRestoreContext {
};

// Create a new low-level WASM VM using runtime of the given type (e.g. "envoy.wasm.runtime.wavm").
WasmVmPtr createWasmVm(absl::string_view runtime);
WasmVmPtr createWasmVm(absl::string_view runtime, const Stats::ScopeSharedPtr& scope);

} // namespace Wasm
} // namespace Common
Expand Down
55 changes: 55 additions & 0 deletions source/extensions/common/wasm/wasm_vm_base.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#pragma once

#include "envoy/stats/scope.h"
#include "envoy/stats/stats.h"
#include "envoy/stats/stats_macros.h"

#include "extensions/common/wasm/wasm_vm.h"

#include "absl/strings/str_cat.h"

namespace Envoy {
namespace Extensions {
namespace Common {
namespace Wasm {

/**
* Wasm host stats.
*/
#define ALL_VM_STATS(COUNTER, GAUGE) \
COUNTER(created) \
COUNTER(cloned) \
GAUGE(active, NeverImport)
Comment thread
jplevyak marked this conversation as resolved.

struct VmStats {
ALL_VM_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT)
};

// Wasm VM base instance. Provides common behavior (e.g. Stats).
class WasmVmBase : public WasmVm {
public:
WasmVmBase(const Stats::ScopeSharedPtr& scope, absl::string_view runtime)
: scope_(scope), runtime_prefix_(absl::StrCat("wasm_vm.", runtime, ".")),
runtime_(std::string(runtime)),
stats_(VmStats{ALL_VM_STATS(POOL_COUNTER_PREFIX(*scope_, runtime_prefix_),
POOL_GAUGE_PREFIX(*scope_, runtime_prefix_))}) {
stats_.created_.inc();
stats_.active_.inc();
ENVOY_LOG(debug, "WasmVm created {} now active", runtime_, stats_.active_.value());
}
virtual ~WasmVmBase() {
stats_.active_.dec();
ENVOY_LOG(debug, "~WasmVm {} {} remaining active", runtime_, stats_.active_.value());
}

protected:
const Stats::ScopeSharedPtr scope_;
const std::string runtime_prefix_;
const std::string runtime_; // The runtime e.g. "v8".
VmStats stats_;
};

} // namespace Wasm
} // namespace Common
} // namespace Extensions
} // namespace Envoy
Loading