Improvements to initialization of linker_allocator

Make linker_allocator independent of the order of global constructors.

Bug: http://b/30483811
Change-Id: I18a323175661b8e1c9e398f2d6112f7a08d2cceb
Test: boot the device with I3ac91758a1a043146c65f2ae0f36fcfbe372c30f
diff --git a/linker/linker_allocator.cpp b/linker/linker_allocator.cpp
index 7deddea..dc6dfc1 100644
--- a/linker/linker_allocator.cpp
+++ b/linker/linker_allocator.cpp
@@ -70,8 +70,8 @@
   return result;
 }
 
-LinkerSmallObjectAllocator::LinkerSmallObjectAllocator()
-    : type_(0), block_size_(0), free_pages_cnt_(0), free_blocks_list_(nullptr) {}
+LinkerSmallObjectAllocator::LinkerSmallObjectAllocator(uint32_t type, size_t block_size)
+    : type_(type), block_size_(block_size), free_pages_cnt_(0), free_blocks_list_(nullptr) {}
 
 void* LinkerSmallObjectAllocator::alloc() {
   CHECK(block_size_ != 0);
@@ -159,11 +159,6 @@
   }
 }
 
-void LinkerSmallObjectAllocator::init(uint32_t type, size_t block_size) {
-  type_ = type;
-  block_size_ = block_size;
-}
-
 linker_vector_t::iterator LinkerSmallObjectAllocator::find_page_record(void* ptr) {
   void* addr = reinterpret_cast<void*>(PAGE_START(reinterpret_cast<uintptr_t>(ptr)));
   small_object_page_record boundary;
@@ -221,11 +216,20 @@
 }
 
 
-LinkerMemoryAllocator::LinkerMemoryAllocator() {
+void LinkerMemoryAllocator::initialize_allocators() {
+  if (allocators_ != nullptr) {
+    return;
+  }
+
+  LinkerSmallObjectAllocator* allocators =
+      reinterpret_cast<LinkerSmallObjectAllocator*>(allocators_buf_);
+
   for (size_t i = 0; i < kSmallObjectAllocatorsCount; ++i) {
     uint32_t type = i + kSmallObjectMinSizeLog2;
-    allocators_[i].init(type, 1 << type);
+    new (allocators + i) LinkerSmallObjectAllocator(type, 1 << type);
   }
+
+  allocators_ = allocators;
 }
 
 void* LinkerMemoryAllocator::alloc_mmap(size_t size) {
@@ -336,5 +340,6 @@
     __libc_fatal("invalid type: %u", type);
   }
 
+  initialize_allocators();
   return &allocators_[type - kSmallObjectMinSizeLog2];
 }
diff --git a/linker/linker_allocator.h b/linker/linker_allocator.h
index 22a337a..8f90dbf 100644
--- a/linker/linker_allocator.h
+++ b/linker/linker_allocator.h
@@ -100,8 +100,7 @@
 
 class LinkerSmallObjectAllocator {
  public:
-  LinkerSmallObjectAllocator();
-  void init(uint32_t type, size_t block_size);
+  LinkerSmallObjectAllocator(uint32_t type, size_t block_size);
   void* alloc();
   void free(void* ptr);
 
@@ -124,7 +123,7 @@
 
 class LinkerMemoryAllocator {
  public:
-  LinkerMemoryAllocator();
+  constexpr LinkerMemoryAllocator() : allocators_(nullptr), allocators_buf_() {}
   void* alloc(size_t size);
 
   // Note that this implementation of realloc never shrinks allocation
@@ -134,8 +133,10 @@
   void* alloc_mmap(size_t size);
   page_info* get_page_info(void* ptr);
   LinkerSmallObjectAllocator* get_small_object_allocator(uint32_t type);
+  void initialize_allocators();
 
-  LinkerSmallObjectAllocator allocators_[kSmallObjectAllocatorsCount];
+  LinkerSmallObjectAllocator* allocators_;
+  uint8_t allocators_buf_[sizeof(LinkerSmallObjectAllocator)*kSmallObjectAllocatorsCount];
 };