1/*
2 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26#include "precompiled.hpp"
27#include "gc/shared/cardTableRS.hpp"
28#include "gc/shared/gcArguments.hpp"
29#include "logging/log.hpp"
30#include "runtime/arguments.hpp"
31#include "runtime/globals.hpp"
32#include "runtime/globals_extension.hpp"
33#include "utilities/defaultStream.hpp"
34#include "utilities/macros.hpp"
35
36size_t HeapAlignment = 0;
37size_t SpaceAlignment = 0;
38
39void GCArguments::initialize() {
40 if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) {
41 MarkSweepAlwaysCompactCount = 1; // Move objects every gc.
42 }
43
44 if (!(UseParallelGC || UseParallelOldGC) && FLAG_IS_DEFAULT(ScavengeBeforeFullGC)) {
45 FLAG_SET_DEFAULT(ScavengeBeforeFullGC, false);
46 }
47
48 if (GCTimeLimit == 100) {
49 // Turn off gc-overhead-limit-exceeded checks
50 FLAG_SET_DEFAULT(UseGCOverheadLimit, false);
51 }
52
53 if (MinHeapFreeRatio == 100) {
54 // Keeping the heap 100% free is hard ;-) so limit it to 99%.
55 FLAG_SET_ERGO(MinHeapFreeRatio, 99);
56 }
57
58 if (!ClassUnloading) {
59 // If class unloading is disabled, also disable concurrent class unloading.
60 FLAG_SET_CMDLINE(ClassUnloadingWithConcurrentMark, false);
61 }
62
63 if (!FLAG_IS_DEFAULT(AllocateOldGenAt)) {
64 // CompressedOops not supported when AllocateOldGenAt is set.
65 LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false));
66 LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedClassPointers, false));
67 // When AllocateOldGenAt is set, we cannot use largepages for entire heap memory.
68 // Only young gen which is allocated in dram can use large pages, but we currently don't support that.
69 FLAG_SET_DEFAULT(UseLargePages, false);
70 }
71}
72
73void GCArguments::initialize_heap_sizes() {
74 initialize_alignments();
75 initialize_heap_flags_and_sizes();
76 initialize_size_info();
77}
78
79size_t GCArguments::compute_heap_alignment() {
80 // The card marking array and the offset arrays for old generations are
81 // committed in os pages as well. Make sure they are entirely full (to
82 // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
83 // byte entry and the os page size is 4096, the maximum heap size should
84 // be 512*4096 = 2MB aligned.
85
86 size_t alignment = CardTableRS::ct_max_alignment_constraint();
87
88 if (UseLargePages) {
89 // In presence of large pages we have to make sure that our
90 // alignment is large page aware.
91 alignment = lcm(os::large_page_size(), alignment);
92 }
93
94 return alignment;
95}
96
97bool GCArguments::check_args_consistency() {
98 bool status = true;
99 if (!FLAG_IS_DEFAULT(AllocateHeapAt) && !FLAG_IS_DEFAULT(AllocateOldGenAt)) {
100 jio_fprintf(defaultStream::error_stream(),
101 "AllocateHeapAt and AllocateOldGenAt cannot be used together.\n");
102 status = false;
103 }
104 if (!FLAG_IS_DEFAULT(AllocateOldGenAt) && (UseSerialGC || UseConcMarkSweepGC || UseEpsilonGC || UseZGC)) {
105 jio_fprintf(defaultStream::error_stream(),
106 "AllocateOldGenAt is not supported for selected GC.\n");
107 status = false;
108 }
109 return status;
110}
111
112#ifdef ASSERT
113void GCArguments::assert_flags() {
114 assert(InitialHeapSize <= MaxHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
115 assert(InitialHeapSize % HeapAlignment == 0, "InitialHeapSize alignment");
116 assert(MaxHeapSize % HeapAlignment == 0, "MaxHeapSize alignment");
117}
118
119void GCArguments::assert_size_info() {
120 assert(MaxHeapSize >= MinHeapSize, "Ergonomics decided on incompatible minimum and maximum heap sizes");
121 assert(InitialHeapSize >= MinHeapSize, "Ergonomics decided on incompatible initial and minimum heap sizes");
122 assert(MaxHeapSize >= InitialHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
123 assert(MinHeapSize % HeapAlignment == 0, "MinHeapSize alignment");
124 assert(InitialHeapSize % HeapAlignment == 0, "InitialHeapSize alignment");
125 assert(MaxHeapSize % HeapAlignment == 0, "MaxHeapSize alignment");
126}
127#endif // ASSERT
128
129void GCArguments::initialize_size_info() {
130 log_debug(gc, heap)("Minimum heap " SIZE_FORMAT " Initial heap " SIZE_FORMAT " Maximum heap " SIZE_FORMAT,
131 MinHeapSize, InitialHeapSize, MaxHeapSize);
132
133 DEBUG_ONLY(assert_size_info();)
134}
135
136void GCArguments::initialize_heap_flags_and_sizes() {
137 assert(SpaceAlignment != 0, "Space alignment not set up properly");
138 assert(HeapAlignment != 0, "Heap alignment not set up properly");
139 assert(HeapAlignment >= SpaceAlignment,
140 "HeapAlignment: " SIZE_FORMAT " less than SpaceAlignment: " SIZE_FORMAT,
141 HeapAlignment, SpaceAlignment);
142 assert(HeapAlignment % SpaceAlignment == 0,
143 "HeapAlignment: " SIZE_FORMAT " not aligned by SpaceAlignment: " SIZE_FORMAT,
144 HeapAlignment, SpaceAlignment);
145
146 if (FLAG_IS_CMDLINE(MaxHeapSize)) {
147 if (FLAG_IS_CMDLINE(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
148 vm_exit_during_initialization("Initial heap size set to a larger value than the maximum heap size");
149 }
150 if (FLAG_IS_CMDLINE(MinHeapSize) && MaxHeapSize < MinHeapSize) {
151 vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
152 }
153 }
154
155 // Check heap parameter properties
156 if (MaxHeapSize < 2 * M) {
157 vm_exit_during_initialization("Too small maximum heap");
158 }
159 if (InitialHeapSize < M) {
160 vm_exit_during_initialization("Too small initial heap");
161 }
162 if (MinHeapSize < M) {
163 vm_exit_during_initialization("Too small minimum heap");
164 }
165
166 // User inputs from -Xmx and -Xms must be aligned
167 // Write back to flags if the values changed
168 if (!is_aligned(MinHeapSize, HeapAlignment)) {
169 FLAG_SET_ERGO(MinHeapSize, align_up(MinHeapSize, HeapAlignment));
170 }
171 if (!is_aligned(InitialHeapSize, HeapAlignment)) {
172 FLAG_SET_ERGO(InitialHeapSize, align_up(InitialHeapSize, HeapAlignment));
173 }
174 if (!is_aligned(MaxHeapSize, HeapAlignment)) {
175 FLAG_SET_ERGO(MaxHeapSize, align_up(MaxHeapSize, HeapAlignment));
176 }
177
178 if (FLAG_IS_CMDLINE(InitialHeapSize) && FLAG_IS_CMDLINE(MinHeapSize) &&
179 InitialHeapSize < MinHeapSize) {
180 vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
181 }
182
183 if (!FLAG_IS_DEFAULT(InitialHeapSize) && InitialHeapSize > MaxHeapSize) {
184 FLAG_SET_ERGO(MaxHeapSize, InitialHeapSize);
185 } else if (!FLAG_IS_DEFAULT(MaxHeapSize) && InitialHeapSize > MaxHeapSize) {
186 FLAG_SET_ERGO(InitialHeapSize, MaxHeapSize);
187 if (InitialHeapSize < MinHeapSize) {
188 FLAG_SET_ERGO(MinHeapSize, InitialHeapSize);
189 }
190 }
191
192 if (FLAG_IS_DEFAULT(SoftMaxHeapSize)) {
193 FLAG_SET_ERGO(SoftMaxHeapSize, MaxHeapSize);
194 }
195
196 FLAG_SET_ERGO(MinHeapDeltaBytes, align_up(MinHeapDeltaBytes, SpaceAlignment));
197
198 DEBUG_ONLY(assert_flags();)
199}
200