Mercurial > hg > truffle
annotate src/share/vm/c1/c1_FrameMap.cpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | a9becfeecd1b |
children | 4ca6dc0799b6 |
rev | line source |
---|---|
0 | 1 /* |
17467
55fb97c4c58d
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
8668
diff
changeset
|
2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
337
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
337
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
337
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "c1/c1_FrameMap.hpp" | |
27 #include "c1/c1_LIR.hpp" | |
28 #include "runtime/sharedRuntime.hpp" | |
29 #ifdef TARGET_ARCH_x86 | |
30 # include "vmreg_x86.inline.hpp" | |
31 #endif | |
32 #ifdef TARGET_ARCH_sparc | |
33 # include "vmreg_sparc.inline.hpp" | |
34 #endif | |
35 #ifdef TARGET_ARCH_zero | |
36 # include "vmreg_zero.inline.hpp" | |
37 #endif | |
2192
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2093
diff
changeset
|
38 #ifdef TARGET_ARCH_arm |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2093
diff
changeset
|
39 # include "vmreg_arm.inline.hpp" |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2093
diff
changeset
|
40 #endif |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2093
diff
changeset
|
41 #ifdef TARGET_ARCH_ppc |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2093
diff
changeset
|
42 # include "vmreg_ppc.inline.hpp" |
b92c45f2bc75
7016023: Enable building ARM and PPC from src/closed repository
bobv
parents:
2093
diff
changeset
|
43 #endif |
0 | 44 |
45 | |
46 | |
47 //----------------------------------------------------- | |
48 | |
49 // Convert method signature into an array of BasicTypes for the arguments | |
50 BasicTypeArray* FrameMap::signature_type_array_for(const ciMethod* method) { | |
51 ciSignature* sig = method->signature(); | |
52 BasicTypeList* sta = new BasicTypeList(method->arg_size()); | |
53 // add receiver, if any | |
54 if (!method->is_static()) sta->append(T_OBJECT); | |
55 // add remaining arguments | |
56 for (int i = 0; i < sig->count(); i++) { | |
57 ciType* type = sig->type_at(i); | |
58 BasicType t = type->basic_type(); | |
59 if (t == T_ARRAY) { | |
60 t = T_OBJECT; | |
61 } | |
62 sta->append(t); | |
63 } | |
64 // done | |
65 return sta; | |
66 } | |
67 | |
68 | |
69 CallingConvention* FrameMap::java_calling_convention(const BasicTypeArray* signature, bool outgoing) { | |
70 // compute the size of the arguments first. The signature array | |
71 // that java_calling_convention takes includes a T_VOID after double | |
72 // work items but our signatures do not. | |
73 int i; | |
74 int sizeargs = 0; | |
75 for (i = 0; i < signature->length(); i++) { | |
76 sizeargs += type2size[signature->at(i)]; | |
77 } | |
78 | |
79 BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sizeargs); | |
80 VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, sizeargs); | |
81 int sig_index = 0; | |
82 for (i = 0; i < sizeargs; i++, sig_index++) { | |
83 sig_bt[i] = signature->at(sig_index); | |
84 if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { | |
85 sig_bt[i + 1] = T_VOID; | |
86 i++; | |
87 } | |
88 } | |
89 | |
90 intptr_t out_preserve = SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs, outgoing); | |
91 LIR_OprList* args = new LIR_OprList(signature->length()); | |
92 for (i = 0; i < sizeargs;) { | |
93 BasicType t = sig_bt[i]; | |
94 assert(t != T_VOID, "should be skipping these"); | |
95 LIR_Opr opr = map_to_opr(t, regs + i, outgoing); | |
96 args->append(opr); | |
97 if (opr->is_address()) { | |
98 LIR_Address* addr = opr->as_address_ptr(); | |
99 assert(addr->disp() == (int)addr->disp(), "out of range value"); | |
2093 | 100 out_preserve = MAX2(out_preserve, (intptr_t)(addr->disp() - STACK_BIAS) / 4); |
0 | 101 } |
102 i += type2size[t]; | |
103 } | |
104 assert(args->length() == signature->length(), "size mismatch"); | |
105 out_preserve += SharedRuntime::out_preserve_stack_slots(); | |
106 | |
107 if (outgoing) { | |
108 // update the space reserved for arguments. | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
109 update_reserved_argument_area_size(out_preserve * BytesPerWord); |
0 | 110 } |
111 return new CallingConvention(args, out_preserve); | |
112 } | |
113 | |
114 | |
115 CallingConvention* FrameMap::c_calling_convention(const BasicTypeArray* signature) { | |
116 // compute the size of the arguments first. The signature array | |
117 // that java_calling_convention takes includes a T_VOID after double | |
118 // work items but our signatures do not. | |
119 int i; | |
120 int sizeargs = 0; | |
121 for (i = 0; i < signature->length(); i++) { | |
122 sizeargs += type2size[signature->at(i)]; | |
123 } | |
124 | |
125 BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sizeargs); | |
126 VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, sizeargs); | |
127 int sig_index = 0; | |
128 for (i = 0; i < sizeargs; i++, sig_index++) { | |
129 sig_bt[i] = signature->at(sig_index); | |
130 if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { | |
131 sig_bt[i + 1] = T_VOID; | |
132 i++; | |
133 } | |
134 } | |
135 | |
14416
6a936747b569
8024344: PPC64 (part 112): C argument in register AND stack slot.
goetz
parents:
8668
diff
changeset
|
136 intptr_t out_preserve = SharedRuntime::c_calling_convention(sig_bt, regs, NULL, sizeargs); |
0 | 137 LIR_OprList* args = new LIR_OprList(signature->length()); |
138 for (i = 0; i < sizeargs;) { | |
139 BasicType t = sig_bt[i]; | |
140 assert(t != T_VOID, "should be skipping these"); | |
141 | |
142 // C calls are always outgoing | |
143 bool outgoing = true; | |
144 LIR_Opr opr = map_to_opr(t, regs + i, outgoing); | |
145 // they might be of different types if for instance floating point | |
146 // values are passed in cpu registers, but the sizes must match. | |
147 assert(type2size[opr->type()] == type2size[t], "type mismatch"); | |
148 args->append(opr); | |
149 if (opr->is_address()) { | |
150 LIR_Address* addr = opr->as_address_ptr(); | |
2093 | 151 out_preserve = MAX2(out_preserve, (intptr_t)(addr->disp() - STACK_BIAS) / 4); |
0 | 152 } |
153 i += type2size[t]; | |
154 } | |
155 assert(args->length() == signature->length(), "size mismatch"); | |
156 out_preserve += SharedRuntime::out_preserve_stack_slots(); | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1584
diff
changeset
|
157 update_reserved_argument_area_size(out_preserve * BytesPerWord); |
0 | 158 return new CallingConvention(args, out_preserve); |
159 } | |
160 | |
161 | |
162 //-------------------------------------------------------- | |
163 // FrameMap | |
164 //-------------------------------------------------------- | |
165 | |
166 bool FrameMap::_init_done = false; | |
167 Register FrameMap::_cpu_rnr2reg [FrameMap::nof_cpu_regs]; | |
168 int FrameMap::_cpu_reg2rnr [FrameMap::nof_cpu_regs]; | |
169 | |
170 | |
171 FrameMap::FrameMap(ciMethod* method, int monitors, int reserved_argument_area_size) { | |
1584 | 172 assert(_init_done, "should already be completed"); |
0 | 173 |
174 _framesize = -1; | |
175 _num_spills = -1; | |
176 | |
177 assert(monitors >= 0, "not set"); | |
178 _num_monitors = monitors; | |
179 assert(reserved_argument_area_size >= 0, "not set"); | |
180 _reserved_argument_area_size = MAX2(4, reserved_argument_area_size) * BytesPerWord; | |
181 | |
182 _argcount = method->arg_size(); | |
183 _argument_locations = new intArray(_argcount, -1); | |
184 _incoming_arguments = java_calling_convention(signature_type_array_for(method), false); | |
185 _oop_map_arg_count = _incoming_arguments->reserved_stack_slots(); | |
186 | |
187 int java_index = 0; | |
188 for (int i = 0; i < _incoming_arguments->length(); i++) { | |
189 LIR_Opr opr = _incoming_arguments->at(i); | |
190 if (opr->is_address()) { | |
191 LIR_Address* address = opr->as_address_ptr(); | |
192 _argument_locations->at_put(java_index, address->disp() - STACK_BIAS); | |
193 _incoming_arguments->args()->at_put(i, LIR_OprFact::stack(java_index, as_BasicType(as_ValueType(address->type())))); | |
194 } | |
195 java_index += type2size[opr->type()]; | |
196 } | |
197 | |
198 } | |
199 | |
200 | |
201 bool FrameMap::finalize_frame(int nof_slots) { | |
202 assert(nof_slots >= 0, "must be positive"); | |
203 assert(_num_spills == -1, "can only be set once"); | |
204 _num_spills = nof_slots; | |
205 assert(_framesize == -1, "should only be calculated once"); | |
206 _framesize = round_to(in_bytes(sp_offset_for_monitor_base(0)) + | |
207 _num_monitors * sizeof(BasicObjectLock) + | |
208 sizeof(intptr_t) + // offset of deopt orig pc | |
209 frame_pad_in_bytes, | |
210 StackAlignmentInBytes) / 4; | |
211 int java_index = 0; | |
212 for (int i = 0; i < _incoming_arguments->length(); i++) { | |
213 LIR_Opr opr = _incoming_arguments->at(i); | |
214 if (opr->is_stack()) { | |
215 _argument_locations->at_put(java_index, in_bytes(framesize_in_bytes()) + | |
216 _argument_locations->at(java_index)); | |
217 } | |
218 java_index += type2size[opr->type()]; | |
219 } | |
220 // make sure it's expressible on the platform | |
221 return validate_frame(); | |
222 } | |
223 | |
224 VMReg FrameMap::sp_offset2vmreg(ByteSize offset) const { | |
225 int offset_in_bytes = in_bytes(offset); | |
226 assert(offset_in_bytes % 4 == 0, "must be multiple of 4 bytes"); | |
227 assert(offset_in_bytes / 4 < framesize() + oop_map_arg_count(), "out of range"); | |
228 return VMRegImpl::stack2reg(offset_in_bytes / 4); | |
229 } | |
230 | |
231 | |
232 bool FrameMap::location_for_sp_offset(ByteSize byte_offset_from_sp, | |
233 Location::Type loc_type, | |
234 Location* loc) const { | |
235 int offset = in_bytes(byte_offset_from_sp); | |
236 assert(offset >= 0, "incorrect offset"); | |
237 if (!Location::legal_offset_in_bytes(offset)) { | |
238 return false; | |
239 } | |
240 Location tmp_loc = Location::new_stk_loc(loc_type, offset); | |
241 *loc = tmp_loc; | |
242 return true; | |
243 } | |
244 | |
245 | |
246 bool FrameMap::locations_for_slot (int index, Location::Type loc_type, | |
247 Location* loc, Location* second) const { | |
248 ByteSize offset_from_sp = sp_offset_for_slot(index); | |
249 if (!location_for_sp_offset(offset_from_sp, loc_type, loc)) { | |
250 return false; | |
251 } | |
252 if (second != NULL) { | |
253 // two word item | |
254 offset_from_sp = offset_from_sp + in_ByteSize(4); | |
255 return location_for_sp_offset(offset_from_sp, loc_type, second); | |
256 } | |
257 return true; | |
258 } | |
259 | |
260 ////////////////////// | |
261 // Public accessors // | |
262 ////////////////////// | |
263 | |
264 | |
265 ByteSize FrameMap::sp_offset_for_slot(const int index) const { | |
266 if (index < argcount()) { | |
267 int offset = _argument_locations->at(index); | |
268 assert(offset != -1, "not a memory argument"); | |
269 assert(offset >= framesize() * 4, "argument inside of frame"); | |
270 return in_ByteSize(offset); | |
271 } | |
272 ByteSize offset = sp_offset_for_spill(index - argcount()); | |
273 assert(in_bytes(offset) < framesize() * 4, "spill outside of frame"); | |
274 return offset; | |
275 } | |
276 | |
277 | |
278 ByteSize FrameMap::sp_offset_for_double_slot(const int index) const { | |
279 ByteSize offset = sp_offset_for_slot(index); | |
280 if (index >= argcount()) { | |
281 assert(in_bytes(offset) + 4 < framesize() * 4, "spill outside of frame"); | |
282 } | |
283 return offset; | |
284 } | |
285 | |
286 | |
287 ByteSize FrameMap::sp_offset_for_spill(const int index) const { | |
288 assert(index >= 0 && index < _num_spills, "out of range"); | |
289 int offset = round_to(first_available_sp_in_frame + _reserved_argument_area_size, sizeof(double)) + | |
290 index * spill_slot_size_in_bytes; | |
291 return in_ByteSize(offset); | |
292 } | |
293 | |
294 ByteSize FrameMap::sp_offset_for_monitor_base(const int index) const { | |
295 int end_of_spills = round_to(first_available_sp_in_frame + _reserved_argument_area_size, sizeof(double)) + | |
296 _num_spills * spill_slot_size_in_bytes; | |
304 | 297 int offset = (int) round_to(end_of_spills, HeapWordSize) + index * sizeof(BasicObjectLock); |
0 | 298 return in_ByteSize(offset); |
299 } | |
300 | |
301 ByteSize FrameMap::sp_offset_for_monitor_lock(int index) const { | |
302 check_monitor_index(index); | |
303 return sp_offset_for_monitor_base(index) + in_ByteSize(BasicObjectLock::lock_offset_in_bytes());; | |
304 } | |
305 | |
306 ByteSize FrameMap::sp_offset_for_monitor_object(int index) const { | |
307 check_monitor_index(index); | |
308 return sp_offset_for_monitor_base(index) + in_ByteSize(BasicObjectLock::obj_offset_in_bytes()); | |
309 } | |
310 | |
311 | |
312 // For OopMaps, map a local variable or spill index to an VMReg. | |
313 // This is the offset from sp() in the frame of the slot for the index, | |
314 // skewed by SharedInfo::stack0 to indicate a stack location (vs.a register.) | |
315 // | |
316 // C ABI size + | |
317 // framesize + framesize + | |
318 // stack0 stack0 stack0 0 <- VMReg->value() | |
319 // | | | <registers> | | |
320 // ..........|..............|..............|.............| | |
321 // 0 1 2 3 | <C ABI area> | 4 5 6 ...... | <- local indices | |
322 // ^ ^ sp() | |
323 // | | | |
324 // arguments non-argument locals | |
325 | |
326 | |
327 VMReg FrameMap::regname(LIR_Opr opr) const { | |
328 if (opr->is_single_cpu()) { | |
329 assert(!opr->is_virtual(), "should not see virtual registers here"); | |
330 return opr->as_register()->as_VMReg(); | |
331 } else if (opr->is_single_stack()) { | |
332 return sp_offset2vmreg(sp_offset_for_slot(opr->single_stack_ix())); | |
333 } else if (opr->is_address()) { | |
334 LIR_Address* addr = opr->as_address_ptr(); | |
335 assert(addr->base() == stack_pointer(), "sp based addressing only"); | |
336 return sp_offset2vmreg(in_ByteSize(addr->index()->as_jint())); | |
337 } | |
338 ShouldNotReachHere(); | |
339 return VMRegImpl::Bad(); | |
340 } | |
341 | |
342 | |
343 | |
344 | |
345 // ------------ extra spill slots --------------- |