src/hotspot/share/gc/z/zObjectAllocator.cpp
changeset 50525 767cdb97f103
child 50844 53772937ea84
equal deleted inserted replaced
50524:04f4e983c2f7 50525:767cdb97f103
       
     1 /*
       
     2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 #include "precompiled.hpp"
       
    25 #include "gc/shared/threadLocalAllocBuffer.inline.hpp"
       
    26 #include "gc/z/zCollectedHeap.hpp"
       
    27 #include "gc/z/zGlobals.hpp"
       
    28 #include "gc/z/zHeap.inline.hpp"
       
    29 #include "gc/z/zObjectAllocator.hpp"
       
    30 #include "gc/z/zPage.inline.hpp"
       
    31 #include "gc/z/zStat.hpp"
       
    32 #include "gc/z/zThread.hpp"
       
    33 #include "gc/z/zUtils.inline.hpp"
       
    34 #include "logging/log.hpp"
       
    35 #include "runtime/atomic.hpp"
       
    36 #include "runtime/safepoint.hpp"
       
    37 #include "runtime/thread.hpp"
       
    38 #include "runtime/threadSMR.hpp"
       
    39 #include "utilities/align.hpp"
       
    40 #include "utilities/debug.hpp"
       
    41 
       
    42 static const ZStatCounter ZCounterUndoObjectAllocationSucceeded("Memory", "Undo Object Allocation Succeeded", ZStatUnitOpsPerSecond);
       
    43 static const ZStatCounter ZCounterUndoObjectAllocationFailed("Memory", "Undo Object Allocation Failed", ZStatUnitOpsPerSecond);
       
    44 static const ZStatSubPhase ZSubPhasePauseRetireTLABS("Pause Retire TLABS");
       
    45 static const ZStatSubPhase ZSubPhasePauseRemapTLABS("Pause Remap TLABS");
       
    46 
       
    47 ZObjectAllocator::ZObjectAllocator(uint nworkers) :
       
    48     _nworkers(nworkers),
       
    49     _used(0),
       
    50     _shared_medium_page(NULL),
       
    51     _shared_small_page(NULL),
       
    52     _worker_small_page(NULL) {}
       
    53 
       
    54 ZPage* ZObjectAllocator::alloc_page(uint8_t type, size_t size, ZAllocationFlags flags) {
       
    55   ZPage* const page = ZHeap::heap()->alloc_page(type, size, flags);
       
    56   if (page != NULL) {
       
    57     // Increment used bytes
       
    58     Atomic::add(size, _used.addr());
       
    59   }
       
    60 
       
    61   return page;
       
    62 }
       
    63 
       
    64 uintptr_t ZObjectAllocator::alloc_object_in_shared_page(ZPage** shared_page,
       
    65                                                         uint8_t page_type,
       
    66                                                         size_t page_size,
       
    67                                                         size_t size,
       
    68                                                         ZAllocationFlags flags) {
       
    69   uintptr_t addr = 0;
       
    70   ZPage* page = *shared_page;
       
    71 
       
    72   if (page != NULL) {
       
    73     addr = page->alloc_object_atomic(size);
       
    74   }
       
    75 
       
    76   if (addr == 0) {
       
    77     // Allocate new page
       
    78     ZPage* const new_page = alloc_page(page_type, page_size, flags);
       
    79     if (new_page != NULL) {
       
    80       // Allocate object before installing the new page
       
    81       addr = new_page->alloc_object(size);
       
    82 
       
    83     retry:
       
    84       // Install new page
       
    85       ZPage* const prev_page = Atomic::cmpxchg(new_page, shared_page, page);
       
    86       if (prev_page != page) {
       
    87         if (prev_page == NULL) {
       
    88           // Previous page was retired, retry installing the new page
       
    89           page = prev_page;
       
    90           goto retry;
       
    91         }
       
    92 
       
    93         // Another page already installed, try allocation there first
       
    94         const uintptr_t prev_addr = prev_page->alloc_object_atomic(size);
       
    95         if (prev_addr == 0) {
       
    96           // Allocation failed, retry installing the new page
       
    97           page = prev_page;
       
    98           goto retry;
       
    99         }
       
   100 
       
   101         // Allocation succeeded in already installed page
       
   102         addr = prev_addr;
       
   103 
       
   104         // Undo new page allocation
       
   105         ZHeap::heap()->undo_alloc_page(new_page);
       
   106       }
       
   107     }
       
   108   }
       
   109 
       
   110   return addr;
       
   111 }
       
   112 
       
   113 uintptr_t ZObjectAllocator::alloc_large_object(size_t size, ZAllocationFlags flags) {
       
   114   assert(ZThread::is_java(), "Should be a Java thread");
       
   115 
       
   116   uintptr_t addr = 0;
       
   117 
       
   118   // Allocate new large page
       
   119   const size_t page_size = align_up(size, ZPageSizeMin);
       
   120   ZPage* const page = alloc_page(ZPageTypeLarge, page_size, flags);
       
   121   if (page != NULL) {
       
   122     // Allocate the object
       
   123     addr = page->alloc_object(size);
       
   124   }
       
   125 
       
   126   return addr;
       
   127 }
       
   128 
       
   129 uintptr_t ZObjectAllocator::alloc_medium_object(size_t size, ZAllocationFlags flags) {
       
   130   return alloc_object_in_shared_page(_shared_medium_page.addr(), ZPageTypeMedium, ZPageSizeMedium, size, flags);
       
   131 }
       
   132 
       
   133 uintptr_t ZObjectAllocator::alloc_small_object_from_nonworker(size_t size, ZAllocationFlags flags) {
       
   134   assert(ZThread::is_java() || ZThread::is_vm(), "Should be a Java or VM thread");
       
   135 
       
   136   if (flags.relocation() && flags.java_thread() && UseTLAB) {
       
   137     // For relocations from Java threads, try TLAB allocation first
       
   138     const uintptr_t addr = (uintptr_t)Thread::current()->tlab().allocate(ZUtils::bytes_to_words(size));
       
   139     if (addr != 0) {
       
   140       return addr;
       
   141     }
       
   142   }
       
   143 
       
   144   // Non-worker small page allocation can never use the reserve
       
   145   flags.set_no_reserve();
       
   146 
       
   147   return alloc_object_in_shared_page(_shared_small_page.addr(), ZPageTypeSmall, ZPageSizeSmall, size, flags);
       
   148 }
       
   149 
       
   150 uintptr_t ZObjectAllocator::alloc_small_object_from_worker(size_t size, ZAllocationFlags flags) {
       
   151   assert(ZThread::is_worker(), "Should be a worker thread");
       
   152 
       
   153   ZPage* page = _worker_small_page.get();
       
   154   uintptr_t addr = 0;
       
   155 
       
   156   if (page != NULL) {
       
   157     addr = page->alloc_object(size);
       
   158   }
       
   159 
       
   160   if (addr == 0) {
       
   161     // Allocate new page
       
   162     page = alloc_page(ZPageTypeSmall, ZPageSizeSmall, flags);
       
   163     if (page != NULL) {
       
   164       addr = page->alloc_object(size);
       
   165     }
       
   166     _worker_small_page.set(page);
       
   167   }
       
   168 
       
   169   return addr;
       
   170 }
       
   171 
       
   172 uintptr_t ZObjectAllocator::alloc_small_object(size_t size, ZAllocationFlags flags) {
       
   173   if (flags.worker_thread()) {
       
   174     return alloc_small_object_from_worker(size, flags);
       
   175   } else {
       
   176     return alloc_small_object_from_nonworker(size, flags);
       
   177   }
       
   178 }
       
   179 
       
   180 uintptr_t ZObjectAllocator::alloc_object(size_t size, ZAllocationFlags flags) {
       
   181   if (size <= ZObjectSizeLimitSmall) {
       
   182     // Small
       
   183     return alloc_small_object(size, flags);
       
   184   } else if (size <= ZObjectSizeLimitMedium) {
       
   185     // Medium
       
   186     return alloc_medium_object(size, flags);
       
   187   } else {
       
   188     // Large
       
   189     return alloc_large_object(size, flags);
       
   190   }
       
   191 }
       
   192 
       
   193 uintptr_t ZObjectAllocator::alloc_object(size_t size) {
       
   194   assert(ZThread::is_java(), "Must be a Java thread");
       
   195 
       
   196   ZAllocationFlags flags;
       
   197   flags.set_java_thread();
       
   198   flags.set_no_reserve();
       
   199 
       
   200   if (!ZStallOnOutOfMemory) {
       
   201     flags.set_non_blocking();
       
   202   }
       
   203 
       
   204   return alloc_object(size, flags);
       
   205 }
       
   206 
       
   207 uintptr_t ZObjectAllocator::alloc_object_for_relocation(size_t size) {
       
   208   assert(ZThread::is_java() || ZThread::is_worker() || ZThread::is_vm(), "Unknown thread");
       
   209 
       
   210   ZAllocationFlags flags;
       
   211   flags.set_relocation();
       
   212   flags.set_non_blocking();
       
   213 
       
   214   if (ZThread::is_worker()) {
       
   215     flags.set_worker_thread();
       
   216   } else if (ZThread::is_java()) {
       
   217     flags.set_java_thread();
       
   218   }
       
   219 
       
   220   return alloc_object(size, flags);
       
   221 }
       
   222 
       
   223 bool ZObjectAllocator::undo_alloc_large_object(ZPage* page) {
       
   224   assert(page->type() == ZPageTypeLarge, "Invalid page type");
       
   225 
       
   226   // Undo page allocation
       
   227   ZHeap::heap()->undo_alloc_page(page);
       
   228   return true;
       
   229 }
       
   230 
       
   231 bool ZObjectAllocator::undo_alloc_medium_object(ZPage* page, uintptr_t addr, size_t size) {
       
   232   assert(page->type() == ZPageTypeMedium, "Invalid page type");
       
   233 
       
   234   // Try atomic undo on shared page
       
   235   return page->undo_alloc_object_atomic(addr, size);
       
   236 }
       
   237 
       
   238 bool ZObjectAllocator::undo_alloc_small_object_from_nonworker(ZPage* page, uintptr_t addr, size_t size) {
       
   239   assert(page->type() == ZPageTypeSmall, "Invalid page type");
       
   240 
       
   241   if (ZThread::is_java()) {
       
   242     // Try undo allocation in TLAB
       
   243     if (Thread::current()->tlab().undo_allocate((HeapWord*)addr, ZUtils::bytes_to_words(size))) {
       
   244       return true;
       
   245     }
       
   246   }
       
   247 
       
   248   // Try atomic undo on shared page
       
   249   return page->undo_alloc_object_atomic(addr, size);
       
   250 }
       
   251 
       
   252 bool ZObjectAllocator::undo_alloc_small_object_from_worker(ZPage* page, uintptr_t addr, size_t size) {
       
   253   assert(page->type() == ZPageTypeSmall, "Invalid page type");
       
   254   assert(page == _worker_small_page.get(), "Invalid page");
       
   255 
       
   256   // Non-atomic undo on worker-local page
       
   257   const bool success = page->undo_alloc_object(addr, size);
       
   258   assert(success, "Should always succeed");
       
   259   return success;
       
   260 }
       
   261 
       
   262 bool ZObjectAllocator::undo_alloc_small_object(ZPage* page, uintptr_t addr, size_t size) {
       
   263   if (ZThread::is_worker()) {
       
   264     return undo_alloc_small_object_from_worker(page, addr, size);
       
   265   } else {
       
   266     return undo_alloc_small_object_from_nonworker(page, addr, size);
       
   267   }
       
   268 }
       
   269 
       
   270 bool ZObjectAllocator::undo_alloc_object(ZPage* page, uintptr_t addr, size_t size) {
       
   271   const uint8_t type = page->type();
       
   272 
       
   273   if (type == ZPageTypeSmall) {
       
   274     return undo_alloc_small_object(page, addr, size);
       
   275   } else if (type == ZPageTypeMedium) {
       
   276     return undo_alloc_medium_object(page, addr, size);
       
   277   } else {
       
   278     return undo_alloc_large_object(page);
       
   279   }
       
   280 }
       
   281 
       
   282 void ZObjectAllocator::undo_alloc_object_for_relocation(ZPage* page, uintptr_t addr, size_t size) {
       
   283   if (undo_alloc_object(page, addr, size)) {
       
   284     ZStatInc(ZCounterUndoObjectAllocationSucceeded);
       
   285   } else {
       
   286     ZStatInc(ZCounterUndoObjectAllocationFailed);
       
   287     log_trace(gc)("Failed to undo object allocation: " PTR_FORMAT ", Size: " SIZE_FORMAT ", Thread: " PTR_FORMAT " (%s)",
       
   288                   addr, size, ZThread::id(), ZThread::name());
       
   289   }
       
   290 }
       
   291 
       
   292 size_t ZObjectAllocator::used() const {
       
   293   size_t total_used = 0;
       
   294 
       
   295   ZPerCPUConstIterator<size_t> iter(&_used);
       
   296   for (const size_t* cpu_used; iter.next(&cpu_used);) {
       
   297     total_used += *cpu_used;
       
   298   }
       
   299 
       
   300   return total_used;
       
   301 }
       
   302 
       
   303 size_t ZObjectAllocator::remaining() const {
       
   304   assert(ZThread::is_java(), "Should be a Java thread");
       
   305 
       
   306   ZPage* page = _shared_small_page.get();
       
   307   if (page != NULL) {
       
   308     return page->remaining();
       
   309   }
       
   310 
       
   311   return 0;
       
   312 }
       
   313 
       
   314 void ZObjectAllocator::retire_tlabs() {
       
   315   ZStatTimer timer(ZSubPhasePauseRetireTLABS);
       
   316   assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
       
   317 
       
   318   // Retire TLABs
       
   319   if (UseTLAB) {
       
   320     ZCollectedHeap* heap = ZCollectedHeap::heap();
       
   321     heap->accumulate_statistics_all_tlabs();
       
   322     heap->ensure_parsability(true /* retire_tlabs */);
       
   323     heap->resize_all_tlabs();
       
   324   }
       
   325 
       
   326   // Reset used
       
   327   _used.set_all(0);
       
   328 
       
   329   // Reset allocation pages
       
   330   _shared_medium_page.set(NULL);
       
   331   _shared_small_page.set_all(NULL);
       
   332   _worker_small_page.set_all(NULL);
       
   333 }
       
   334 
       
   335 static void remap_tlab_address(HeapWord** p) {
       
   336   *p = (HeapWord*)ZAddress::good_or_null((uintptr_t)*p);
       
   337 }
       
   338 
       
   339 void ZObjectAllocator::remap_tlabs() {
       
   340   ZStatTimer timer(ZSubPhasePauseRemapTLABS);
       
   341   assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint");
       
   342 
       
   343   if (UseTLAB) {
       
   344     for (JavaThreadIteratorWithHandle iter; JavaThread* thread = iter.next(); ) {
       
   345       thread->tlab().addresses_do(remap_tlab_address);
       
   346     }
       
   347   }
       
   348 }