diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-04-27 19:25:15 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-04-27 19:25:15 -0700 |
commit | 6a6bdc1cef5ec35cb9f7caf6e10ec76ee1107d0d (patch) | |
tree | 9ed1b23b55c86f8fa1aee285bfdde9d47c2f1ae8 | |
parent | 4a85f62e8a83117a081e9691d8830b6a7a876d1d (diff) | |
parent | f0a4f15dc27ffff9505503a8168854b7662b2657 (diff) | |
download | binaryen-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.yml | 2 | ||||
-rw-r--r-- | src/asm2wasm.h | 29 | ||||
-rw-r--r-- | src/asm_v_wasm.h | 2 | ||||
-rw-r--r-- | src/asmjs/asm_v_wasm.cpp | 6 | ||||
-rw-r--r-- | src/binaryen-shell.cpp | 12 | ||||
-rw-r--r-- | src/emscripten-optimizer/istring.h | 4 | ||||
-rw-r--r-- | src/emscripten-optimizer/parser.cpp | 26 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.cpp | 9 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.h | 1 | ||||
-rw-r--r-- | src/passes/Print.cpp | 10 | ||||
-rw-r--r-- | src/passes/RemoveImports.cpp | 9 | ||||
-rw-r--r-- | src/s2wasm.h | 42 | ||||
-rw-r--r-- | src/shell-interface.h | 6 | ||||
-rw-r--r-- | src/wasm-binary.h | 43 | ||||
-rw-r--r-- | src/wasm-builder.h | 2 | ||||
-rw-r--r-- | src/wasm-linker.cpp | 15 | ||||
-rw-r--r-- | src/wasm-linker.h | 7 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 34 | ||||
-rw-r--r-- | src/wasm-traversal.h | 18 | ||||
-rw-r--r-- | src/wasm-validator.h | 4 | ||||
-rw-r--r-- | src/wasm.h | 50 | ||||
-rw-r--r-- | src/wasm2asm.h | 10 |
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))); |