src/hotspot/share/gc/z/zPage.inline.hpp
changeset 50525 767cdb97f103
child 51804 eef954e29714
equal deleted inserted replaced
50524:04f4e983c2f7 50525:767cdb97f103
       
     1 /*
       
     2  * Copyright (c) 2015, 2017, 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 #ifndef SHARE_GC_Z_ZPAGE_INLINE_HPP
       
    25 #define SHARE_GC_Z_ZPAGE_INLINE_HPP
       
    26 
       
    27 #include "gc/z/zAddress.inline.hpp"
       
    28 #include "gc/z/zForwardingTable.inline.hpp"
       
    29 #include "gc/z/zGlobals.hpp"
       
    30 #include "gc/z/zLiveMap.inline.hpp"
       
    31 #include "gc/z/zMark.hpp"
       
    32 #include "gc/z/zNUMA.hpp"
       
    33 #include "gc/z/zPage.hpp"
       
    34 #include "gc/z/zPhysicalMemory.inline.hpp"
       
    35 #include "gc/z/zUtils.inline.hpp"
       
    36 #include "gc/z/zVirtualMemory.inline.hpp"
       
    37 #include "oops/oop.inline.hpp"
       
    38 #include "runtime/atomic.hpp"
       
    39 #include "utilities/align.hpp"
       
    40 #include "utilities/debug.hpp"
       
    41 
       
    42 inline const char* ZPage::type_to_string() const {
       
    43   switch (type()) {
       
    44   case ZPageTypeSmall:
       
    45     return "Small";
       
    46 
       
    47   case ZPageTypeMedium:
       
    48     return "Medium";
       
    49 
       
    50   default:
       
    51     assert(type() == ZPageTypeLarge, "Invalid page type");
       
    52     return "Large";
       
    53   }
       
    54 }
       
    55 
       
    56 inline uint32_t ZPage::object_max_count() const {
       
    57   switch (type()) {
       
    58   case ZPageTypeLarge:
       
    59     // A large page can only contain a single
       
    60     // object aligned to the start of the page.
       
    61     return 1;
       
    62 
       
    63   default:
       
    64     return (uint32_t)(size() >> object_alignment_shift());
       
    65   }
       
    66 }
       
    67 
       
    68 inline size_t ZPage::object_alignment_shift() const {
       
    69   switch (type()) {
       
    70   case ZPageTypeSmall:
       
    71     return ZObjectAlignmentSmallShift;
       
    72 
       
    73   case ZPageTypeMedium:
       
    74     return ZObjectAlignmentMediumShift;
       
    75 
       
    76   default:
       
    77     assert(type() == ZPageTypeLarge, "Invalid page type");
       
    78     return ZObjectAlignmentLargeShift;
       
    79   }
       
    80 }
       
    81 
       
    82 inline size_t ZPage::object_alignment() const {
       
    83   switch (type()) {
       
    84   case ZPageTypeSmall:
       
    85     return ZObjectAlignmentSmall;
       
    86 
       
    87   case ZPageTypeMedium:
       
    88     return ZObjectAlignmentMedium;
       
    89 
       
    90   default:
       
    91     assert(type() == ZPageTypeLarge, "Invalid page type");
       
    92     return ZObjectAlignmentLarge;
       
    93   }
       
    94 }
       
    95 
       
    96 inline uint8_t ZPage::type() const {
       
    97   return _type;
       
    98 }
       
    99 
       
   100 inline uintptr_t ZPage::start() const {
       
   101   return _virtual.start();
       
   102 }
       
   103 
       
   104 inline uintptr_t ZPage::end() const {
       
   105   return _virtual.end();
       
   106 }
       
   107 
       
   108 inline size_t ZPage::size() const {
       
   109   return _virtual.size();
       
   110 }
       
   111 
       
   112 inline uintptr_t ZPage::top() const {
       
   113   return _top;
       
   114 }
       
   115 
       
   116 inline size_t ZPage::remaining() const {
       
   117   return end() - top();
       
   118 }
       
   119 
       
   120 inline ZPhysicalMemory& ZPage::physical_memory() {
       
   121   return _physical;
       
   122 }
       
   123 
       
   124 inline const ZVirtualMemory& ZPage::virtual_memory() const {
       
   125   return _virtual;
       
   126 }
       
   127 
       
   128 inline uint8_t ZPage::numa_id() {
       
   129   if (_numa_id == (uint8_t)-1) {
       
   130     _numa_id = (uint8_t)ZNUMA::memory_id(ZAddress::good(start()));
       
   131   }
       
   132 
       
   133   return _numa_id;
       
   134 }
       
   135 
       
   136 inline bool ZPage::inc_refcount() {
       
   137   for (uint32_t prev_refcount = _refcount; prev_refcount > 0; prev_refcount = _refcount) {
       
   138     if (Atomic::cmpxchg(prev_refcount + 1, &_refcount, prev_refcount) == prev_refcount) {
       
   139       return true;
       
   140     }
       
   141   }
       
   142   return false;
       
   143 }
       
   144 
       
   145 inline bool ZPage::dec_refcount() {
       
   146   assert(is_active(), "Should be active");
       
   147   return Atomic::sub(1u, &_refcount) == 0;
       
   148 }
       
   149 
       
   150 inline bool ZPage::is_in(uintptr_t addr) const {
       
   151   const uintptr_t offset = ZAddress::offset(addr);
       
   152   return offset >= start() && offset < top();
       
   153 }
       
   154 
       
   155 inline uintptr_t ZPage::block_start(uintptr_t addr) const {
       
   156   if (block_is_obj(addr)) {
       
   157     return addr;
       
   158   } else {
       
   159     return ZAddress::good(top());
       
   160   }
       
   161 }
       
   162 
       
   163 inline size_t ZPage::block_size(uintptr_t addr) const {
       
   164   if (block_is_obj(addr)) {
       
   165     return ZUtils::object_size(addr);
       
   166   } else {
       
   167     return end() - top();
       
   168   }
       
   169 }
       
   170 
       
   171 inline bool ZPage::block_is_obj(uintptr_t addr) const {
       
   172   return ZAddress::offset(addr) < top();
       
   173 }
       
   174 
       
   175 inline bool ZPage::is_active() const {
       
   176   return _refcount > 0;
       
   177 }
       
   178 
       
   179 inline bool ZPage::is_allocating() const {
       
   180   return is_active() && _seqnum == ZGlobalSeqNum;
       
   181 }
       
   182 
       
   183 inline bool ZPage::is_relocatable() const {
       
   184   return is_active() && _seqnum < ZGlobalSeqNum;
       
   185 }
       
   186 
       
   187 inline bool ZPage::is_detached() const {
       
   188   return _physical.is_null();
       
   189 }
       
   190 
       
   191 inline bool ZPage::is_mapped() const {
       
   192   return _seqnum > 0;
       
   193 }
       
   194 
       
   195 inline void ZPage::set_pre_mapped() {
       
   196   // The _seqnum variable is also used to signal that the virtual and physical
       
   197   // memory has been mapped. So, we need to set it to non-zero when the memory
       
   198   // has been pre-mapped.
       
   199   _seqnum = 1;
       
   200 }
       
   201 
       
   202 inline bool ZPage::is_pinned() const {
       
   203   return _pinned;
       
   204 }
       
   205 
       
   206 inline void ZPage::set_pinned() {
       
   207   _pinned = 1;
       
   208 }
       
   209 
       
   210 inline bool ZPage::is_forwarding() const {
       
   211   return !_forwarding.is_null();
       
   212 }
       
   213 
       
   214 inline void ZPage::set_forwarding() {
       
   215   assert(is_marked(), "Should be marked");
       
   216   _forwarding.setup(_livemap.live_objects());
       
   217 }
       
   218 
       
   219 inline void ZPage::reset_forwarding() {
       
   220   _forwarding.reset();
       
   221   _pinned = 0;
       
   222 }
       
   223 
       
   224 inline void ZPage::verify_forwarding() const {
       
   225   _forwarding.verify(object_max_count(), _livemap.live_objects());
       
   226 }
       
   227 
       
   228 inline bool ZPage::is_marked() const {
       
   229   assert(is_relocatable(), "Invalid page state");
       
   230   return _livemap.is_marked();
       
   231 }
       
   232 
       
   233 inline bool ZPage::is_object_marked(uintptr_t addr) const {
       
   234   const size_t index = ((ZAddress::offset(addr) - start()) >> object_alignment_shift()) * 2;
       
   235   return _livemap.get(index);
       
   236 }
       
   237 
       
   238 inline bool ZPage::is_object_strongly_marked(uintptr_t addr) const {
       
   239   const size_t index = ((ZAddress::offset(addr) - start()) >> object_alignment_shift()) * 2;
       
   240   return _livemap.get(index + 1);
       
   241 }
       
   242 
       
   243 inline bool ZPage::is_object_live(uintptr_t addr) const {
       
   244   return is_allocating() || is_object_marked(addr);
       
   245 }
       
   246 
       
   247 inline bool ZPage::is_object_strongly_live(uintptr_t addr) const {
       
   248   return is_allocating() || is_object_strongly_marked(addr);
       
   249 }
       
   250 
       
   251 inline bool ZPage::mark_object(uintptr_t addr, bool finalizable, bool& inc_live) {
       
   252   assert(ZAddress::is_marked(addr), "Invalid address");
       
   253   assert(is_relocatable(), "Invalid page state");
       
   254   assert(is_in(addr), "Invalid address");
       
   255 
       
   256   // Set mark bit
       
   257   const size_t index = ((ZAddress::offset(addr) - start()) >> object_alignment_shift()) * 2;
       
   258   return _livemap.set_atomic(index, finalizable, inc_live);
       
   259 }
       
   260 
       
   261 inline void ZPage::inc_live_atomic(uint32_t objects, size_t bytes) {
       
   262   _livemap.inc_live_atomic(objects, bytes);
       
   263 }
       
   264 
       
   265 inline size_t ZPage::live_bytes() const {
       
   266   assert(is_marked(), "Should be marked");
       
   267   return _livemap.live_bytes();
       
   268 }
       
   269 
       
   270 inline void ZPage::object_iterate(ObjectClosure* cl) {
       
   271   _livemap.iterate(cl, ZAddress::good(start()), object_alignment_shift());
       
   272 }
       
   273 
       
   274 inline uintptr_t ZPage::alloc_object(size_t size) {
       
   275   assert(is_allocating(), "Invalid state");
       
   276 
       
   277   const size_t aligned_size = align_up(size, object_alignment());
       
   278   const uintptr_t addr = top();
       
   279   const uintptr_t new_top = addr + aligned_size;
       
   280 
       
   281   if (new_top > end()) {
       
   282     // Not enough space left
       
   283     return 0;
       
   284   }
       
   285 
       
   286   _top = new_top;
       
   287 
       
   288   // Fill alignment padding if needed
       
   289   if (aligned_size != size) {
       
   290     ZUtils::insert_filler_object(addr + size, aligned_size - size);
       
   291   }
       
   292 
       
   293   return ZAddress::good(addr);
       
   294 }
       
   295 
       
   296 inline uintptr_t ZPage::alloc_object_atomic(size_t size) {
       
   297   assert(is_allocating(), "Invalid state");
       
   298 
       
   299   const size_t aligned_size = align_up(size, object_alignment());
       
   300   uintptr_t addr = top();
       
   301 
       
   302   for (;;) {
       
   303     const uintptr_t new_top = addr + aligned_size;
       
   304     if (new_top > end()) {
       
   305       // Not enough space left
       
   306       return 0;
       
   307     }
       
   308 
       
   309     const uintptr_t prev_top = Atomic::cmpxchg(new_top, &_top, addr);
       
   310     if (prev_top == addr) {
       
   311       // Fill alignment padding if needed
       
   312       if (aligned_size != size) {
       
   313         ZUtils::insert_filler_object(addr + size, aligned_size - size);
       
   314       }
       
   315 
       
   316       // Success
       
   317       return ZAddress::good(addr);
       
   318     }
       
   319 
       
   320     // Retry
       
   321     addr = prev_top;
       
   322   }
       
   323 }
       
   324 
       
   325 inline bool ZPage::undo_alloc_object(uintptr_t addr, size_t size) {
       
   326   assert(is_allocating(), "Invalid state");
       
   327 
       
   328   const uintptr_t offset = ZAddress::offset(addr);
       
   329   const size_t aligned_size = align_up(size, object_alignment());
       
   330   const uintptr_t old_top = top();
       
   331   const uintptr_t new_top = old_top - aligned_size;
       
   332 
       
   333   if (new_top != offset) {
       
   334     // Failed to undo allocation, not the last allocated object
       
   335     return false;
       
   336   }
       
   337 
       
   338   _top = new_top;
       
   339 
       
   340   // Success
       
   341   return true;
       
   342 }
       
   343 
       
   344 inline bool ZPage::undo_alloc_object_atomic(uintptr_t addr, size_t size) {
       
   345   assert(is_allocating(), "Invalid state");
       
   346 
       
   347   const uintptr_t offset = ZAddress::offset(addr);
       
   348   const size_t aligned_size = align_up(size, object_alignment());
       
   349   uintptr_t old_top = top();
       
   350 
       
   351   for (;;) {
       
   352     const uintptr_t new_top = old_top - aligned_size;
       
   353     if (new_top != offset) {
       
   354       // Failed to undo allocation, not the last allocated object
       
   355       return false;
       
   356     }
       
   357 
       
   358     const uintptr_t prev_top = Atomic::cmpxchg(new_top, &_top, old_top);
       
   359     if (prev_top == old_top) {
       
   360       // Success
       
   361       return true;
       
   362     }
       
   363 
       
   364     // Retry
       
   365     old_top = prev_top;
       
   366   }
       
   367 }
       
   368 
       
   369 #endif // SHARE_GC_Z_ZPAGE_INLINE_HPP