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);