From 127f9688cc26ab362dabadac5494af23cd78ac8b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 27 Apr 2016 10:43:21 -0700 Subject: allocate only expressions in arenas - functions, imports, exports, function types, can more simply be held by unique_ptrs on the owning module. this avoids need to coordinate arena allocation for their elements, and only the far more plentiful expression nodes are a perf factor anyhow --- src/wasm-binary.h | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 3f7ad44d4..9d4f567b0 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -447,9 +447,9 @@ class WasmBinaryWriter : public Visitor { 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); @@ -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(); + 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(); + 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(); + auto curr = new Export; auto index = getU32LEB(); assert(index < functionTypes.size()); curr->name = getInlineString(); @@ -1774,7 +1773,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); -- cgit v1.2.3 From f22e2796f5ac72c64c36cb562d1462093741f8d7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 27 Apr 2016 14:54:30 -0700 Subject: just use a simple vector in data segments --- src/passes/Print.cpp | 2 +- src/s2wasm.h | 42 +++++++++++++++++++++--------------------- src/shell-interface.h | 6 +++--- src/wasm-binary.h | 14 ++++++-------- src/wasm-linker.cpp | 9 +++++---- src/wasm-linker.h | 5 +++++ src/wasm-validator.h | 4 ++-- src/wasm.h | 11 ++++++++--- 8 files changed, 51 insertions(+), 42 deletions(-) (limited to 'src/wasm-binary.h') diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 256968bb7..1a62de4f3 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -485,7 +485,7 @@ struct PrintSExpression : public Visitor { 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; 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(); // leaked intentionally, no new allocation in Memory + std::vector raw; bool zero = true; std::vector> 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 9d4f567b0..91fe91b49 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -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); } @@ -1548,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); } } diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index 334ea475d..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 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(raw), pointerSize); + out.addSegment("__stack_pointer", raw); } } @@ -238,7 +239,7 @@ void Linker::emscriptenGlue(std::ostream& o) { if (curr->target == EMSCRIPTEN_ASM_CONST) { auto arg = curr->operands[0]->cast(); 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(); diff --git a/src/wasm-linker.h b/src/wasm-linker.h index 07f270d69..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& 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)); 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 45a01bd76..b5dee81b8 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1169,10 +1169,15 @@ public: static const size_t kPageMask = ~(kPageSize - 1); struct Segment { size_t offset; - const char* data; - size_t size; + std::vector 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& init) : offset(offset) { + data.swap(init); + } }; size_t initial, max; // sizes are in pages -- cgit v1.2.3