summaryrefslogtreecommitdiff
path: root/src/emscripten-optimizer
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-05-16 16:35:12 -0700
committerGitHub <noreply@github.com>2017-05-16 16:35:12 -0700
commit6331e094380bc538cc7dcd5a716968b764939f81 (patch)
tree9b6974af153f404f20d4c49e9eb27a5055406b7f /src/emscripten-optimizer
parent77802a63e5814bcde5ac9af3f4694507d8bae9e9 (diff)
downloadbinaryen-6331e094380bc538cc7dcd5a716968b764939f81.tar.gz
binaryen-6331e094380bc538cc7dcd5a716968b764939f81.tar.bz2
binaryen-6331e094380bc538cc7dcd5a716968b764939f81.zip
Parallelize istring creation (#1008)
* parallelize istring creation, by having a thread-local set and a global set guarded by a mutex. each time a new string shows up in a thread, it will be added to that thread's set, after accessing the global set through the lock first, which means we lock at most once per new string per thread * don't leak strings in istring store * since we now create names in a parallel thread-safe manner, we don't need to pre-create names in RelooperJumpThreading
Diffstat (limited to 'src/emscripten-optimizer')
-rw-r--r--src/emscripten-optimizer/istring.h43
1 files changed, 29 insertions, 14 deletions
diff --git a/src/emscripten-optimizer/istring.h b/src/emscripten-optimizer/istring.h
index e47361eeb..b991159e5 100644
--- a/src/emscripten-optimizer/istring.h
+++ b/src/emscripten-optimizer/istring.h
@@ -30,6 +30,7 @@
#include <assert.h>
#include "support/threads.h"
+#include "support/utilities.h"
namespace cashew {
@@ -66,21 +67,35 @@ struct IString {
void set(const char *s, bool reuse=true) {
typedef std::unordered_set<const char *, CStringHash, CStringEqual> StringSet;
- static StringSet* strings = new StringSet();
-
- auto existing = strings->find(s);
-
- if (existing == strings->end()) {
- // the StringSet cache is a global shared structure, which should
- // not be modified by multiple threads at once.
- assert(!wasm::ThreadPool::isRunning());
- if (!reuse) {
- size_t len = strlen(s) + 1;
- char *copy = (char*)malloc(len); // XXX leaked
- strncpy(copy, s, len);
- s = copy;
+ // one global store of strings per thread, we must not access this
+ // in parallel
+ thread_local static StringSet strings;
+
+ auto existing = strings.find(s);
+
+ if (existing == strings.end()) {
+ // if the string isn't already known, we must use a single global
+ // storage location, guarded by a mutex, so each string is allocated
+ // exactly once
+ static std::mutex mutex;
+ std::unique_lock<std::mutex> lock(mutex);
+ // a single global set contains the actual strings, so we allocate each one
+ // exactly once.
+ static StringSet globalStrings;
+ auto globalExisting = globalStrings.find(s);
+ if (globalExisting == globalStrings.end()) {
+ if (!reuse) {
+ static std::vector<std::unique_ptr<std::string>> allocated;
+ allocated.emplace_back(wasm::make_unique<std::string>(s));
+ s = allocated.back()->c_str(); // we'll never modify it, so this is ok
+ }
+ // insert into global set
+ globalStrings.insert(s);
+ } else {
+ s = *globalExisting;
}
- strings->insert(s);
+ // add the string to our thread-local set
+ strings.insert(s);
} else {
s = *existing;
}