Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(620)

Unified Diff: src/IceDefs.h

Issue 1776473007: Subzero. Allocate global initializers from a dedicated arena. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Removes global variable (and initializer) allocation methods from GlobalContext. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceConverter.cpp ('k') | src/IceELFObjectWriter.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceDefs.h
diff --git a/src/IceDefs.h b/src/IceDefs.h
index d9c0c234784e0d569ae6c83ed109bb981d37749f..eaf0dc02434c432fd0fb883a2596da0821e7fd56 100644
--- a/src/IceDefs.h
+++ b/src/IceDefs.h
@@ -73,6 +73,11 @@ class Variable;
class VariableDeclaration;
class VariablesMetadata;
+/// SizeT is for holding small-ish limits like number of source operands in an
+/// instruction. It is used instead of size_t (which may be 64-bits wide) when
+/// we want to save space.
+using SizeT = uint32_t;
+
constexpr char GlobalOffsetTable[] = "_GLOBAL_OFFSET_TABLE_";
// makeUnique should be used when memory is expected to be allocated from the
// heap (as opposed to allocated from some Allocator.) It is intended to be
@@ -139,12 +144,127 @@ using NodeList = CfgVector<CfgNode *>;
// Containers that use the default (global) allocator.
using ConstantList = std::vector<Constant *>;
using FunctionDeclarationList = std::vector<FunctionDeclaration *>;
-using VariableDeclarationList = std::vector<VariableDeclaration *>;
-/// SizeT is for holding small-ish limits like number of source operands in an
-/// instruction. It is used instead of size_t (which may be 64-bits wide) when
-/// we want to save space.
-using SizeT = uint32_t;
+/// VariableDeclarationList is a container for holding VariableDeclarations --
+/// i.e., Global Variables. It is also used to create said variables, and their
+/// initializers in an arena.
+class VariableDeclarationList {
+ VariableDeclarationList(const VariableDeclarationList &) = delete;
+ VariableDeclarationList &operator=(const VariableDeclarationList &) = delete;
+ VariableDeclarationList(VariableDeclarationList &&) = delete;
+ VariableDeclarationList &operator=(VariableDeclarationList &&) = delete;
+
+public:
+ using VariableDeclarationArray = std::vector<VariableDeclaration *>;
+
+ VariableDeclarationList() : Arena(new ArenaAllocator()) {}
+
+ ~VariableDeclarationList() { clearAndPurge(); }
+
+ template <typename T> T *allocate_initializer(SizeT Count = 1) {
+ static_assert(
+ std::is_trivially_destructible<T>::value,
+ "allocate_initializer can only allocate trivially destructible types.");
+ return Arena->Allocate<T>(Count);
+ }
+
+ template <typename T> T *allocate_variable_declaration() {
+ static_assert(!std::is_trivially_destructible<T>::value,
+ "allocate_variable_declaration expects non-trivially "
+ "destructible types.");
+ T *Ret = Arena->Allocate<T>();
+ Dtors.emplace_back([Ret]() { Ret->~T(); });
+ return Ret;
+ }
+
+ // This do nothing method is invoked when a global variable is created, but it
+ // will not be emitted. If we ever need to track the created variabled, having
+ // this hook is handy.
+ void willNotBeEmitted(VariableDeclaration *) {}
+
+ /// Merges Other with this, effectively resetting Other to an empty state.
+ void merge(VariableDeclarationList *Other) {
+ assert(Other != nullptr);
+ addArena(std::move(Other->Arena));
+ for (std::size_t i = 0; i < Other->MergedArenas.size(); ++i) {
+ addArena(std::move(Other->MergedArenas[i]));
+ }
+ Other->MergedArenas.clear();
+
+ Dtors.insert(Dtors.end(), Other->Dtors.begin(), Other->Dtors.end());
+ Other->Dtors.clear();
+
+ Globals.insert(Globals.end(), Other->Globals.begin(), Other->Globals.end());
+ Other->Globals.clear();
+ }
+
+ /// Destroys all GlobalVariables and initializers that this knows about
+ /// (including those merged with it), and releases memory.
+ void clearAndPurge() {
+ if (Arena == nullptr) {
+ // Arena is only null if this was merged, so we ensure there's no state
+ // being held by this.
+ assert(Dtors.empty());
+ assert(Globals.empty());
+ assert(MergedArenas.empty());
+ return;
+ }
+ // Invokes destructors in reverse creation order.
+ for (auto Dtor = Dtors.rbegin(); Dtor != Dtors.rend(); ++Dtor) {
+ (*Dtor)();
+ }
+ Dtors.clear();
+ Globals.clear();
+ MergedArenas.clear();
+ Arena->Reset();
+ }
+
+ /// Adapt the relevant parts of the std::vector<VariableDeclaration *>
+ /// interface.
+ /// @{
+ VariableDeclarationArray::iterator begin() { return Globals.begin(); }
+
+ VariableDeclarationArray::iterator end() { return Globals.end(); }
+
+ VariableDeclarationArray::const_iterator begin() const {
+ return Globals.begin();
+ }
+
+ VariableDeclarationArray::const_iterator end() const { return Globals.end(); }
+
+ bool empty() const { return Globals.empty(); }
+
+ VariableDeclarationArray::size_type size() const { return Globals.size(); }
+
+ VariableDeclarationArray::reference
+ at(VariableDeclarationArray::size_type Pos) {
+ return Globals.at(Pos);
+ }
+
+ void push_back(VariableDeclaration *Global) { Globals.push_back(Global); }
+
+ void reserve(VariableDeclarationArray::size_type Capacity) {
+ Globals.reserve(Capacity);
+ }
+
+ void clear() { Globals.clear(); }
+
+ VariableDeclarationArray::reference back() { return Globals.back(); }
+ /// @}
+
+private:
+ using ArenaPtr = std::unique_ptr<ArenaAllocator>;
+ using DestructorsArray = std::vector<std::function<void()>>;
+
+ void addArena(ArenaPtr NewArena) {
+ MergedArenas.emplace_back(std::move(NewArena));
+ }
+
+ ArenaPtr Arena;
+ VariableDeclarationArray Globals;
+ DestructorsArray Dtors;
+ std::vector<ArenaPtr> MergedArenas;
+};
/// InstNumberT is for holding an instruction number. Instruction numbers are
/// used for representing Variable live ranges.
« no previous file with comments | « src/IceConverter.cpp ('k') | src/IceELFObjectWriter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698