Fix initializing the allocator before creating empty vector.
MSVC's implementation of the STL allocates memory even for an empty
vector. Since we're using a custom thread-local allocator, it should
be initialized before any STL member containers get initialized.
BUG=swiftshader:7
Change-Id: I4bd977e7ee8eb87006fe08b051cbcfc9bc62342b
Reviewed-on: https://chromium-review.googlesource.com/381531
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Jim Stichnoth <stichnot@chromium.org>
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index 6e944ac..ef775fe 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -22,8 +22,8 @@
#include "IceELFObjectWriter.h"
#include "IceGlobalInits.h"
#include "IceInst.h"
-#include "IceInstrumentation.h"
#include "IceInstVarIter.h"
+#include "IceInstrumentation.h"
#include "IceLiveness.h"
#include "IceLoopAnalyzer.h"
#include "IceOperand.h"
@@ -35,9 +35,9 @@
namespace Ice {
Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber)
- : Ctx(Ctx), SequenceNumber(SequenceNumber), VMask(getFlags().getVerbose()),
- FunctionName(), NextInstNumber(Inst::NumberInitial), Live(nullptr) {
- Allocator.reset(new ArenaAllocator());
+ : Allocator(createAllocator()), Ctx(Ctx), SequenceNumber(SequenceNumber),
+ VMask(getFlags().getVerbose()), FunctionName(),
+ NextInstNumber(Inst::NumberInitial), Live(nullptr) {
NodeStrings.reset(new StringPool);
VarStrings.reset(new StringPool);
CfgLocalAllocatorScope _(this);
@@ -65,6 +65,15 @@
}
}
+// Called in the initalizer list of Cfg's constructor to create the Allocator
+// and set it as TLS before any other member fields are constructed, since they
+// may depend on it.
+ArenaAllocator *Cfg::createAllocator() {
+ ArenaAllocator *Allocator = new ArenaAllocator();
+ CfgAllocatorTraits::set_current(Allocator);
+ return Allocator;
+}
+
/// Create a string like "foo(i=123:b=9)" indicating the function name, number
/// of high-level instructions, and number of basic blocks. This string is only
/// used for dumping and other diagnostics, and the idea is that given a set of
diff --git a/src/IceCfg.h b/src/IceCfg.h
index 933d64c..3a3dcbf 100644
--- a/src/IceCfg.h
+++ b/src/IceCfg.h
@@ -31,6 +31,8 @@
Cfg(const Cfg &) = delete;
Cfg &operator=(const Cfg &) = delete;
+ std::unique_ptr<ArenaAllocator> Allocator;
+
public:
~Cfg();
@@ -306,6 +308,8 @@
CfgVector<Inst *>
findLoopInvariantInstructions(const CfgUnorderedSet<SizeT> &Body);
+ static ArenaAllocator *createAllocator();
+
GlobalContext *Ctx;
uint32_t SequenceNumber; /// output order for emission
OptLevel OptimizationLevel = Opt_m1;
@@ -323,7 +327,6 @@
VarList Variables;
VarList Args; /// subset of Variables, in argument order
VarList ImplicitArgs; /// subset of Variables
- std::unique_ptr<ArenaAllocator> Allocator;
// Separate string pools for CfgNode and Variable names, due to a combination
// of the uniqueness requirement, and assumptions in lit tests.
std::unique_ptr<StringPool> NodeStrings;
diff --git a/src/IceMemory.cpp b/src/IceMemory.cpp
index 57c969e..0026661 100644
--- a/src/IceMemory.cpp
+++ b/src/IceMemory.cpp
@@ -31,9 +31,17 @@
void CfgAllocatorTraits::set_current(const manager_type *Manager) {
ArenaAllocator *Allocator =
Manager == nullptr ? nullptr : Manager->Allocator.get();
+ set_current(Allocator);
+}
+
+void CfgAllocatorTraits::set_current(ArenaAllocator *Allocator) {
ICE_TLS_SET_FIELD(CfgAllocator, Allocator);
}
+void CfgAllocatorTraits::set_current(nullptr_t) {
+ ICE_TLS_SET_FIELD(CfgAllocator, nullptr);
+}
+
ICE_TLS_DEFINE_FIELD(ArenaAllocator *, LivenessAllocatorTraits,
LivenessAllocator);
diff --git a/src/IceMemory.h b/src/IceMemory.h
index 7fff65c..366c49d 100644
--- a/src/IceMemory.h
+++ b/src/IceMemory.h
@@ -143,6 +143,8 @@
static allocator_type current();
static void set_current(const manager_type *Manager);
+ static void set_current(ArenaAllocator *Allocator);
+ static void set_current(nullptr_t);
private:
ICE_TLS_DECLARE_FIELD(ArenaAllocator *, CfgAllocator);