summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/emscripten-optimizer/simple_ast.cpp45
-rw-r--r--src/emscripten-optimizer/simple_ast.h78
-rw-r--r--src/mixed_arena.h76
-rw-r--r--src/passes/MergeBlocks.cpp2
-rw-r--r--src/wasm-linker.cpp5
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;
}
}