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];
 }