summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-04-27 19:25:15 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-04-27 19:25:15 -0700
commit6a6bdc1cef5ec35cb9f7caf6e10ec76ee1107d0d (patch)
tree9ed1b23b55c86f8fa1aee285bfdde9d47c2f1ae8
parent4a85f62e8a83117a081e9691d8830b6a7a876d1d (diff)
parentf0a4f15dc27ffff9505503a8168854b7662b2657 (diff)
downloadbinaryen-6a6bdc1cef5ec35cb9f7caf6e10ec76ee1107d0d.tar.gz
binaryen-6a6bdc1cef5ec35cb9f7caf6e10ec76ee1107d0d.tar.bz2
binaryen-6a6bdc1cef5ec35cb9f7caf6e10ec76ee1107d0d.zip
Merge pull request #403 from WebAssembly/leaks
Fix leaks and enable leak checks
-rw-r--r--.travis.yml2
-rw-r--r--src/asm2wasm.h29
-rw-r--r--src/asm_v_wasm.h2
-rw-r--r--src/asmjs/asm_v_wasm.cpp6
-rw-r--r--src/binaryen-shell.cpp12
-rw-r--r--src/emscripten-optimizer/istring.h4
-rw-r--r--src/emscripten-optimizer/parser.cpp26
-rw-r--r--src/emscripten-optimizer/simple_ast.cpp9
-rw-r--r--src/emscripten-optimizer/simple_ast.h1
-rw-r--r--src/passes/Print.cpp10
-rw-r--r--src/passes/RemoveImports.cpp9
-rw-r--r--src/s2wasm.h42
-rw-r--r--src/shell-interface.h6
-rw-r--r--src/wasm-binary.h43
-rw-r--r--src/wasm-builder.h2
-rw-r--r--src/wasm-linker.cpp15
-rw-r--r--src/wasm-linker.h7
-rw-r--r--src/wasm-s-parser.h34
-rw-r--r--src/wasm-traversal.h18
-rw-r--r--src/wasm-validator.h4
-rw-r--r--src/wasm.h50
-rw-r--r--src/wasm2asm.h10
22 files changed, 180 insertions, 161 deletions
diff --git a/.travis.yml b/.travis.yml
index 953a20e7c..7c69a5d52 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,7 +35,7 @@ matrix:
before_install:
- export CC="${CC}-${COMPILER_VERSION}"
- export CXX="${CXX}-${COMPILER_VERSION}"
- - export ASAN_OPTIONS="detect_leaks=0 symbolize=1"
+ - export ASAN_OPTIONS="symbolize=1"
install:
- pip install --user flake8
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index ae24358d7..f905d2047 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -216,13 +216,13 @@ private:
// function types. we fill in this information as we see
// uses, in the first pass
- std::map<IString, FunctionType*> importedFunctionTypes;
+ std::map<IString, std::unique_ptr<FunctionType>> importedFunctionTypes;
std::map<IString, std::vector<CallImport*>> importedFunctionCalls;
void noteImportedFunctionCall(Ref ast, WasmType resultType, AsmData *asmData, CallImport* call) {
assert(ast[0] == CALL && ast[1][0] == NAME);
IString importName = ast[1][1]->getIString();
- auto* type = allocator.alloc<FunctionType>();
+ auto type = make_unique<FunctionType>();
type->name = IString((std::string("type$") + importName.str).c_str(), false); // TODO: make a list of such types
type->result = resultType;
Ref args = ast[2];
@@ -231,7 +231,7 @@ private:
}
// if we already saw this signature, verify it's the same (or else handle that)
if (importedFunctionTypes.find(importName) != importedFunctionTypes.end()) {
- FunctionType* previous = importedFunctionTypes[importName];
+ FunctionType* previous = importedFunctionTypes[importName].get();
#if 0
std::cout << "compare " << importName.str << "\nfirst: ";
type.print(std::cout, 0);
@@ -254,7 +254,7 @@ private:
}
}
} else {
- importedFunctionTypes[importName] = type;
+ importedFunctionTypes[importName].swap(type);
}
importedFunctionCalls[importName].push_back(call);
}
@@ -508,7 +508,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
}
}
}
- auto import = allocator.alloc<Import>();
+ auto import = new Import();
import->name = name;
import->module = moduleName;
import->base = imported[2]->getIString();
@@ -519,6 +519,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
if (type != WasmType::none) {
// wasm has no imported constants, so allocate a global, and we need to write the value into that
allocateGlobal(name, type, true, import->module, import->base);
+ delete import;
} else {
wasm.addImport(import);
}
@@ -678,7 +679,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
getTempRet0 = value;
}
assert(wasm.checkFunction(value));
- auto export_ = allocator.alloc<Export>();
+ auto export_ = new Export;
export_->name = key;
export_->value = value;
wasm.addExport(export_);
@@ -690,7 +691,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
std::vector<IString> toErase;
- for (auto* import : wasm.imports) {
+ for (auto& import : wasm.imports) {
IString name = import->name;
if (importedFunctionTypes.find(name) != importedFunctionTypes.end()) {
// special math builtins
@@ -699,7 +700,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
import->type = builtin;
continue;
}
- import->type = ensureFunctionType(getSig(importedFunctionTypes[name]), &wasm);
+ import->type = ensureFunctionType(getSig(importedFunctionTypes[name].get()), &wasm);
} else if (import->module != ASM2WASM) { // special-case the special module
// never actually used
toErase.push_back(name);
@@ -714,7 +715,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
for (auto& pair : importedFunctionCalls) {
IString name = pair.first;
auto& list = pair.second;
- auto type = importedFunctionTypes[name];
+ auto type = importedFunctionTypes[name].get();
for (auto* call : list) {
for (size_t i = call->operands.size(); i < type->params.size(); i++) {
auto val = allocator.alloc<Const>();
@@ -754,7 +755,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
{ builder.makeGetLocal(0, i32) }
)
));
- auto export_ = allocator.alloc<Export>();
+ auto export_ = new Export;
export_->name = export_->value = GROW_WASM_MEMORY;
wasm.addExport(export_);
}
@@ -869,7 +870,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
std::cout << '\n';
}
- auto function = allocator.alloc<Function>();
+ auto function = new Function;
function->name = name;
Ref params = ast[2];
Ref body = ast[3];
@@ -1017,7 +1018,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
static bool addedImport = false;
if (!addedImport) {
addedImport = true;
- auto import = allocator.alloc<Import>(); // f64-rem = asm2wasm.f64-rem;
+ auto import = new Import; // f64-rem = asm2wasm.f64-rem;
import->name = F64_REM;
import->module = ASM2WASM;
import->base = F64_REM;
@@ -1055,7 +1056,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
static bool addedImport = false;
if (!addedImport) {
addedImport = true;
- auto import = allocator.alloc<Import>(); // debugger = asm2wasm.debugger;
+ auto import = new Import; // debugger = asm2wasm.debugger;
import->name = DEBUGGER;
import->module = ASM2WASM;
import->base = DEBUGGER;
@@ -1168,7 +1169,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
static bool addedImport = false;
if (!addedImport) {
addedImport = true;
- auto import = allocator.alloc<Import>(); // f64-to-int = asm2wasm.f64-to-int;
+ auto import = new Import; // f64-to-int = asm2wasm.f64-to-int;
import->name = F64_TO_INT;
import->module = ASM2WASM;
import->base = F64_TO_INT;
diff --git a/src/asm_v_wasm.h b/src/asm_v_wasm.h
index cfb4d44d5..52524ecbc 100644
--- a/src/asm_v_wasm.h
+++ b/src/asm_v_wasm.h
@@ -55,7 +55,7 @@ std::string getSig(WasmType result, const ListType& operands) {
WasmType sigToWasmType(char sig);
-FunctionType sigToFunctionType(std::string sig);
+FunctionType* sigToFunctionType(std::string sig);
FunctionType* ensureFunctionType(std::string sig, Module* wasm);
diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp
index 3e7e0241e..14a7fbdae 100644
--- a/src/asmjs/asm_v_wasm.cpp
+++ b/src/asmjs/asm_v_wasm.cpp
@@ -82,8 +82,8 @@ WasmType sigToWasmType(char sig) {
}
}
-FunctionType* sigToFunctionType(std::string sig, MixedArena& allocator) {
- auto ret = allocator.alloc<FunctionType>();
+FunctionType* sigToFunctionType(std::string sig) {
+ auto ret = new FunctionType;
ret->result = sigToWasmType(sig[0]);
for (size_t i = 1; i < sig.size(); i++) {
ret->params.push_back(sigToWasmType(sig[i]));
@@ -97,7 +97,7 @@ FunctionType* ensureFunctionType(std::string sig, Module* wasm) {
return wasm->getFunctionType(name);
}
// add new type
- auto type = wasm->allocator.alloc<FunctionType>();
+ auto type = new FunctionType;
type->name = name;
type->result = sigToWasmType(sig[0]);
for (size_t i = 1; i < sig.size(); i++) {
diff --git a/src/binaryen-shell.cpp b/src/binaryen-shell.cpp
index 4f2890969..509bd97dc 100644
--- a/src/binaryen-shell.cpp
+++ b/src/binaryen-shell.cpp
@@ -74,11 +74,11 @@ static void run_asserts(size_t* i, bool* checked, Module* wasm,
Element* root,
std::unique_ptr<SExpressionWasmBuilder>* builder,
Name entry) {
- ShellExternalInterface* interface = nullptr;
- ModuleInstance* instance = nullptr;
+ std::unique_ptr<ShellExternalInterface> interface;
+ std::unique_ptr<ModuleInstance> instance;
if (wasm) {
- interface = new ShellExternalInterface();
- instance = new ModuleInstance(*wasm, interface);
+ interface = make_unique<ShellExternalInterface>();
+ instance = make_unique<ModuleInstance>(*wasm, interface.get());
if (entry.is()) {
Function* function = wasm->getFunction(entry);
if (!function) {
@@ -128,7 +128,7 @@ static void run_asserts(size_t* i, bool* checked, Module* wasm,
assert(invalid);
} else if (id == INVOKE) {
assert(wasm);
- Invocation invocation(curr, instance, *builder->get());
+ Invocation invocation(curr, instance.get(), *builder->get());
invocation.invoke();
} else {
// an invoke test
@@ -136,7 +136,7 @@ static void run_asserts(size_t* i, bool* checked, Module* wasm,
bool trapped = false;
Literal result;
try {
- Invocation invocation(*curr[1], instance, *builder->get());
+ Invocation invocation(*curr[1], instance.get(), *builder->get());
result = invocation.invoke();
} catch (const TrapException&) {
trapped = true;
diff --git a/src/emscripten-optimizer/istring.h b/src/emscripten-optimizer/istring.h
index 149f77d23..e47361eeb 100644
--- a/src/emscripten-optimizer/istring.h
+++ b/src/emscripten-optimizer/istring.h
@@ -149,11 +149,13 @@ namespace cashew {
// IStringSet
class IStringSet : public std::unordered_set<IString> {
+ std::vector<char> data;
public:
IStringSet() {}
IStringSet(const char *init) { // comma-delimited list
int size = strlen(init) + 1;
- char *curr = new char[size]; // leaked!
+ data.resize(size);
+ char *curr = &data[0];
strncpy(curr, init, size);
while (1) {
char *end = strchr(curr, ' ');
diff --git a/src/emscripten-optimizer/parser.cpp b/src/emscripten-optimizer/parser.cpp
index b8297fc29..ef2891941 100644
--- a/src/emscripten-optimizer/parser.cpp
+++ b/src/emscripten-optimizer/parser.cpp
@@ -121,19 +121,19 @@ static std::vector<std::unordered_map<IString, int>> precedences; // op, type =>
struct Init {
Init() {
// operators, rtl, type
- operatorClasses.push_back(OperatorClass(".", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("! ~ + -", true, OperatorClass::Prefix));
- operatorClasses.push_back(OperatorClass("* / %", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("+ -", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("<< >> >>>", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("< <= > >=", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("== !=", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("&", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("^", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("|", false, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass("? :", true, OperatorClass::Tertiary));
- operatorClasses.push_back(OperatorClass("=", true, OperatorClass::Binary));
- operatorClasses.push_back(OperatorClass(",", true, OperatorClass::Binary));
+ operatorClasses.emplace_back(".", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("! ~ + -", true, OperatorClass::Prefix);
+ operatorClasses.emplace_back("* / %", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("+ -", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("<< >> >>>", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("< <= > >=", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("== !=", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("&", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("^", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("|", false, OperatorClass::Binary);
+ operatorClasses.emplace_back("? :", true, OperatorClass::Tertiary);
+ operatorClasses.emplace_back("=", true, OperatorClass::Binary);
+ operatorClasses.emplace_back(",", true, OperatorClass::Binary);
precedences.resize(OperatorClass::Tertiary + 1);
diff --git a/src/emscripten-optimizer/simple_ast.cpp b/src/emscripten-optimizer/simple_ast.cpp
index 285686b9a..dddaeab02 100644
--- a/src/emscripten-optimizer/simple_ast.cpp
+++ b/src/emscripten-optimizer/simple_ast.cpp
@@ -56,6 +56,15 @@ bool Ref::operator!() {
Arena arena;
+Arena::~Arena() {
+ for (auto* chunk : chunks) {
+ delete[] chunk;
+ }
+ for (auto* chunk : arr_chunks) {
+ delete[] chunk;
+ }
+}
+
Ref Arena::alloc() {
if (chunks.size() == 0 || index == CHUNK_SIZE) {
chunks.push_back(new Value[CHUNK_SIZE]);
diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h
index 75b7987be..bfb42c510 100644
--- a/src/emscripten-optimizer/simple_ast.h
+++ b/src/emscripten-optimizer/simple_ast.h
@@ -84,6 +84,7 @@ struct Arena {
int arr_index;
Arena() : index(0), arr_index(0) {}
+ ~Arena();
Ref alloc();
ArrayStorage* allocArray();
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index eb0a6d33b..1a62de4f3 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -485,7 +485,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
for (auto segment : curr->memory.segments) {
o << maybeNewLine;
o << (minify ? "" : " ") << "(segment " << segment.offset << " \"";
- for (size_t i = 0; i < segment.size; i++) {
+ for (size_t i = 0; i < segment.data.size(); i++) {
unsigned char c = segment.data[i];
switch (c) {
case '\n': o << "\\n"; break;
@@ -522,17 +522,17 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
for (auto& child : curr->functionTypes) {
doIndent(o, indent);
- visitFunctionType(child, true);
+ visitFunctionType(child.get(), true);
o << maybeNewLine;
}
for (auto& child : curr->imports) {
doIndent(o, indent);
- visitImport(child);
+ visitImport(child.get());
o << maybeNewLine;
}
for (auto& child : curr->exports) {
doIndent(o, indent);
- visitExport(child);
+ visitExport(child.get());
o << maybeNewLine;
}
if (curr->table.names.size() > 0) {
@@ -542,7 +542,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
for (auto& child : curr->functions) {
doIndent(o, indent);
- visitFunction(child);
+ visitFunction(child.get());
o << maybeNewLine;
}
decIndent();
diff --git a/src/passes/RemoveImports.cpp b/src/passes/RemoveImports.cpp
index 0adb9a448..1ef28292f 100644
--- a/src/passes/RemoveImports.cpp
+++ b/src/passes/RemoveImports.cpp
@@ -48,9 +48,12 @@ struct RemoveImports : public WalkerPass<PostWalker<RemoveImports, Visitor<Remov
}
void visitModule(Module *curr) {
- auto imports = curr->imports; // copy
- for (auto* import : imports) {
- curr->removeImport(import->name);
+ std::vector<Name> names;
+ for (auto& import : curr->imports) {
+ names.push_back(import->name);
+ }
+ for (auto& name : names) {
+ curr->removeImport(name);
}
}
};
diff --git a/src/s2wasm.h b/src/s2wasm.h
index b66859ce9..3efd667d5 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -1035,7 +1035,7 @@ class S2WasmBuilder {
}
mustMatch(name.str);
mustMatch(":");
- auto raw = new std::vector<char>(); // leaked intentionally, no new allocation in Memory
+ std::vector<char> raw;
bool zero = true;
std::vector<std::pair<LinkerObject::Relocation*, size_t>> currRelocations; // [relocation, offset in raw]
while (1) {
@@ -1049,8 +1049,8 @@ class S2WasmBuilder {
z = true;
}
auto quoted = getQuoted();
- raw->insert(raw->end(), quoted.begin(), quoted.end());
- if (z) raw->push_back(0);
+ raw.insert(raw.end(), quoted.begin(), quoted.end());
+ if (z) raw.push_back(0);
zero = false;
} else if (match(".zero") || match(".skip")) {
int32_t size = getInt();
@@ -1063,43 +1063,43 @@ class S2WasmBuilder {
if (value != 0) zero = false;
}
for (size_t i = 0, e = size; i < e; i++) {
- raw->push_back(value);
+ raw.push_back(value);
}
} else if (match(".int8")) {
- size_t size = raw->size();
- raw->resize(size + 1);
- (*(int8_t*)(&(*raw)[size])) = getInt();
+ size_t size = raw.size();
+ raw.resize(size + 1);
+ (*(int8_t*)(&raw[size])) = getInt();
zero = false;
} else if (match(".int16")) {
- size_t size = raw->size();
- raw->resize(size + 2);
- (*(int16_t*)(&(*raw)[size])) = getInt();
+ size_t size = raw.size();
+ raw.resize(size + 2);
+ (*(int16_t*)(&raw[size])) = getInt();
zero = false;
} else if (match(".int32")) {
- size_t size = raw->size();
- raw->resize(size + 4);
- if (getConst((uint32_t*)&(*raw)[size])) { // just the size, as we may reallocate; we must fix this later, if it's a relocation
+ size_t size = raw.size();
+ raw.resize(size + 4);
+ if (getConst((uint32_t*)&raw[size])) { // just the size, as we may reallocate; we must fix this later, if it's a relocation
currRelocations.emplace_back(linkerObj->getCurrentRelocation(), size);
}
zero = false;
} else if (match(".int64")) {
- size_t size = raw->size();
- raw->resize(size + 8);
- (*(int64_t*)(&(*raw)[size])) = getInt64();
+ size_t size = raw.size();
+ raw.resize(size + 8);
+ (*(int64_t*)(&raw[size])) = getInt64();
zero = false;
} else {
break;
}
}
skipWhitespace();
- size_t size = raw->size();
+ size_t size = raw.size();
if (match(".size")) {
mustMatch(name.str);
mustMatch(",");
size_t seenSize = atoi(getStr().str); // TODO: optimize
assert(seenSize >= size);
- while (raw->size() < seenSize) {
- raw->push_back(0);
+ while (raw.size() < seenSize) {
+ raw.push_back(0);
}
size = seenSize;
}
@@ -1107,12 +1107,12 @@ class S2WasmBuilder {
for (auto& curr : currRelocations) {
auto* r = curr.first;
auto i = curr.second;
- r->data = (uint32_t*)&(*raw)[i];
+ r->data = (uint32_t*)&raw[i];
}
// assign the address, add to memory
linkerObj->addStatic(size, align, name);
if (!zero) {
- linkerObj->addSegment(name, (const char*)&(*raw)[0], size);
+ linkerObj->addSegment(name, raw);
}
}
diff --git a/src/shell-interface.h b/src/shell-interface.h
index b23b7b645..1dbabf3fa 100644
--- a/src/shell-interface.h
+++ b/src/shell-interface.h
@@ -88,9 +88,9 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
void init(Module& wasm) override {
memory.resize(wasm.memory.initial * wasm::Memory::kPageSize);
// apply memory segments
- for (auto segment : wasm.memory.segments) {
- assert(segment.offset + segment.size <= wasm.memory.initial * wasm::Memory::kPageSize);
- for (size_t i = 0; i != segment.size; ++i) {
+ for (auto& segment : wasm.memory.segments) {
+ assert(segment.offset + segment.data.size() <= wasm.memory.initial * wasm::Memory::kPageSize);
+ for (size_t i = 0; i != segment.data.size(); ++i) {
memory.set(segment.offset + i, segment.data[i]);
}
}
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 3f7ad44d4..91fe91b49 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -447,9 +447,9 @@ class WasmBinaryWriter : public Visitor<WasmBinaryWriter, void> {
void prepare() {
// we need function types for all our functions
- for (auto* func : wasm->functions) {
+ for (auto& func : wasm->functions) {
if (func->type.isNull()) {
- func->type = ensureFunctionType(getSig(func), wasm)->name;
+ func->type = ensureFunctionType(getSig(func.get()), wasm)->name;
}
}
}
@@ -523,7 +523,7 @@ public:
if (debug) std::cerr << "== writeSignatures" << std::endl;
auto start = startSection(BinaryConsts::Section::Signatures);
o << U32LEB(wasm->functionTypes.size());
- for (auto* type : wasm->functionTypes) {
+ for (auto& type : wasm->functionTypes) {
if (debug) std::cerr << "write one" << std::endl;
o << int8_t(BinaryConsts::TypeForms::Basic);
o << U32LEB(type->params.size());
@@ -553,7 +553,7 @@ public:
if (debug) std::cerr << "== writeImports" << std::endl;
auto start = startSection(BinaryConsts::Section::ImportTable);
o << U32LEB(wasm->imports.size());
- for (auto* import : wasm->imports) {
+ for (auto& import : wasm->imports) {
if (debug) std::cerr << "write one" << std::endl;
o << U32LEB(getFunctionTypeIndex(import->type->name));
writeInlineString(import->module.str);
@@ -606,7 +606,7 @@ public:
if (debug) std::cerr << "== writeFunctionSignatures" << std::endl;
auto start = startSection(BinaryConsts::Section::FunctionSignatures);
o << U32LEB(wasm->functions.size());
- for (auto* curr : wasm->functions) {
+ for (auto& curr : wasm->functions) {
if (debug) std::cerr << "write one" << std::endl;
o << U32LEB(getFunctionTypeIndex(curr->type));
}
@@ -623,7 +623,7 @@ public:
if (debug) std::cerr << "write one at" << o.size() << std::endl;
size_t sizePos = writeU32LEBPlaceholder();
size_t start = o.size();
- Function* function = wasm->functions[i];
+ Function* function = wasm->getFunction(i);
mappedLocals.clear();
numLocalsByType.clear();
if (debug) std::cerr << "writing" << function->name << std::endl;
@@ -654,7 +654,7 @@ public:
if (debug) std::cerr << "== writeexports" << std::endl;
auto start = startSection(BinaryConsts::Section::ExportTable);
o << U32LEB(wasm->exports.size());
- for (auto* curr : wasm->exports) {
+ for (auto& curr : wasm->exports) {
if (debug) std::cerr << "write one" << std::endl;
o << U32LEB(getFunctionIndex(curr->value));
writeInlineString(curr->name.str);
@@ -666,14 +666,14 @@ public:
if (wasm->memory.segments.size() == 0) return;
uint32_t num = 0;
for (auto& segment : wasm->memory.segments) {
- if (segment.size > 0) num++;
+ if (segment.data.size() > 0) num++;
}
auto start = startSection(BinaryConsts::Section::DataSegments);
o << U32LEB(num);
for (auto& segment : wasm->memory.segments) {
- if (segment.size == 0) continue;
+ if (segment.data.size() == 0) continue;
o << U32LEB(segment.offset);
- writeInlineBuffer(segment.data, segment.size);
+ writeInlineBuffer(&segment.data[0], segment.data.size());
}
finishSection(start);
}
@@ -720,7 +720,7 @@ public:
if (debug) std::cerr << "== writeNames" << std::endl;
auto start = startSection(BinaryConsts::Section::Names);
o << U32LEB(wasm->functions.size());
- for (auto* curr : wasm->functions) {
+ for (auto& curr : wasm->functions) {
writeInlineString(curr->name.str);
o << U32LEB(0); // TODO: locals
}
@@ -1354,7 +1354,7 @@ public:
if (debug) std::cerr << "num: " << numTypes << std::endl;
for (size_t i = 0; i < numTypes; i++) {
if (debug) std::cerr << "read one" << std::endl;
- auto curr = allocator.alloc<FunctionType>();
+ auto curr = new FunctionType;
auto form = getInt8();
assert(form == BinaryConsts::TypeForms::Basic);
size_t numParams = getU32LEB();
@@ -1379,11 +1379,11 @@ public:
if (debug) std::cerr << "num: " << num << std::endl;
for (size_t i = 0; i < num; i++) {
if (debug) std::cerr << "read one" << std::endl;
- auto curr = allocator.alloc<Import>();
+ auto curr = new Import;
curr->name = Name(std::string("import$") + std::to_string(i));
auto index = getU32LEB();
assert(index < wasm.functionTypes.size());
- curr->type = wasm.functionTypes[index];
+ curr->type = wasm.getFunctionType(index);
assert(curr->type->name.is());
curr->module = getInlineString();
curr->base = getInlineString();
@@ -1400,8 +1400,7 @@ public:
for (size_t i = 0; i < num; i++) {
if (debug) std::cerr << "read one" << std::endl;
auto index = getU32LEB();
- assert(index < wasm.functionTypes.size());
- functionTypes.push_back(wasm.functionTypes[index]);
+ functionTypes.push_back(wasm.getFunctionType(index));
}
}
@@ -1481,7 +1480,7 @@ public:
if (debug) std::cerr << "num: " << num << std::endl;
for (size_t i = 0; i < num; i++) {
if (debug) std::cerr << "read one" << std::endl;
- auto curr = allocator.alloc<Export>();
+ auto curr = new Export;
auto index = getU32LEB();
assert(index < functionTypes.size());
curr->name = getInlineString();
@@ -1549,15 +1548,13 @@ public:
auto num = getU32LEB();
for (size_t i = 0; i < num; i++) {
Memory::Segment curr;
- curr.offset = getU32LEB();
+ auto offset = getU32LEB();
auto size = getU32LEB();
- auto buffer = (char*)malloc(size);
+ char buffer[size];
for (size_t j = 0; j < size; j++) {
buffer[j] = char(getInt8());
}
- curr.data = (const char*)buffer;
- curr.size = size;
- wasm.memory.segments.push_back(curr);
+ wasm.memory.segments.emplace_back(offset, (const char*)buffer, size);
}
}
@@ -1774,7 +1771,7 @@ public:
void visitCallIndirect(CallIndirect *curr) {
if (debug) std::cerr << "zz node: CallIndirect" << std::endl;
auto arity = getU32LEB();
- curr->fullType = wasm.functionTypes[getU32LEB()];
+ curr->fullType = wasm.getFunctionType(getU32LEB());
auto num = curr->fullType->params.size();
assert(num == arity);
curr->operands.resize(num);
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index e25dafc60..5d4c90840 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -45,7 +45,7 @@ public:
WasmType resultType,
std::vector<NameType>&& vars,
Expression* body = nullptr) {
- auto* func = allocator.alloc<Function>();
+ auto* func = new Function;
func->name = name;
func->result = resultType;
func->body = body;
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp
index 6dca9e01b..a854f0cd0 100644
--- a/src/wasm-linker.cpp
+++ b/src/wasm-linker.cpp
@@ -43,10 +43,11 @@ void Linker::placeStackPointer(size_t stackAllocation) {
if (stackAllocation) {
// If we are allocating the stack, set up a relocation to initialize the
// stack pointer to point to one past-the-end of the stack allocation.
- auto* raw = new uint32_t;
- out.addRelocation(LinkerObject::Relocation::kData, raw, ".stack", stackAllocation);
+ std::vector<char> raw;
+ raw.resize(pointerSize);
+ out.addRelocation(LinkerObject::Relocation::kData, (uint32_t*)&raw[0], ".stack", stackAllocation);
assert(out.wasm.memory.segments.size() == 0);
- out.addSegment("__stack_pointer", reinterpret_cast<char*>(raw), pointerSize);
+ out.addSegment("__stack_pointer", raw);
}
}
@@ -56,7 +57,7 @@ void Linker::layout() {
Name target = f.first;
// Create an import for the target if necessary.
if (!out.wasm.checkImport(target)) {
- auto import = out.wasm.allocator.alloc<Import>();
+ auto import = new Import;
import->name = import->base = target;
import->module = ENV;
import->type = ensureFunctionType(getSig(*f.second.begin()), &out.wasm);
@@ -154,7 +155,7 @@ void Linker::layout() {
if (out.symbolInfo.implementedFunctions.count(start) != 0) {
Fatal() << "Start function already present: `" << start << "`\n";
}
- auto* func = out.wasm.allocator.alloc<Function>();
+ auto* func = new Function;
func->name = start;
out.wasm.addFunction(func);
exportFunction(start, true);
@@ -238,7 +239,7 @@ void Linker::emscriptenGlue(std::ostream& o) {
if (curr->target == EMSCRIPTEN_ASM_CONST) {
auto arg = curr->operands[0]->cast<Const>();
size_t segmentIndex = parent->segmentsByAddress[arg->value.geti32()];
- std::string code = escape(parent->out.wasm.memory.segments[segmentIndex].data);
+ std::string code = escape(&parent->out.wasm.memory.segments[segmentIndex].data[0]);
int32_t id;
if (ids.count(code) == 0) {
id = ids.size();
@@ -254,7 +255,7 @@ void Linker::emscriptenGlue(std::ostream& o) {
// add import, if necessary
if (allSigs.count(sig) == 0) {
allSigs.insert(sig);
- auto import = parent->out.wasm.allocator.alloc<Import>();
+ auto import = new Import;
import->name = import->base = curr->target;
import->module = ENV;
import->type = ensureFunctionType(getSig(curr), &parent->out.wasm);
diff --git a/src/wasm-linker.h b/src/wasm-linker.h
index ab336e581..f6cf832c7 100644
--- a/src/wasm-linker.h
+++ b/src/wasm-linker.h
@@ -103,6 +103,11 @@ class LinkerObject {
wasm.memory.segments.emplace_back(0, data, size);
}
+ void addSegment(Name name, std::vector<char>& data) {
+ segments[name] = wasm.memory.segments.size();
+ wasm.memory.segments.emplace_back(0, data);
+ }
+
void addInitializerFunction(Name name) {
initializerFunctions.emplace_back(name);
assert(symbolInfo.implementedFunctions.count(name));
@@ -246,7 +251,7 @@ class Linker {
return;
}
if (out.wasm.checkExport(name)) return; // Already exported
- auto exp = out.wasm.allocator.alloc<Export>();
+ auto exp = new Export;
exp->name = exp->value = name;
out.wasm.addExport(exp);
}
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index b6a532790..a2a0e0027 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -52,7 +52,7 @@ int unhex(char c) {
//
class Element {
- typedef std::vector<Element*> List;
+ typedef ArenaVector<Element*> List;
bool isList_;
List list_;
@@ -60,8 +60,7 @@ class Element {
bool dollared_;
public:
- Element() : isList_(true) {}
- Element(MixedArena& allocator) : Element() {}
+ Element(MixedArena& allocator) : isList_(true), list_(allocator) {}
bool isList() { return isList_; }
bool isStr() { return !isList_; }
@@ -317,7 +316,7 @@ private:
}
// function parsing state
- Function *currFunction = nullptr;
+ std::unique_ptr<Function> currFunction;
std::map<Name, WasmType> currLocalTypes;
size_t localIndex; // params and vars
size_t otherIndex;
@@ -363,12 +362,12 @@ private:
Name type;
Block* autoBlock = nullptr; // we may need to add a block for the very top level
auto makeFunction = [&]() {
- currFunction = Builder(wasm).makeFunction(
+ currFunction = std::unique_ptr<Function>(Builder(wasm).makeFunction(
name,
std::move(params),
result,
std::move(vars)
- );
+ ));
};
for (;i < s.size(); i++) {
Element& curr = *s[i];
@@ -439,10 +438,9 @@ private:
assert(currFunction->result == result);
currFunction->body = body;
currFunction->type = type;
- wasm.addFunction(currFunction);
+ wasm.addFunction(currFunction.release());
currLocalTypes.clear();
labelStack.clear();
- currFunction = nullptr;
}
WasmType stringToWasmType(IString str, bool allowError=false, bool prefix=false) {
@@ -1068,7 +1066,7 @@ private:
Element& curr = *s[i];
assert(curr[0]->str() == SEGMENT);
const char *input = curr[2]->c_str();
- char *data = (char*)malloc(strlen(input)); // over-allocated, since escaping collapses, but whatever
+ char data[strlen(input)];
char *write = data;
while (1) {
if (input[0] == 0) break;
@@ -1102,7 +1100,7 @@ private:
*write++ = input[0];
input++;
}
- wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), data, write - data);
+ wasm.memory.segments.emplace_back(atoi(curr[1]->c_str()), (const char*)data, write - data);
i++;
}
}
@@ -1114,14 +1112,14 @@ private:
wasm.memory.exportName = s[1]->str();
return;
}
- auto ex = allocator.alloc<Export>();
+ std::unique_ptr<Export> ex = make_unique<Export>();
ex->name = s[1]->str();
ex->value = s[2]->str();
- wasm.addExport(ex);
+ wasm.addExport(ex.release());
}
void parseImport(Element& s) {
- auto im = allocator.alloc<Import>();
+ std::unique_ptr<Import> im = make_unique<Import>();
size_t i = 1;
if (s.size() > 3 && s[3]->isStr()) {
im->name = s[i++]->str();
@@ -1132,7 +1130,7 @@ private:
im->module = s[i++]->str();
if (!s[i]->isStr()) onError();
im->base = s[i++]->str();
- FunctionType* type = allocator.alloc<FunctionType>();
+ std::unique_ptr<FunctionType> type = make_unique<FunctionType>();
if (s.size() > i) {
Element& params = *s[i];
IString id = params[0]->str();
@@ -1155,8 +1153,8 @@ private:
type->result = stringToWasmType(result[1]->str());
}
}
- im->type = ensureFunctionType(getSig(type), &wasm);
- wasm.addImport(im);
+ im->type = ensureFunctionType(getSig(type.get()), &wasm);
+ wasm.addImport(im.release());
}
void parseTable(Element& s) {
@@ -1166,7 +1164,7 @@ private:
}
void parseType(Element& s) {
- auto type = allocator.alloc<FunctionType>();
+ std::unique_ptr<FunctionType> type = make_unique<FunctionType>();
size_t i = 1;
if (s[i]->isStr()) {
type->name = s[i]->str();
@@ -1184,7 +1182,7 @@ private:
type->result = stringToWasmType(curr[1]->str());
}
}
- wasm.addFunctionType(type);
+ wasm.addFunctionType(type.release());
}
};
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index a2e29ea77..59fea2a56 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -181,14 +181,14 @@ struct Walker : public VisitorType {
// Dispatch statically through the SubType.
SubType* self = static_cast<SubType*>(this);
- for (auto curr : module->functionTypes) {
- self->visitFunctionType(curr);
+ for (auto& curr : module->functionTypes) {
+ self->visitFunctionType(curr.get());
}
- for (auto curr : module->imports) {
- self->visitImport(curr);
+ for (auto& curr : module->imports) {
+ self->visitImport(curr.get());
}
- for (auto curr : module->exports) {
- self->visitExport(curr);
+ for (auto& curr : module->exports) {
+ self->visitExport(curr.get());
}
auto processFunction = [](SubType* instance, Function* func) {
@@ -201,8 +201,8 @@ struct Walker : public VisitorType {
// if this is not a function-parallel traversal, run
// sequentially
if (!self->isFunctionParallel()) {
- for (auto curr : module->functions) {
- processFunction(self, curr);
+ for (auto& curr : module->functions) {
+ processFunction(self, curr.get());
}
} else {
// execute in parallel on helper threads
@@ -222,7 +222,7 @@ struct Walker : public VisitorType {
if (index >= numFunctions) {
return ThreadWorkState::Finished; // nothing left
}
- Function* curr = module->functions[index];
+ Function* curr = module->functions[index].get();
// do the current task
processFunction(instance, curr);
if (index + 1 == numFunctions) {
diff --git a/src/wasm-validator.h b/src/wasm-validator.h
index 73aa7fecf..ca168e48b 100644
--- a/src/wasm-validator.h
+++ b/src/wasm-validator.h
@@ -87,9 +87,9 @@ public:
void visitMemory(Memory *curr) {
shouldBeFalse(curr->initial > curr->max);
size_t top = 0;
- for (auto segment : curr->segments) {
+ for (auto& segment : curr->segments) {
shouldBeFalse(segment.offset < top);
- top = segment.offset + segment.size;
+ top = segment.offset + segment.data.size();
}
shouldBeFalse(top > curr->initial);
}
diff --git a/src/wasm.h b/src/wasm.h
index 62b551433..b5dee81b8 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -881,12 +881,11 @@ public:
class Switch : public SpecificExpression<Expression::SwitchId> {
public:
- Switch() : condition(nullptr), value(nullptr) {}
- Switch(MixedArena& allocator) : Switch() {
+ Switch(MixedArena& allocator) : targets(allocator), condition(nullptr), value(nullptr) {
type = unreachable;
}
- std::vector<Name> targets;
+ ArenaVector<Name> targets;
Name default_;
Expression *condition;
Expression *value;
@@ -912,9 +911,9 @@ class FunctionType {
public:
Name name;
WasmType result;
- ArenaVector<WasmType> params;
+ std::vector<WasmType> params;
- FunctionType(MixedArena& allocator) : result(none), params(allocator) {}
+ FunctionType() : result(none) {}
bool operator==(FunctionType& b) {
if (name != b.name) return false; // XXX
@@ -1097,7 +1096,7 @@ public:
std::vector<Name> localNames;
std::map<Name, Index> localIndices;
- Function(MixedArena& allocator) : result(none) {}
+ Function() : result(none) {}
size_t getNumParams() {
return params.size();
@@ -1147,7 +1146,7 @@ public:
class Import {
public:
- Import(MixedArena& allocator) : type(nullptr) {}
+ Import() : type(nullptr) {}
Name name, module, base; // name = module.base
FunctionType* type;
@@ -1155,8 +1154,6 @@ public:
class Export {
public:
- Export(MixedArena& allocator) {}
-
Name name; // exported name
Name value; // internal name
};
@@ -1172,10 +1169,15 @@ public:
static const size_t kPageMask = ~(kPageSize - 1);
struct Segment {
size_t offset;
- const char* data;
- size_t size;
+ std::vector<char> data; // TODO: optimize
Segment() {}
- Segment(size_t offset, const char *data, size_t size) : offset(offset), data(data), size(size) {}
+ Segment(size_t offset, const char *init, size_t size) : offset(offset) {
+ data.resize(size);
+ memcpy(&data[0], init, size);
+ }
+ Segment(size_t offset, std::vector<char>& init) : offset(offset) {
+ data.swap(init);
+ }
};
size_t initial, max; // sizes are in pages
@@ -1188,10 +1190,10 @@ public:
class Module {
public:
// wasm contents (generally you shouldn't access these from outside, except maybe for iterating; use add*() and the get() functions)
- std::vector<FunctionType*> functionTypes;
- std::vector<Import*> imports;
- std::vector<Export*> exports;
- std::vector<Function*> functions;
+ std::vector<std::unique_ptr<FunctionType>> functionTypes;
+ std::vector<std::unique_ptr<Import>> imports;
+ std::vector<std::unique_ptr<Export>> exports;
+ std::vector<std::unique_ptr<Function>> functions;
Table table;
Memory memory;
@@ -1209,10 +1211,10 @@ private:
public:
Module() : functionTypeIndex(0), importIndex(0), exportIndex(0), functionIndex(0) {}
- FunctionType* getFunctionType(size_t i) { assert(i < functionTypes.size());return functionTypes[i]; }
- Import* getImport(size_t i) { assert(i < imports.size()); return imports[i]; }
- Export* getExport(size_t i) { assert(i < exports.size()); return exports[i]; }
- Function* getFunction(size_t i) { assert(i < functions.size()); return functions[i]; }
+ FunctionType* getFunctionType(size_t i) { assert(i < functionTypes.size()); return functionTypes[i].get(); }
+ Import* getImport(size_t i) { assert(i < imports.size()); return imports[i].get(); }
+ Export* getExport(size_t i) { assert(i < exports.size()); return exports[i].get(); }
+ Function* getFunction(size_t i) { assert(i < functions.size()); return functions[i].get(); }
FunctionType* getFunctionType(Name name) { assert(functionTypesMap[name]); return functionTypesMap[name]; }
Import* getImport(Name name) { assert(importsMap[name]); return importsMap[name]; }
@@ -1229,7 +1231,7 @@ public:
if (curr->name.isNull()) {
curr->name = numericName;
}
- functionTypes.push_back(curr);
+ functionTypes.push_back(std::unique_ptr<FunctionType>(curr));
functionTypesMap[curr->name] = curr;
functionTypesMap[numericName] = curr;
functionTypeIndex++;
@@ -1239,7 +1241,7 @@ public:
if (curr->name.isNull()) {
curr->name = numericName;
}
- imports.push_back(curr);
+ imports.push_back(std::unique_ptr<Import>(curr));
importsMap[curr->name] = curr;
importsMap[numericName] = curr;
importIndex++;
@@ -1249,7 +1251,7 @@ public:
if (curr->name.isNull()) {
curr->name = numericName;
}
- exports.push_back(curr);
+ exports.push_back(std::unique_ptr<Export>(curr));
exportsMap[curr->name] = curr;
exportsMap[numericName] = curr;
exportIndex++;
@@ -1259,7 +1261,7 @@ public:
if (curr->name.isNull()) {
curr->name = numericName;
}
- functions.push_back(curr);
+ functions.push_back(std::unique_ptr<Function>(curr));
functionsMap[curr->name] = curr;
functionsMap[numericName] = curr;
functionIndex++;
diff --git a/src/wasm2asm.h b/src/wasm2asm.h
index 82eb0b1a9..e0b071f9b 100644
--- a/src/wasm2asm.h
+++ b/src/wasm2asm.h
@@ -205,8 +205,8 @@ Ref Wasm2AsmBuilder::processWasm(Module* wasm) {
asmFunc[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeString(USE_ASM)));
// create heaps, etc
addBasics(asmFunc[3]);
- for (auto import : wasm->imports) {
- addImport(asmFunc[3], import);
+ for (auto& import : wasm->imports) {
+ addImport(asmFunc[3], import.get());
}
// figure out the table size
tableSize = wasm->table.names.size();
@@ -216,8 +216,8 @@ Ref Wasm2AsmBuilder::processWasm(Module* wasm) {
}
tableSize = pow2ed;
// functions
- for (auto func : wasm->functions) {
- asmFunc[3]->push_back(processFunction(func));
+ for (auto& func : wasm->functions) {
+ asmFunc[3]->push_back(processFunction(func.get()));
}
addTables(asmFunc[3], wasm);
// memory XXX
@@ -320,7 +320,7 @@ void Wasm2AsmBuilder::addTables(Ref ast, Module *wasm) {
void Wasm2AsmBuilder::addExports(Ref ast, Module *wasm) {
Ref exports = ValueBuilder::makeObject();
- for (auto export_ : wasm->exports) {
+ for (auto& export_ : wasm->exports) {
ValueBuilder::appendToObject(exports, fromName(export_->name), ValueBuilder::makeName(fromName(export_->value)));
}
ast->push_back(ValueBuilder::makeStatement(ValueBuilder::makeReturn(exports)));