summaryrefslogtreecommitdiff
path: root/src/c-writer.cc
diff options
context:
space:
mode:
authorShravan Narayan <shravanrn@gmail.com>2024-06-26 11:30:44 -0500
committerGitHub <noreply@github.com>2024-06-26 09:30:44 -0700
commit0e871afa4aaac9fe0b1f00cb42a59be666657a06 (patch)
tree22c449953033d0ea98200d9117c11419054a762e /src/c-writer.cc
parentf820d171654de2dcb8cbf7078b4c98336c8e3c69 (diff)
downloadwabt-0e871afa4aaac9fe0b1f00cb42a59be666657a06.tar.gz
wabt-0e871afa4aaac9fe0b1f00cb42a59be666657a06.tar.bz2
wabt-0e871afa4aaac9fe0b1f00cb42a59be666657a06.zip
wasm2c: Segue optimization for modules with a single unshared memory (#2395)
Diffstat (limited to 'src/c-writer.cc')
-rw-r--r--src/c-writer.cc64
1 files changed, 62 insertions, 2 deletions
diff --git a/src/c-writer.cc b/src/c-writer.cc
index cd0ee1fd..1a091957 100644
--- a/src/c-writer.cc
+++ b/src/c-writer.cc
@@ -308,6 +308,7 @@ class CWriter {
void Indent(int size = INDENT_SIZE);
void Dedent(int size = INDENT_SIZE);
+ void NonIndented(std::function<void()> func);
void WriteIndent();
void WriteData(const char* src, size_t size);
void Writef(const char* format, ...);
@@ -402,6 +403,9 @@ class CWriter {
void WriteElemInitializerDecls();
void WriteElemInitializers();
void WriteElemTableInit(bool, const ElemSegment*, const Table*);
+ bool IsSingleUnsharedMemory();
+ void InstallSegueBase(Memory* memory, bool save_old_value);
+ void RestoreSegueBase();
void WriteExports(CWriterPhase);
void WriteTailCallExports(CWriterPhase);
void WriteInitDecl();
@@ -1021,6 +1025,13 @@ void CWriter::Dedent(int size) {
assert(indent_ >= 0);
}
+void CWriter::NonIndented(std::function<void()> func) {
+ int copy = indent_;
+ indent_ = 0;
+ func();
+ indent_ = copy;
+}
+
void CWriter::WriteIndent() {
static char s_indent[] =
" "
@@ -1479,6 +1490,11 @@ std::string CWriter::GenerateHeaderGuard() const {
void CWriter::WriteSourceTop() {
Write(s_source_includes);
Write(Newline(), "#include \"", header_name_, "\"", Newline());
+
+ if (IsSingleUnsharedMemory()) {
+ Write("#define IS_SINGLE_UNSHARED_MEMORY 1", Newline());
+ }
+
Write(s_source_declarations, Newline());
if (module_->features_used.simd) {
@@ -2425,6 +2441,28 @@ void CWriter::WriteElemTableInit(bool active_initialization,
Write(");", Newline());
}
+bool CWriter::IsSingleUnsharedMemory() {
+ return module_->memories.size() == 1 &&
+ !module_->memories[0]->page_limits.is_shared;
+}
+
+void CWriter::InstallSegueBase(Memory* memory, bool save_old_value) {
+ NonIndented([&] { Write("#if WASM_RT_USE_SEGUE", Newline()); });
+ if (save_old_value) {
+ Write("uintptr_t segue_saved_base = WASM_RT_SEGUE_READ_BASE();", Newline());
+ }
+ auto primary_memory =
+ ExternalInstanceRef(ModuleFieldType::Memory, memory->name);
+ Write("WASM_RT_SEGUE_WRITE_BASE(", primary_memory, ".data);", Newline());
+ NonIndented([&] { Write("#endif", Newline()); });
+}
+
+void CWriter::RestoreSegueBase() {
+ NonIndented([&] { Write("#if WASM_RT_USE_SEGUE", Newline()); });
+ Write("WASM_RT_SEGUE_WRITE_BASE(segue_saved_base);", Newline());
+ NonIndented([&] { Write("#endif", Newline()); });
+}
+
void CWriter::WriteExports(CWriterPhase kind) {
if (module_->exports.empty())
return;
@@ -2500,8 +2538,14 @@ void CWriter::WriteExports(CWriterPhase kind) {
switch (export_->kind) {
case ExternalKind::Func: {
Write(OpenBrace());
- if (func_->GetNumResults() > 0) {
- Write("return ");
+ if (IsSingleUnsharedMemory()) {
+ InstallSegueBase(module_->memories[0], true /* save_old_value */);
+ }
+ auto num_results = func_->GetNumResults();
+ if (num_results > 1) {
+ Write(func_->decl.sig.result_types, " ret = ");
+ } else if (num_results == 1) {
+ Write(func_->GetResultType(0), " ret = ");
}
Write(ExternalRef(ModuleFieldType::Func, internal_name), "(");
@@ -2513,6 +2557,12 @@ void CWriter::WriteExports(CWriterPhase kind) {
Write("instance");
}
WriteParamSymbols(index_to_name);
+ if (IsSingleUnsharedMemory()) {
+ RestoreSegueBase();
+ }
+ if (num_results > 0) {
+ Write("return ret;", Newline());
+ }
Write(CloseBrace(), Newline());
local_sym_map_.clear();
@@ -2611,6 +2661,9 @@ void CWriter::WriteInit() {
}
if (!module_->memories.empty()) {
Write("init_memories(instance);", Newline());
+ if (IsSingleUnsharedMemory()) {
+ InstallSegueBase(module_->memories[0], true /* save_old_value */);
+ }
}
if (!module_->tables.empty() && !module_->elem_segments.empty()) {
Write("init_elem_instances(instance);", Newline());
@@ -2631,6 +2684,10 @@ void CWriter::WriteInit() {
}
Write(Newline());
}
+
+ if (IsSingleUnsharedMemory()) {
+ RestoreSegueBase();
+ }
Write(CloseBrace(), Newline());
}
@@ -3733,6 +3790,9 @@ void CWriter::Write(const ExprList& exprs) {
Write(StackVar(0), " = ", func, "(",
ExternalInstancePtr(ModuleFieldType::Memory, memory->name), ", ",
StackVar(0), ");", Newline());
+ if (IsSingleUnsharedMemory()) {
+ InstallSegueBase(module_->memories[0], false /* save_old_value */);
+ }
break;
}