diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/emscripten-optimizer/simple_ast.cpp | 45 | ||||
-rw-r--r-- | src/emscripten-optimizer/simple_ast.h | 78 | ||||
-rw-r--r-- | src/mixed_arena.h | 76 | ||||
-rw-r--r-- | src/passes/MergeBlocks.cpp | 2 | ||||
-rw-r--r-- | src/wasm-linker.cpp | 5 |
5 files changed, 99 insertions, 107 deletions
diff --git a/src/emscripten-optimizer/simple_ast.cpp b/src/emscripten-optimizer/simple_ast.cpp index 4f36036ae..7379e9740 100644 --- a/src/emscripten-optimizer/simple_ast.cpp +++ b/src/emscripten-optimizer/simple_ast.cpp @@ -54,32 +54,7 @@ bool Ref::operator!() { // Arena -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]); - index = 0; - } - return &chunks.back()[index++]; -} - -ArrayStorage* Arena::allocArray() { - if (arr_chunks.size() == 0 || arr_index == CHUNK_SIZE) { - arr_chunks.push_back(new ArrayStorage[CHUNK_SIZE]); - arr_index = 0; - } - return &arr_chunks.back()[arr_index++]; -} +GlobalMixedArena arena; // dump @@ -161,7 +136,7 @@ void traversePre(Ref node, std::function<void (Ref)> visit) { int index = 0; ArrayStorage* arr = &node->getArray(); int arrsize = (int)arr->size(); - Ref* arrdata = arr->data(); + Ref* arrdata = &(*arr)[0]; stack.push_back(TraverseInfo(node, arr)); while (1) { if (index < arrsize) { @@ -173,7 +148,7 @@ void traversePre(Ref node, std::function<void (Ref)> visit) { visit(sub); arr = &sub->getArray(); arrsize = (int)arr->size(); - arrdata = arr->data(); + arrdata = &(*arr)[0]; stack.push_back(TraverseInfo(sub, arr)); } } else { @@ -183,7 +158,7 @@ void traversePre(Ref node, std::function<void (Ref)> visit) { index = back.index; arr = back.arr; arrsize = (int)arr->size(); - arrdata = arr->data(); + arrdata = &(*arr)[0]; } } } @@ -196,7 +171,7 @@ void traversePrePost(Ref node, std::function<void (Ref)> visitPre, std::function int index = 0; ArrayStorage* arr = &node->getArray(); int arrsize = (int)arr->size(); - Ref* arrdata = arr->data(); + Ref* arrdata = &(*arr)[0]; stack.push_back(TraverseInfo(node, arr)); while (1) { if (index < arrsize) { @@ -208,7 +183,7 @@ void traversePrePost(Ref node, std::function<void (Ref)> visitPre, std::function visitPre(sub); arr = &sub->getArray(); arrsize = (int)arr->size(); - arrdata = arr->data(); + arrdata = &(*arr)[0]; stack.push_back(TraverseInfo(sub, arr)); } } else { @@ -219,7 +194,7 @@ void traversePrePost(Ref node, std::function<void (Ref)> visitPre, std::function index = back.index; arr = back.arr; arrsize = (int)arr->size(); - arrdata = arr->data(); + arrdata = &(*arr)[0]; } } } @@ -232,7 +207,7 @@ void traversePrePostConditional(Ref node, std::function<bool (Ref)> visitPre, st int index = 0; ArrayStorage* arr = &node->getArray(); int arrsize = (int)arr->size(); - Ref* arrdata = arr->data(); + Ref* arrdata = &(*arr)[0]; stack.push_back(TraverseInfo(node, arr)); while (1) { if (index < arrsize) { @@ -244,7 +219,7 @@ void traversePrePostConditional(Ref node, std::function<bool (Ref)> visitPre, st index = 0; arr = &sub->getArray(); arrsize = (int)arr->size(); - arrdata = arr->data(); + arrdata = &(*arr)[0]; stack.push_back(TraverseInfo(sub, arr)); } } @@ -256,7 +231,7 @@ void traversePrePostConditional(Ref node, std::function<bool (Ref)> visitPre, st index = back.index; arr = back.arr; arrsize = (int)arr->size(); - arrdata = arr->data(); + arrdata = &(*arr)[0]; } } } diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index e89ddb666..f4dce76aa 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -36,6 +36,7 @@ #include "parser.h" #include "snprintf.h" #include "support/safe_integer.h" +#include "mixed_arena.h" #define err(str) fprintf(stderr, str "\n"); #define errv(str, ...) fprintf(stderr, str "\n", __VA_ARGS__); @@ -73,25 +74,28 @@ struct Ref { // Arena allocation, free it all on process exit -typedef std::vector<Ref> ArrayStorage; - -struct Arena { - #define CHUNK_SIZE 1000 - std::vector<Value*> chunks; - int index; // in last chunk - - std::vector<ArrayStorage*> arr_chunks; - int arr_index; +// A mixed arena for global allocation only, so members do not +// receive an allocator, they all use the global one anyhow +class GlobalMixedArena : public MixedArena { +public: + template<class T> + T* alloc() { + auto* ret = static_cast<T*>(allocSpace(sizeof(T))); + new (ret) T(); + return ret; + } +}; - Arena() : index(0), arr_index(0) {} - ~Arena(); +extern GlobalMixedArena arena; - Ref alloc(); - ArrayStorage* allocArray(); +class ArrayStorage : public ArenaVectorBase<ArrayStorage, Ref> { +public: + void allocate(size_t size) { + allocatedElements = size; + data = static_cast<Ref*>(arena.allocSpace(sizeof(Ref) * allocatedElements)); + } }; -extern Arena arena; - // Main value type struct Value { enum Type { @@ -139,7 +143,7 @@ struct Value { } void free() { - if (type == Array) { arr->clear(); arr->shrink_to_fit(); } + if (type == Array) { arr->clear(); } else if (type == Object) delete obj; type = Null; num = 0; @@ -166,14 +170,14 @@ struct Value { Value& setArray(ArrayStorage &a) { free(); type = Array; - arr = arena.allocArray(); + arr = arena.alloc<ArrayStorage>(); *arr = a; return *this; } Value& setArray(size_t size_hint=0) { free(); type = Array; - arr = arena.allocArray(); + arr = arena.alloc<ArrayStorage>(); arr->reserve(size_hint); return *this; } @@ -322,7 +326,7 @@ struct Value { skip(); setArray(); while (*curr != ']') { - Ref temp = arena.alloc(); + Ref temp = arena.alloc<Value>(); arr->push_back(temp); curr = temp->parse(curr); skip(); @@ -364,7 +368,7 @@ struct Value { assert(*curr == ':'); curr++; skip(); - Ref value = arena.alloc(); + Ref value = arena.alloc<Value>(); curr = value->parse(curr); (*obj)[key] = value; skip(); @@ -473,14 +477,14 @@ struct Value { if (old != size) arr->resize(size); if (old < size) { for (auto i = old; i < size; i++) { - (*arr)[i] = arena.alloc(); + (*arr)[i] = arena.alloc<Value>(); } } } Ref& operator[](unsigned x) { assert(isArray()); - return arr->at(x); + return (*arr)[x]; } Value& push_back(Ref r) { @@ -501,18 +505,6 @@ struct Value { return arr->back(); } - void splice(int x, int num) { - assert(isArray()); - arr->erase(arr->begin() + x, arr->begin() + x + num); - } - - void insert(int x, int num) { - arr->insert(arr->begin() + x, num, Ref()); - } - void insert(int x, Ref node) { - arr->insert(arr->begin() + x, 1, node); - } - int indexOf(Ref other) { assert(isArray()); for (size_t i = 0; i < arr->size(); i++) { @@ -523,7 +515,7 @@ struct Value { Ref map(std::function<Ref (Ref node)> func) { assert(isArray()); - Ref ret = arena.alloc(); + Ref ret = arena.alloc<Value>(); ret->setArray(); for (size_t i = 0; i < arr->size(); i++) { ret->push_back(func((*arr)[i])); @@ -533,7 +525,7 @@ struct Value { Ref filter(std::function<bool (Ref node)> func) { assert(isArray()); - Ref ret = arena.alloc(); + Ref ret = arena.alloc<Value>(); ret->setArray(); for (size_t i = 0; i < arr->size(); i++) { Ref curr = (*arr)[i]; @@ -1332,16 +1324,16 @@ class ValueBuilder { static IStringSet statable; static Ref makeRawString(const IString& s) { - return &arena.alloc()->setString(s); + return &arena.alloc<Value>()->setString(s); } static Ref makeNull() { - return &arena.alloc()->setNull(); + return &arena.alloc<Value>()->setNull(); } public: static Ref makeRawArray(int size_hint=0) { - return &arena.alloc()->setArray(size_hint); + return &arena.alloc<Value>()->setArray(size_hint); } static Ref makeToplevel() { @@ -1471,7 +1463,7 @@ public: } static Ref makeDouble(double num) { - return &arena.alloc()->setNumber(num); + return &arena.alloc<Value>()->setNumber(num); } static Ref makeInt(uint32_t num) { return makeDouble(double(num)); @@ -1489,7 +1481,7 @@ public: static Ref makeBinary(Ref left, IString op, Ref right) { if (op == SET) { return &makeRawArray(4)->push_back(makeRawString(ASSIGN)) - .push_back(&arena.alloc()->setBool(true)) + .push_back(&arena.alloc<Value>()->setBool(true)) .push_back(left) .push_back(right); } else if (op == COMMA) { @@ -1670,13 +1662,13 @@ public: static Ref makeAssign(Ref target, Ref value) { return &makeRawArray(3)->push_back(makeRawString(ASSIGN)) - .push_back(&arena.alloc()->setBool(true)) + .push_back(&arena.alloc<Value>()->setBool(true)) .push_back(target) .push_back(value); } static Ref makeAssign(IString target, Ref value) { return &makeRawArray(3)->push_back(makeRawString(ASSIGN)) - .push_back(&arena.alloc()->setBool(true)) + .push_back(&arena.alloc<Value>()->setBool(true)) .push_back(makeName(target)) .push_back(value); } diff --git a/src/mixed_arena.h b/src/mixed_arena.h index 28b2dd462..52e47fbde 100644 --- a/src/mixed_arena.h +++ b/src/mixed_arena.h @@ -144,39 +144,24 @@ struct MixedArena { // // A vector that allocates in an arena. // -// TODO: consider not saving the allocator, but requiring it be -// passed in when needed, would make this (and thus Blocks etc. -// smaller) -// // TODO: specialize on the initial size of the array -template <typename T> -class ArenaVector { - MixedArena& allocator; +template <typename SubType, typename T> +class ArenaVectorBase { +protected: T* data = nullptr; size_t usedElements = 0, allocatedElements = 0; - void allocate(size_t size) { - allocatedElements = size; - data = static_cast<T*>(allocator.allocSpace(sizeof(T) * allocatedElements)); - } - void reallocate(size_t size) { T* old = data; - allocate(size); + static_cast<SubType*>(this)->allocate(size); for (size_t i = 0; i < usedElements; i++) { data[i] = old[i]; } } public: - ArenaVector(MixedArena& allocator) : allocator(allocator) {} - - ArenaVector(ArenaVector<T>&& other) : allocator(other.allocator) { - *this = other; - } - T& operator[](size_t index) const { assert(index < usedElements); return data[index]; @@ -216,11 +201,21 @@ public: usedElements++; } + void clear() { + usedElements = 0; + } + + void reserve(size_t size) { + if (size > allocatedElements) { + reallocate(size); + } + } + template<typename ListType> void set(const ListType& list) { size_t size = list.size(); if (allocatedElements < size) { - allocate(size); + static_cast<SubType*>(this)->allocate(size); } for (size_t i = 0; i < size; i++) { data[i] = list[i]; @@ -228,14 +223,15 @@ public: usedElements = size; } - void operator=(ArenaVector<T>& other) { + void operator=(SubType& other) { set(other); } - void operator=(ArenaVector<T>&& other) { + void swap(SubType& other) { data = other.data; usedElements = other.usedElements; allocatedElements = other.allocatedElements; + other.data = nullptr; other.usedElements = other.allocatedElements = 0; } @@ -243,10 +239,10 @@ public: // iteration struct Iterator { - const ArenaVector<T>* parent; + const SubType* parent; size_t index; - Iterator(const ArenaVector<T>* parent, size_t index) : parent(parent), index(index) {} + Iterator(const SubType* parent, size_t index) : parent(parent), index(index) {} bool operator!=(const Iterator& other) const { return index != other.index || parent != other.parent; @@ -262,10 +258,38 @@ public: }; Iterator begin() const { - return Iterator(this, 0); + return Iterator(static_cast<const SubType*>(this), 0); } Iterator end() const { - return Iterator(this, usedElements); + return Iterator(static_cast<const SubType*>(this), usedElements); + } + + void allocate(size_t size) { + abort(); // must be implemented in children + } +}; + +// A vector that has an allocator for arena allocation +// +// TODO: consider not saving the allocator, but requiring it be +// passed in when needed, would make this (and thus Blocks etc. +// smaller) + +template <typename T> +class ArenaVector : public ArenaVectorBase<ArenaVector<T>, T> { +private: + MixedArena& allocator; + +public: + ArenaVector(MixedArena& allocator) : allocator(allocator) {} + + ArenaVector(ArenaVector<T>&& other) : allocator(other.allocator) { + *this = other; + } + + void allocate(size_t size) { + this->allocatedElements = size; + this->data = static_cast<T*>(allocator.allocSpace(sizeof(T) * this->allocatedElements)); } }; diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp index 467ffb4ed..383837beb 100644 --- a/src/passes/MergeBlocks.cpp +++ b/src/passes/MergeBlocks.cpp @@ -190,7 +190,7 @@ static void optimizeBlock(Block* curr, Module* module) { for (size_t j = i + 1; j < curr->list.size(); j++) { merged.push_back(curr->list[j]); } - curr->list = merged; + curr->list.swap(merged); more = true; changed = true; break; diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index 757fc88ca..c2fc00562 100644 --- a/src/wasm-linker.cpp +++ b/src/wasm-linker.cpp @@ -82,11 +82,12 @@ void Linker::layout() { // behavior. for (auto* call : f.second) { auto type = call->type; - auto operands = std::move(call->operands); + ExpressionList operands(out.wasm.allocator); + operands.swap(call->operands); auto target = call->target; CallImport* newCall = ExpressionManipulator::convert<Call, CallImport>(call, out.wasm.allocator); newCall->type = type; - newCall->operands = std::move(operands); + newCall->operands.swap(operands); newCall->target = target; } } |