src/hotspot/share/oops/compressedOops.cpp
changeset 54780 f8d182aedc92
child 58015 dd84de796f2c
child 58678 9cf78a70fa4f
equal deleted inserted replaced
54779:e0bd4c7a176e 54780:f8d182aedc92
       
     1 /*
       
     2  * Copyright (c) 2019, 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 
       
    25 #include "precompiled.hpp"
       
    26 #include "aot/aotLoader.hpp"
       
    27 #include "logging/log.hpp"
       
    28 #include "logging/logStream.hpp"
       
    29 #include "memory/memRegion.hpp"
       
    30 #include "memory/universe.hpp"
       
    31 #include "oops/compressedOops.hpp"
       
    32 #include "gc/shared/collectedHeap.hpp"
       
    33 #include "runtime/globals.hpp"
       
    34 
       
    35 // For UseCompressedOops.
       
    36 NarrowPtrStruct CompressedOops::_narrow_oop = { NULL, 0, true };
       
    37 
       
    38 address CompressedOops::_narrow_ptrs_base;
       
    39 
       
    40 // Choose the heap base address and oop encoding mode
       
    41 // when compressed oops are used:
       
    42 // Unscaled  - Use 32-bits oops without encoding when
       
    43 //     NarrowOopHeapBaseMin + heap_size < 4Gb
       
    44 // ZeroBased - Use zero based compressed oops with encoding when
       
    45 //     NarrowOopHeapBaseMin + heap_size < 32Gb
       
    46 // HeapBased - Use compressed oops with heap base + encoding.
       
    47 void CompressedOops::initialize() {
       
    48 #ifdef _LP64
       
    49   if (UseCompressedOops) {
       
    50     // Subtract a page because something can get allocated at heap base.
       
    51     // This also makes implicit null checking work, because the
       
    52     // memory+1 page below heap_base needs to cause a signal.
       
    53     // See needs_explicit_null_check.
       
    54     // Only set the heap base for compressed oops because it indicates
       
    55     // compressed oops for pstack code.
       
    56     if ((uint64_t)Universe::heap()->reserved_region().end() > UnscaledOopHeapMax) {
       
    57       // Didn't reserve heap below 4Gb.  Must shift.
       
    58       set_shift(LogMinObjAlignmentInBytes);
       
    59     }
       
    60     if ((uint64_t)Universe::heap()->reserved_region().end() <= OopEncodingHeapMax) {
       
    61       // Did reserve heap below 32Gb. Can use base == 0;
       
    62       set_base(0);
       
    63     }
       
    64     AOTLoader::set_narrow_oop_shift();
       
    65 
       
    66     set_ptrs_base(base());
       
    67 
       
    68     LogTarget(Info, gc, heap, coops) lt;
       
    69     if (lt.is_enabled()) {
       
    70       ResourceMark rm;
       
    71       LogStream ls(lt);
       
    72       print_mode(&ls);
       
    73     }
       
    74 
       
    75     // Tell tests in which mode we run.
       
    76     Arguments::PropertyList_add(new SystemProperty("java.vm.compressedOopsMode",
       
    77                                                    mode_to_string(mode()),
       
    78                                                    false));
       
    79   }
       
    80   // base() is one page below the heap.
       
    81   assert((intptr_t)base() <= (intptr_t)(Universe::heap()->base() - os::vm_page_size()) ||
       
    82          base() == NULL, "invalid value");
       
    83   assert(shift() == LogMinObjAlignmentInBytes ||
       
    84          shift() == 0, "invalid value");
       
    85 #endif
       
    86 }
       
    87 
       
    88 void CompressedOops::set_base(address base) {
       
    89   assert(UseCompressedOops, "no compressed oops?");
       
    90   _narrow_oop._base    = base;
       
    91 }
       
    92 
       
    93 void CompressedOops::set_shift(int shift) {
       
    94   _narrow_oop._shift   = shift;
       
    95 }
       
    96 
       
    97 void CompressedOops::set_use_implicit_null_checks(bool use) {
       
    98   assert(UseCompressedOops, "no compressed ptrs?");
       
    99   _narrow_oop._use_implicit_null_checks   = use;
       
   100 }
       
   101 
       
   102 void CompressedOops::set_ptrs_base(address addr) {
       
   103   _narrow_ptrs_base = addr;
       
   104 }
       
   105 
       
   106 CompressedOops::Mode CompressedOops::mode() {
       
   107   if (base_disjoint()) {
       
   108     return DisjointBaseNarrowOop;
       
   109   }
       
   110 
       
   111   if (base() != 0) {
       
   112     return HeapBasedNarrowOop;
       
   113   }
       
   114 
       
   115   if (shift() != 0) {
       
   116     return ZeroBasedNarrowOop;
       
   117   }
       
   118 
       
   119   return UnscaledNarrowOop;
       
   120 }
       
   121 
       
   122 const char* CompressedOops::mode_to_string(Mode mode) {
       
   123   switch (mode) {
       
   124     case UnscaledNarrowOop:
       
   125       return "32-bit";
       
   126     case ZeroBasedNarrowOop:
       
   127       return "Zero based";
       
   128     case DisjointBaseNarrowOop:
       
   129       return "Non-zero disjoint base";
       
   130     case HeapBasedNarrowOop:
       
   131       return "Non-zero based";
       
   132     default:
       
   133       ShouldNotReachHere();
       
   134       return "";
       
   135   }
       
   136 }
       
   137 
       
   138 // Test whether bits of addr and possible offsets into the heap overlap.
       
   139 bool CompressedOops::is_disjoint_heap_base_address(address addr) {
       
   140   return (((uint64_t)(intptr_t)addr) &
       
   141           (((uint64_t)UCONST64(0xFFFFffffFFFFffff)) >> (32-LogMinObjAlignmentInBytes))) == 0;
       
   142 }
       
   143 
       
   144 // Check for disjoint base compressed oops.
       
   145 bool CompressedOops::base_disjoint() {
       
   146   return _narrow_oop._base != NULL && is_disjoint_heap_base_address(_narrow_oop._base);
       
   147 }
       
   148 
       
   149 // Check for real heapbased compressed oops.
       
   150 // We must subtract the base as the bits overlap.
       
   151 // If we negate above function, we also get unscaled and zerobased.
       
   152 bool CompressedOops::base_overlaps() {
       
   153   return _narrow_oop._base != NULL && !is_disjoint_heap_base_address(_narrow_oop._base);
       
   154 }
       
   155 
       
   156 void CompressedOops::print_mode(outputStream* st) {
       
   157   st->print("Heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
       
   158             p2i(Universe::heap()->base()), Universe::heap()->reserved_region().byte_size()/M);
       
   159 
       
   160   st->print(", Compressed Oops mode: %s", mode_to_string(mode()));
       
   161 
       
   162   if (base() != 0) {
       
   163     st->print(": " PTR_FORMAT, p2i(base()));
       
   164   }
       
   165 
       
   166   if (shift() != 0) {
       
   167     st->print(", Oop shift amount: %d", shift());
       
   168   }
       
   169 
       
   170   if (!use_implicit_null_checks()) {
       
   171     st->print(", no protected page in front of the heap");
       
   172   }
       
   173   st->cr();
       
   174 }
       
   175 
       
   176 // For UseCompressedClassPointers.
       
   177 NarrowPtrStruct CompressedKlassPointers::_narrow_klass = { NULL, 0, true };
       
   178 
       
   179 // CompressedClassSpaceSize set to 1GB, but appear 3GB away from _narrow_ptrs_base during CDS dump.
       
   180 uint64_t CompressedKlassPointers::_narrow_klass_range = (uint64_t(max_juint)+1);;
       
   181 
       
   182 void CompressedKlassPointers::set_base(address base) {
       
   183   assert(UseCompressedClassPointers, "no compressed klass ptrs?");
       
   184   _narrow_klass._base   = base;
       
   185 }
       
   186 
       
   187 void CompressedKlassPointers::set_shift(int shift)       {
       
   188   assert(shift == 0 || shift == LogKlassAlignmentInBytes, "invalid shift for klass ptrs");
       
   189   _narrow_klass._shift   = shift;
       
   190 }
       
   191 
       
   192 void CompressedKlassPointers::set_range(uint64_t range) {
       
   193   assert(UseCompressedClassPointers, "no compressed klass ptrs?");
       
   194   _narrow_klass_range = range;
       
   195 }