Skip to content

Commit 8ccb826

Browse files
authored
Extract common bytecode operations into WasmBase. (#161)
Signed-off-by: Piotr Sikora <[email protected]>
1 parent 314743b commit 8ccb826

File tree

18 files changed

+193
-255
lines changed

18 files changed

+193
-255
lines changed

BUILD

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@ cc_library(
2525
"src/*.h",
2626
"src/*.cc",
2727
"src/common/*.h",
28-
"src/common/*.cc",
28+
"src/null/*.cc",
2929
"src/third_party/*.h",
3030
"src/third_party/*.cc",
31-
"src/null/*.cc",
3231
]),
3332
deps = [
3433
":include",

src/common/bytecode_util.h renamed to include/proxy-wasm/bytecode_util.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include "include/proxy-wasm/wasm_vm.h"
2121

2222
namespace proxy_wasm {
23-
namespace common {
2423

2524
// Utilitiy functions which directly operate on Wasm bytecodes.
2625
class BytecodeUtil {
@@ -73,5 +72,4 @@ class BytecodeUtil {
7372
static bool parseVarint(const char *&begin, const char *end, uint32_t &ret);
7473
};
7574

76-
} // namespace common
7775
} // namespace proxy_wasm

include/proxy-wasm/null_vm.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ struct NullVm : public WasmVm {
3535
std::string_view runtime() override { return "null"; }
3636
Cloneable cloneable() override { return Cloneable::InstantiatedModule; };
3737
std::unique_ptr<WasmVm> clone() override;
38-
bool load(const std::string &code, bool allow_precompiled) override;
39-
AbiVersion getAbiVersion() override;
38+
bool load(std::string_view bytecode, std::string_view precompiled,
39+
std::unordered_map<uint32_t, std::string> function_names) override;
4040
bool link(std::string_view debug_name) override;
4141
uint64_t getMemorySize() override;
4242
std::optional<std::string_view> getMemory(uint64_t pointer, uint64_t size) override;

include/proxy-wasm/wasm.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
5858
WasmBase(const std::shared_ptr<WasmHandleBase> &other, WasmVmFactory factory);
5959
virtual ~WasmBase();
6060

61-
bool initialize(const std::string &code, bool allow_precompiled = false);
61+
bool load(const std::string &code, bool allow_precompiled = false);
62+
bool initialize();
6263
void startVm(ContextBase *root_context);
6364
bool configure(ContextBase *root_context, std::shared_ptr<PluginBase> plugin);
6465
// Returns the root ContextBase or nullptr if onStart returns false.
@@ -79,9 +80,11 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
7980
bool isFailed() { return failed_ != FailState::Ok; }
8081
FailState fail_state() { return failed_; }
8182

82-
const std::string &code() const { return code_; }
8383
const std::string &vm_configuration() const;
84-
bool allow_precompiled() const { return allow_precompiled_; }
84+
85+
const std::string &moduleBytecode() const { return module_bytecode_; }
86+
const std::string &modulePrecompiled() const { return module_precompiled_; }
87+
const std::unordered_map<uint32_t, std::string> functionNames() const { return function_names_; }
8588

8689
void timerReady(uint32_t root_context_id);
8790
void queueReady(uint32_t root_context_id, uint32_t token);
@@ -135,7 +138,7 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
135138
virtual void error(std::string_view message) { std::cerr << message << "\n"; }
136139
virtual void unimplemented() { error("unimplemented proxy-wasm API"); }
137140

138-
AbiVersion abiVersion() { return abi_version_; }
141+
AbiVersion abiVersion() const { return abi_version_; }
139142

140143
const std::unordered_map<std::string, std::string> &envs() { return envs_; }
141144

@@ -182,7 +185,7 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
182185
std::string vm_id_; // User-provided vm_id.
183186
std::string vm_key_; // vm_id + hash of code.
184187
std::unique_ptr<WasmVm> wasm_vm_;
185-
Cloneable started_from_{Cloneable::NotCloneable};
188+
std::optional<Cloneable> started_from_;
186189

187190
uint32_t next_context_id_ = 1; // 0 is reserved for the VM context.
188191
std::shared_ptr<ContextBase> vm_context_; // Context unrelated to any specific root or stream
@@ -260,15 +263,17 @@ class WasmBase : public std::enable_shared_from_this<WasmBase> {
260263
std::shared_ptr<WasmHandleBase> base_wasm_handle_;
261264

262265
// Used by the base_wasm to enable non-clonable thread local Wasm(s) to be constructed.
263-
std::string code_;
264-
std::string vm_configuration_;
265-
bool allow_precompiled_ = false;
266-
bool stop_iteration_ = false;
267-
FailState failed_ = FailState::Ok; // Wasm VM fatal error.
266+
std::string module_bytecode_;
267+
std::string module_precompiled_;
268+
std::unordered_map<uint32_t, std::string> function_names_;
268269

269270
// ABI version.
270271
AbiVersion abi_version_ = AbiVersion::Unknown;
271272

273+
std::string vm_configuration_;
274+
bool stop_iteration_ = false;
275+
FailState failed_ = FailState::Ok; // Wasm VM fatal error.
276+
272277
// Plugin Stats/Metrics
273278
uint32_t next_counter_metric_id_ = static_cast<uint32_t>(MetricType::Counter);
274279
uint32_t next_gauge_metric_id_ = static_cast<uint32_t>(MetricType::Gauge);

include/proxy-wasm/wasm_vm.h

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <memory>
2020
#include <optional>
2121
#include <string>
22+
#include <unordered_map>
2223

2324
#include "include/proxy-wasm/word.h"
2425

@@ -174,14 +175,13 @@ class WasmVm {
174175
* Load the WASM code from a file. Return true on success. Once the module is loaded it can be
175176
* queried, e.g. to see which version of emscripten support is required. After loading, the
176177
* appropriate ABI callbacks can be registered and then the module can be link()ed (see below).
177-
* @param code the WASM binary code (or registered NullVm plugin name).
178-
* @param allow_precompiled if true, allows supporting VMs (e.g. WAVM) to load the binary
179-
* machine code from a user-defined section of the WASM file. Because that code is not verified by
180-
* the proxy process it is up to the user to ensure that the code is both safe and is built for
181-
* the linked in version of WAVM.
178+
* @param bytecode the Wasm bytecode or registered NullVm plugin name.
179+
* @param precompiled (optional) the precompiled Wasm module.
180+
* @param function_names (optional) an index-to-name mapping for the functions.
182181
* @return whether or not the load was successful.
183182
*/
184-
virtual bool load(const std::string &code, bool allow_precompiled) = 0;
183+
virtual bool load(std::string_view bytecode, std::string_view precompiled,
184+
const std::unordered_map<uint32_t, std::string> function_names) = 0;
185185

186186
/**
187187
* Link the WASM code to the host-provided functions, e.g. the ABI. Prior to linking, the module
@@ -192,12 +192,6 @@ class WasmVm {
192192
*/
193193
virtual bool link(std::string_view debug_name) = 0;
194194

195-
/**
196-
* Get ABI version of the module.
197-
* @return the ABI version.
198-
*/
199-
virtual AbiVersion getAbiVersion() = 0;
200-
201195
/**
202196
* Get size of the currently allocated memory in the VM.
203197
* @return the size of memory in bytes.

src/common/bytecode_util.cc renamed to src/bytecode_util.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include "src/common/bytecode_util.h"
15+
#include "include/proxy-wasm/bytecode_util.h"
16+
1617
#include <cstring>
1718

1819
namespace proxy_wasm {
19-
namespace common {
2020

2121
bool BytecodeUtil::checkWasmHeader(std::string_view bytecode) {
2222
// Wasm file header is 8 bytes (magic number + version).
@@ -240,5 +240,4 @@ bool BytecodeUtil::parseVarint(const char *&pos, const char *end, uint32_t &ret)
240240
return ret != static_cast<uint32_t>(-1);
241241
}
242242

243-
} // namespace common
244243
} // namespace proxy_wasm

src/null/null_vm.cc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,23 @@ std::unique_ptr<WasmVm> NullVm::clone() {
4040
auto cloned_null_vm = std::make_unique<NullVm>(*this);
4141
if (integration())
4242
cloned_null_vm->integration().reset(integration()->clone());
43-
cloned_null_vm->load(plugin_name_, false /* unused */);
43+
cloned_null_vm->load(plugin_name_, {} /* unused */, {} /* unused */);
4444
return cloned_null_vm;
4545
}
4646

4747
// "Load" the plugin by obtaining a pointer to it from the factory.
48-
bool NullVm::load(const std::string &name, bool /* allow_precompiled */) {
48+
bool NullVm::load(std::string_view name, std::string_view,
49+
const std::unordered_map<uint32_t, std::string>) {
4950
if (!null_vm_plugin_factories_)
5051
return false;
51-
auto factory = (*null_vm_plugin_factories_)[name];
52+
auto factory = (*null_vm_plugin_factories_)[std::string(name)];
5253
if (!factory)
5354
return false;
5455
plugin_name_ = name;
5556
plugin_ = factory();
5657
plugin_->wasm_vm_ = this;
5758
return true;
58-
}
59-
60-
AbiVersion NullVm::getAbiVersion() { return AbiVersion::ProxyWasm_0_2_1; }
59+
} // namespace proxy_wasm
6160

6261
bool NullVm::link(std::string_view /* name */) { return true; }
6362

src/v8/v8.cc

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
#include <utility>
2626
#include <vector>
2727

28-
#include "src/common/bytecode_util.h"
29-
3028
#include "v8.h"
3129
#include "v8-version.h"
3230
#include "wasm-api/wasm.hh"
@@ -64,8 +62,8 @@ class V8 : public WasmVm {
6462
// WasmVm
6563
std::string_view runtime() override { return "v8"; }
6664

67-
bool load(const std::string &code, bool allow_precompiled) override;
68-
AbiVersion getAbiVersion() override;
65+
bool load(std::string_view bytecode, std::string_view precompiled,
66+
const std::unordered_map<uint32_t, std::string> function_names) override;
6967
std::string_view getPrecompiledSectionName() override;
7068
bool link(std::string_view debug_name) override;
7169

@@ -122,8 +120,6 @@ class V8 : public WasmVm {
122120

123121
std::unordered_map<std::string, FuncDataPtr> host_functions_;
124122
std::unordered_map<std::string, wasm::own<wasm::Func>> module_functions_;
125-
126-
AbiVersion abi_version_;
127123
std::unordered_map<uint32_t, std::string> function_names_index_;
128124
};
129125

@@ -251,58 +247,31 @@ template <typename T, typename U> constexpr T convertValTypesToArgsTuple(const U
251247

252248
// V8 implementation.
253249

254-
bool V8::load(const std::string &code, bool allow_precompiled) {
250+
bool V8::load(std::string_view bytecode, std::string_view precompiled,
251+
const std::unordered_map<uint32_t, std::string> function_names) {
255252
store_ = wasm::Store::make(engine());
256253

257-
// Get ABI version from bytecode.
258-
if (!common::BytecodeUtil::getAbiVersion(code, abi_version_)) {
259-
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
260-
return false;
261-
}
254+
if (!precompiled.empty()) {
255+
auto vec = wasm::vec<byte_t>::make_uninitialized(precompiled.size());
256+
::memcpy(vec.get(), precompiled.data(), precompiled.size());
257+
module_ = wasm::Module::deserialize(store_.get(), vec);
262258

263-
if (allow_precompiled) {
264-
const auto section_name = getPrecompiledSectionName();
265-
if (!section_name.empty()) {
266-
std::string_view precompiled = {};
267-
if (!common::BytecodeUtil::getCustomSection(code, section_name, precompiled)) {
268-
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
269-
return false;
270-
}
271-
if (!precompiled.empty()) {
272-
auto vec = wasm::vec<byte_t>::make_uninitialized(precompiled.size());
273-
::memcpy(vec.get(), precompiled.data(), precompiled.size());
274-
275-
module_ = wasm::Module::deserialize(store_.get(), vec);
276-
if (!module_) {
277-
// Precompiled module that cannot be loaded is considered a hard error,
278-
// so don't fallback to compiling the bytecode.
279-
return false;
280-
}
281-
}
282-
}
259+
} else {
260+
auto vec = wasm::vec<byte_t>::make_uninitialized(bytecode.size());
261+
::memcpy(vec.get(), bytecode.data(), bytecode.size());
262+
module_ = wasm::Module::make(store_.get(), vec);
283263
}
284264

285265
if (!module_) {
286-
std::string stripped;
287-
if (!common::BytecodeUtil::getStrippedSource(code, stripped)) {
288-
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
289-
return false;
290-
};
291-
wasm::vec<byte_t> stripped_vec = wasm::vec<byte_t>::make(stripped.size(), stripped.data());
292-
module_ = wasm::Module::make(store_.get(), stripped_vec);
266+
return false;
293267
}
294268

295-
if (module_) {
296-
shared_module_ = module_->share();
297-
assert((shared_module_ != nullptr));
298-
}
269+
shared_module_ = module_->share();
270+
assert(shared_module_ != nullptr);
299271

300-
if (!common::BytecodeUtil::getFunctionNameIndex(code, function_names_index_)) {
301-
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
302-
return false;
303-
};
272+
function_names_index_ = function_names;
304273

305-
return module_ != nullptr;
274+
return true;
306275
}
307276

308277
std::unique_ptr<WasmVm> V8::clone() {
@@ -314,7 +283,6 @@ std::unique_ptr<WasmVm> V8::clone() {
314283

315284
clone->module_ = wasm::Module::obtain(clone->store_.get(), shared_module_.get());
316285
clone->function_names_index_ = function_names_index_;
317-
clone->abi_version_ = abi_version_;
318286

319287
return clone;
320288
}
@@ -335,8 +303,6 @@ std::string_view V8::getPrecompiledSectionName() {
335303
return name;
336304
}
337305

338-
AbiVersion V8::getAbiVersion() { return abi_version_; }
339-
340306
bool V8::link(std::string_view debug_name) {
341307
assert(module_ != nullptr);
342308

src/wamr/wamr.cc

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@
2929
#include <utility>
3030
#include <vector>
3131

32+
#include "include/proxy-wasm/bytecode_util.h"
33+
3234
#include "src/wamr/types.h"
3335
#include "wasm_c_api.h"
34-
#include "src/common/bytecode_util.h"
3536

3637
namespace proxy_wasm {
3738
namespace wamr {
@@ -62,9 +63,8 @@ class Wamr : public WasmVm {
6263
Cloneable cloneable() override { return Cloneable::NotCloneable; }
6364
std::unique_ptr<WasmVm> clone() override { return nullptr; }
6465

65-
AbiVersion getAbiVersion() override;
66-
67-
bool load(const std::string &code, bool allow_precompiled = false) override;
66+
bool load(std::string_view bytecode, std::string_view precompiled,
67+
const std::unordered_map<uint32_t, std::string> function_names) override;
6868
bool link(std::string_view debug_name) override;
6969
uint64_t getMemorySize() override;
7070
std::optional<std::string_view> getMemory(uint64_t pointer, uint64_t size) override;
@@ -113,27 +113,15 @@ class Wamr : public WasmVm {
113113

114114
std::unordered_map<std::string, HostFuncDataPtr> host_functions_;
115115
std::unordered_map<std::string, WasmFuncPtr> module_functions_;
116-
AbiVersion abi_version_;
117116
};
118117

119-
bool Wamr::load(const std::string &code, bool allow_precompiled) {
118+
bool Wamr::load(std::string_view bytecode, std::string_view,
119+
const std::unordered_map<uint32_t, std::string>) {
120120
store_ = wasm_store_new(engine());
121121

122-
// Get ABI version from bytecode.
123-
if (!common::BytecodeUtil::getAbiVersion(code, abi_version_)) {
124-
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
125-
return false;
126-
}
127-
128-
std::string stripped;
129-
if (!common::BytecodeUtil::getStrippedSource(code, stripped)) {
130-
fail(FailState::UnableToInitializeCode, "Failed to parse corrupted Wasm module");
131-
return false;
132-
};
133-
134-
WasmByteVec stripped_vec;
135-
wasm_byte_vec_new(stripped_vec.get(), stripped.size(), stripped.data());
136-
module_ = wasm_module_new(store_.get(), stripped_vec.get());
122+
WasmByteVec vec;
123+
wasm_byte_vec_new(vec.get(), bytecode.size(), bytecode.data());
124+
module_ = wasm_module_new(store_.get(), vec.get());
137125

138126
return module_ != nullptr;
139127
}
@@ -622,8 +610,6 @@ void Wamr::getModuleFunctionImpl(std::string_view function_name,
622610
};
623611
};
624612

625-
AbiVersion Wamr::getAbiVersion() { return abi_version_; }
626-
627613
} // namespace wamr
628614

629615
std::unique_ptr<WasmVm> createWamrVm() { return std::make_unique<wamr::Wamr>(); }

0 commit comments

Comments
 (0)