Mercurial > hg > truffle
annotate src/share/vm/compiler/oopMap.cpp @ 6862:8a5ea0a9ccc4
7127708: G1: change task num types from int to uint in concurrent mark
Summary: Change the type of various task num fields, parameters etc to unsigned and rename them to be more consistent with the other collectors. Code changes were also reviewed by Vitaly Davidovich.
Reviewed-by: johnc
Contributed-by: Kaushik Srenevasan <kaushik@twitter.com>
author | johnc |
---|---|
date | Sat, 06 Oct 2012 01:17:44 -0700 |
parents | d2a62e0f25eb |
children | 957c266d8bc5 b9a9ed0f8eeb |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 1998, 2010, 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:
948
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
948
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:
948
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "code/codeBlob.hpp" | |
27 #include "code/codeCache.hpp" | |
28 #include "code/nmethod.hpp" | |
29 #include "code/scopeDesc.hpp" | |
30 #include "compiler/oopMap.hpp" | |
31 #include "gc_interface/collectedHeap.hpp" | |
32 #include "memory/allocation.inline.hpp" | |
33 #include "memory/resourceArea.hpp" | |
34 #include "runtime/frame.inline.hpp" | |
35 #include "runtime/signature.hpp" | |
36 #ifdef COMPILER1 | |
37 #include "c1/c1_Defs.hpp" | |
38 #endif | |
0 | 39 |
40 // OopMapStream | |
41 | |
42 OopMapStream::OopMapStream(OopMap* oop_map) { | |
43 if(oop_map->omv_data() == NULL) { | |
44 _stream = new CompressedReadStream(oop_map->write_stream()->buffer()); | |
45 } else { | |
46 _stream = new CompressedReadStream(oop_map->omv_data()); | |
47 } | |
48 _mask = OopMapValue::type_mask_in_place; | |
49 _size = oop_map->omv_count(); | |
50 _position = 0; | |
51 _valid_omv = false; | |
52 } | |
53 | |
54 | |
55 OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) { | |
56 if(oop_map->omv_data() == NULL) { | |
57 _stream = new CompressedReadStream(oop_map->write_stream()->buffer()); | |
58 } else { | |
59 _stream = new CompressedReadStream(oop_map->omv_data()); | |
60 } | |
61 _mask = oop_types_mask; | |
62 _size = oop_map->omv_count(); | |
63 _position = 0; | |
64 _valid_omv = false; | |
65 } | |
66 | |
67 | |
68 void OopMapStream::find_next() { | |
69 while(_position++ < _size) { | |
70 _omv.read_from(_stream); | |
71 if(((int)_omv.type() & _mask) > 0) { | |
72 _valid_omv = true; | |
73 return; | |
74 } | |
75 } | |
76 _valid_omv = false; | |
77 } | |
78 | |
79 | |
80 // OopMap | |
81 | |
82 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd | |
83 // slots to hold 4-byte values like ints and floats in the LP64 build. | |
84 OopMap::OopMap(int frame_size, int arg_count) { | |
85 // OopMaps are usually quite so small, so pick a small initial size | |
86 set_write_stream(new CompressedWriteStream(32)); | |
87 set_omv_data(NULL); | |
88 set_omv_count(0); | |
89 | |
90 #ifdef ASSERT | |
91 _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count; | |
92 _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length); | |
93 for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value; | |
94 #endif | |
95 } | |
96 | |
97 | |
98 OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) { | |
99 // This constructor does a deep copy | |
100 // of the source OopMap. | |
101 set_write_stream(new CompressedWriteStream(source->omv_count() * 2)); | |
102 set_omv_data(NULL); | |
103 set_omv_count(0); | |
104 set_offset(source->offset()); | |
105 | |
106 #ifdef ASSERT | |
107 _locs_length = source->_locs_length; | |
108 _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length); | |
109 for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value; | |
110 #endif | |
111 | |
112 // We need to copy the entries too. | |
113 for (OopMapStream oms(source); !oms.is_done(); oms.next()) { | |
114 OopMapValue omv = oms.current(); | |
115 omv.write_on(write_stream()); | |
116 increment_count(); | |
117 } | |
118 } | |
119 | |
120 | |
121 OopMap* OopMap::deep_copy() { | |
122 return new OopMap(_deep_copy_token, this); | |
123 } | |
124 | |
125 | |
126 void OopMap::copy_to(address addr) { | |
127 memcpy(addr,this,sizeof(OopMap)); | |
128 memcpy(addr + sizeof(OopMap),write_stream()->buffer(),write_stream()->position()); | |
129 OopMap* new_oop = (OopMap*)addr; | |
130 new_oop->set_omv_data_size(write_stream()->position()); | |
131 new_oop->set_omv_data((unsigned char *)(addr + sizeof(OopMap))); | |
132 new_oop->set_write_stream(NULL); | |
133 } | |
134 | |
135 | |
136 int OopMap::heap_size() const { | |
137 int size = sizeof(OopMap); | |
138 int align = sizeof(void *) - 1; | |
139 if(write_stream() != NULL) { | |
140 size += write_stream()->position(); | |
141 } else { | |
142 size += omv_data_size(); | |
143 } | |
144 // Align to a reasonable ending point | |
145 size = ((size+align) & ~align); | |
146 return size; | |
147 } | |
148 | |
149 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd | |
150 // slots to hold 4-byte values like ints and floats in the LP64 build. | |
151 void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) { | |
152 | |
153 assert(reg->value() < _locs_length, "too big reg value for stack size"); | |
154 assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" ); | |
155 debug_only( _locs_used[reg->value()] = x; ) | |
156 | |
157 OopMapValue o(reg, x); | |
158 | |
159 if(x == OopMapValue::callee_saved_value) { | |
160 // This can never be a stack location, so we don't need to transform it. | |
161 assert(optional->is_reg(), "Trying to callee save a stack location"); | |
162 o.set_content_reg(optional); | |
163 } else if(x == OopMapValue::derived_oop_value) { | |
164 o.set_content_reg(optional); | |
165 } | |
166 | |
167 o.write_on(write_stream()); | |
168 increment_count(); | |
169 } | |
170 | |
171 | |
172 void OopMap::set_oop(VMReg reg) { | |
173 set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad()); | |
174 } | |
175 | |
176 | |
177 void OopMap::set_value(VMReg reg) { | |
178 // At this time, we only need value entries in our OopMap when ZapDeadCompiledLocals is active. | |
179 if (ZapDeadCompiledLocals) | |
180 set_xxx(reg, OopMapValue::value_value, VMRegImpl::Bad()); | |
181 } | |
182 | |
183 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
184 void OopMap::set_narrowoop(VMReg reg) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
185 set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad()); |
0 | 186 } |
187 | |
188 | |
189 void OopMap::set_callee_saved(VMReg reg, VMReg caller_machine_register ) { | |
190 set_xxx(reg, OopMapValue::callee_saved_value, caller_machine_register); | |
191 } | |
192 | |
193 | |
194 void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) { | |
195 if( reg == derived_from_local_register ) { | |
196 // Actually an oop, derived shares storage with base, | |
197 set_oop(reg); | |
198 } else { | |
199 set_xxx(reg, OopMapValue::derived_oop_value, derived_from_local_register); | |
200 } | |
201 } | |
202 | |
203 // OopMapSet | |
204 | |
205 OopMapSet::OopMapSet() { | |
206 set_om_size(MinOopMapAllocation); | |
207 set_om_count(0); | |
208 OopMap** temp = NEW_RESOURCE_ARRAY(OopMap*, om_size()); | |
209 set_om_data(temp); | |
210 } | |
211 | |
212 | |
213 void OopMapSet::grow_om_data() { | |
214 int new_size = om_size() * 2; | |
215 OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size); | |
216 memcpy(new_data,om_data(),om_size() * sizeof(OopMap*)); | |
217 set_om_size(new_size); | |
218 set_om_data(new_data); | |
219 } | |
220 | |
221 | |
222 void OopMapSet::copy_to(address addr) { | |
223 address temp = addr; | |
224 int align = sizeof(void *) - 1; | |
225 // Copy this | |
226 memcpy(addr,this,sizeof(OopMapSet)); | |
227 temp += sizeof(OopMapSet); | |
228 temp = (address)((intptr_t)(temp + align) & ~align); | |
229 // Do the needed fixups to the new OopMapSet | |
230 OopMapSet* new_set = (OopMapSet*)addr; | |
231 new_set->set_om_data((OopMap**)temp); | |
232 // Allow enough space for the OopMap pointers | |
233 temp += (om_count() * sizeof(OopMap*)); | |
234 | |
235 for(int i=0; i < om_count(); i++) { | |
236 OopMap* map = at(i); | |
237 map->copy_to((address)temp); | |
238 new_set->set(i,(OopMap*)temp); | |
239 temp += map->heap_size(); | |
240 } | |
241 // This "locks" the OopMapSet | |
242 new_set->set_om_size(-1); | |
243 } | |
244 | |
245 | |
246 void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) { | |
247 assert(om_size() != -1,"Cannot grow a fixed OopMapSet"); | |
248 | |
249 if(om_count() >= om_size()) { | |
250 grow_om_data(); | |
251 } | |
252 map->set_offset(pc_offset); | |
253 | |
254 #ifdef ASSERT | |
255 if(om_count() > 0) { | |
256 OopMap* last = at(om_count()-1); | |
257 if (last->offset() == map->offset() ) { | |
258 fatal("OopMap inserted twice"); | |
259 } | |
260 if(last->offset() > map->offset()) { | |
261 tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d", | |
262 om_count(),last->offset(),om_count()+1,map->offset()); | |
263 } | |
264 } | |
265 #endif // ASSERT | |
266 | |
267 set(om_count(),map); | |
268 increment_count(); | |
269 } | |
270 | |
271 | |
272 int OopMapSet::heap_size() const { | |
273 // The space we use | |
274 int size = sizeof(OopMap); | |
275 int align = sizeof(void *) - 1; | |
276 size = ((size+align) & ~align); | |
277 size += om_count() * sizeof(OopMap*); | |
278 | |
279 // Now add in the space needed for the indivdiual OopMaps | |
280 for(int i=0; i < om_count(); i++) { | |
281 size += at(i)->heap_size(); | |
282 } | |
283 // We don't need to align this, it will be naturally pointer aligned | |
284 return size; | |
285 } | |
286 | |
287 | |
288 OopMap* OopMapSet::singular_oop_map() { | |
289 guarantee(om_count() == 1, "Make sure we only have a single gc point"); | |
290 return at(0); | |
291 } | |
292 | |
293 | |
294 OopMap* OopMapSet::find_map_at_offset(int pc_offset) const { | |
295 int i, len = om_count(); | |
296 assert( len > 0, "must have pointer maps" ); | |
297 | |
298 // Scan through oopmaps. Stop when current offset is either equal or greater | |
299 // than the one we are looking for. | |
300 for( i = 0; i < len; i++) { | |
301 if( at(i)->offset() >= pc_offset ) | |
302 break; | |
303 } | |
304 | |
305 assert( i < len, "oopmap not found" ); | |
306 | |
307 OopMap* m = at(i); | |
308 assert( m->offset() == pc_offset, "oopmap not found" ); | |
309 return m; | |
310 } | |
311 | |
312 class DoNothingClosure: public OopClosure { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
313 public: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
314 void do_oop(oop* p) {} |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
315 void do_oop(narrowOop* p) {} |
0 | 316 }; |
317 static DoNothingClosure do_nothing; | |
318 | |
319 static void add_derived_oop(oop* base, oop* derived) { | |
320 #ifndef TIERED | |
321 COMPILER1_PRESENT(ShouldNotReachHere();) | |
322 #endif // TIERED | |
323 #ifdef COMPILER2 | |
324 DerivedPointerTable::add(derived, base); | |
325 #endif // COMPILER2 | |
326 } | |
327 | |
328 | |
329 #ifndef PRODUCT | |
330 static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) { | |
331 // Print oopmap and regmap | |
332 tty->print_cr("------ "); | |
333 CodeBlob* cb = fr->cb(); | |
334 OopMapSet* maps = cb->oop_maps(); | |
335 OopMap* map = cb->oop_map_for_return_address(fr->pc()); | |
336 map->print(); | |
337 if( cb->is_nmethod() ) { | |
338 nmethod* nm = (nmethod*)cb; | |
339 // native wrappers have no scope data, it is implied | |
340 if (nm->is_native_method()) { | |
341 tty->print("bci: 0 (native)"); | |
342 } else { | |
343 ScopeDesc* scope = nm->scope_desc_at(fr->pc()); | |
344 tty->print("bci: %d ",scope->bci()); | |
345 } | |
346 } | |
347 tty->cr(); | |
348 fr->print_on(tty); | |
349 tty->print(" "); | |
350 cb->print_value_on(tty); tty->cr(); | |
351 reg_map->print(); | |
352 tty->print_cr("------ "); | |
353 | |
354 } | |
355 #endif // PRODUCT | |
356 | |
357 void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) { | |
358 // add derived oops to a table | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
359 all_do(fr, reg_map, f, add_derived_oop, &do_nothing); |
0 | 360 } |
361 | |
362 | |
363 void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, | |
364 OopClosure* oop_fn, void derived_oop_fn(oop*, oop*), | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
365 OopClosure* value_fn) { |
0 | 366 CodeBlob* cb = fr->cb(); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
367 assert(cb != NULL, "no codeblob"); |
0 | 368 |
369 NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);) | |
370 | |
371 OopMapSet* maps = cb->oop_maps(); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
372 OopMap* map = cb->oop_map_for_return_address(fr->pc()); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
373 assert(map != NULL, "no ptr map found"); |
0 | 374 |
375 // handle derived pointers first (otherwise base pointer may be | |
376 // changed before derived pointer offset has been collected) | |
377 OopMapValue omv; | |
378 { | |
379 OopMapStream oms(map,OopMapValue::derived_oop_value); | |
380 if (!oms.is_done()) { | |
381 #ifndef TIERED | |
382 COMPILER1_PRESENT(ShouldNotReachHere();) | |
383 #endif // !TIERED | |
384 // Protect the operation on the derived pointers. This | |
385 // protects the addition of derived pointers to the shared | |
386 // derived pointer table in DerivedPointerTable::add(). | |
387 MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag); | |
388 do { | |
389 omv = oms.current(); | |
390 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); | |
391 if ( loc != NULL ) { | |
392 oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); | |
393 oop *derived_loc = loc; | |
858 | 394 oop val = *base_loc; |
395 if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { | |
396 // Ignore NULL oops and decoded NULL narrow oops which | |
397 // equal to Universe::narrow_oop_base when a narrow oop | |
398 // implicit null check is used in compiled code. | |
399 // The narrow_oop_base could be NULL or be the address | |
400 // of the page below heap depending on compressed oops mode. | |
401 } else | |
402 derived_oop_fn(base_loc, derived_loc); | |
0 | 403 } |
404 oms.next(); | |
405 } while (!oms.is_done()); | |
406 } | |
407 } | |
408 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
409 // We want coop, value and oop oop_types |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
410 int mask = OopMapValue::oop_value | OopMapValue::value_value | OopMapValue::narrowoop_value; |
0 | 411 { |
412 for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) { | |
413 omv = oms.current(); | |
414 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); | |
415 if ( loc != NULL ) { | |
416 if ( omv.type() == OopMapValue::oop_value ) { | |
858 | 417 oop val = *loc; |
418 if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) { | |
419 // Ignore NULL oops and decoded NULL narrow oops which | |
420 // equal to Universe::narrow_oop_base when a narrow oop | |
421 // implicit null check is used in compiled code. | |
422 // The narrow_oop_base could be NULL or be the address | |
423 // of the page below heap depending on compressed oops mode. | |
424 continue; | |
425 } | |
0 | 426 #ifdef ASSERT |
244
524eca34ea76
6684714: Optimize EA Connection Graph build performance
kvn
parents:
113
diff
changeset
|
427 if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
428 !Universe::heap()->is_in_or_null(*loc)) { |
0 | 429 tty->print_cr("# Found non oop pointer. Dumping state at failure"); |
430 // try to dump out some helpful debugging information | |
431 trace_codeblob_maps(fr, reg_map); | |
432 omv.print(); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
433 tty->print_cr("register r"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
434 omv.reg()->print(); |
0 | 435 tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc); |
436 // do the real assert. | |
437 assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer"); | |
438 } | |
439 #endif // ASSERT | |
440 oop_fn->do_oop(loc); | |
441 } else if ( omv.type() == OopMapValue::value_value ) { | |
858 | 442 assert((*loc) == (oop)NULL || !Universe::is_narrow_oop_base(*loc), |
443 "found invalid value pointer"); | |
0 | 444 value_fn->do_oop(loc); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
445 } else if ( omv.type() == OopMapValue::narrowoop_value ) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
446 narrowOop *nl = (narrowOop*)loc; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
447 #ifndef VM_LITTLE_ENDIAN |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
448 if (!omv.reg()->is_stack()) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
449 // compressed oops in registers only take up 4 bytes of an |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
450 // 8 byte register but they are in the wrong part of the |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
451 // word so adjust loc to point at the right place. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
452 nl = (narrowOop*)((address)nl + 4); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
453 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
454 #endif |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
455 oop_fn->do_oop(nl); |
0 | 456 } |
457 } | |
458 } | |
459 } | |
460 } | |
461 | |
462 | |
463 // Update callee-saved register info for the following frame | |
464 void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) { | |
465 ResourceMark rm; | |
466 CodeBlob* cb = fr->cb(); | |
467 assert(cb != NULL, "no codeblob"); | |
468 | |
469 // Any reg might be saved by a safepoint handler (see generate_handler_blob). | |
470 const int max_saved_on_entry_reg_count = ConcreteRegisterImpl::number_of_registers; | |
471 assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id), | |
472 "already updated this map; do not 'update' it twice!" ); | |
473 debug_only(reg_map->_update_for_id = fr->id()); | |
474 | |
475 // Check if caller must update oop argument | |
476 assert((reg_map->include_argument_oops() || | |
477 !cb->caller_must_gc_arguments(reg_map->thread())), | |
478 "include_argument_oops should already be set"); | |
479 | |
480 int nof_callee = 0; | |
481 oop* locs[2*max_saved_on_entry_reg_count+1]; | |
482 VMReg regs[2*max_saved_on_entry_reg_count+1]; | |
483 // ("+1" because max_saved_on_entry_reg_count might be zero) | |
484 | |
485 // Scan through oopmap and find location of all callee-saved registers | |
486 // (we do not do update in place, since info could be overwritten) | |
487 | |
488 address pc = fr->pc(); | |
489 | |
490 OopMap* map = cb->oop_map_for_return_address(pc); | |
491 | |
492 assert(map != NULL, " no ptr map found"); | |
493 | |
494 OopMapValue omv; | |
495 for(OopMapStream oms(map,OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { | |
496 omv = oms.current(); | |
497 assert(nof_callee < 2*max_saved_on_entry_reg_count, "overflow"); | |
498 regs[nof_callee] = omv.content_reg(); | |
499 locs[nof_callee] = fr->oopmapreg_to_location(omv.reg(),reg_map); | |
500 nof_callee++; | |
501 } | |
502 | |
503 // Check that runtime stubs save all callee-saved registers | |
504 #ifdef COMPILER2 | |
505 assert(cb->is_compiled_by_c1() || !cb->is_runtime_stub() || | |
506 (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT), | |
507 "must save all"); | |
508 #endif // COMPILER2 | |
509 | |
510 // Copy found callee-saved register to reg_map | |
511 for(int i = 0; i < nof_callee; i++) { | |
512 reg_map->set_location(regs[i], (address)locs[i]); | |
513 } | |
514 } | |
515 | |
516 //============================================================================= | |
517 // Non-Product code | |
518 | |
519 #ifndef PRODUCT | |
520 | |
521 bool OopMap::has_derived_pointer() const { | |
522 #ifndef TIERED | |
523 COMPILER1_PRESENT(return false); | |
524 #endif // !TIERED | |
525 #ifdef COMPILER2 | |
526 OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value); | |
527 return oms.is_done(); | |
528 #else | |
529 return false; | |
530 #endif // COMPILER2 | |
531 } | |
532 | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
533 #endif //PRODUCT |
0 | 534 |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
535 // Printing code is present in product build for -XX:+PrintAssembly. |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
536 |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
537 static |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
538 void print_register_type(OopMapValue::oop_types x, VMReg optional, |
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
539 outputStream* st) { |
0 | 540 switch( x ) { |
541 case OopMapValue::oop_value: | |
25
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
542 st->print("Oop"); |
0 | 543 break; |
544 case OopMapValue::value_value: | |
25
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
545 st->print("Value" ); |
0 | 546 break; |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
547 case OopMapValue::narrowoop_value: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
100
diff
changeset
|
548 tty->print("NarrowOop" ); |
0 | 549 break; |
550 case OopMapValue::callee_saved_value: | |
25
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
551 st->print("Callers_" ); |
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
552 optional->print_on(st); |
0 | 553 break; |
554 case OopMapValue::derived_oop_value: | |
25
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
555 st->print("Derived_oop_" ); |
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
556 optional->print_on(st); |
0 | 557 break; |
558 default: | |
559 ShouldNotReachHere(); | |
560 } | |
561 } | |
562 | |
563 | |
25
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
564 void OopMapValue::print_on(outputStream* st) const { |
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
565 reg()->print_on(st); |
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
566 st->print("="); |
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
567 print_register_type(type(),content_reg(),st); |
c5cbd367e4d1
6621094: PrintOptoAssembly is broken for oops information in DebugInfo
kvn
parents:
0
diff
changeset
|
568 st->print(" "); |
0 | 569 } |
570 | |
571 | |
572 void OopMap::print_on(outputStream* st) const { | |
573 OopMapValue omv; | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
574 st->print("OopMap{"); |
0 | 575 for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) { |
576 omv = oms.current(); | |
577 omv.print_on(st); | |
578 } | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
579 st->print("off=%d}", (int) offset()); |
0 | 580 } |
581 | |
582 | |
583 void OopMapSet::print_on(outputStream* st) const { | |
584 int i, len = om_count(); | |
585 | |
586 st->print_cr("OopMapSet contains %d OopMaps\n",len); | |
587 | |
588 for( i = 0; i < len; i++) { | |
589 OopMap* m = at(i); | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
590 st->print_cr("#%d ",i); |
0 | 591 m->print_on(st); |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
592 st->cr(); |
0 | 593 } |
594 } | |
100
c7c777385a15
6667042: PrintAssembly option does not work without special plugin
jrose
parents:
25
diff
changeset
|
595 |
0 | 596 |
597 | |
598 //------------------------------DerivedPointerTable--------------------------- | |
599 | |
600 #ifdef COMPILER2 | |
601 | |
6197 | 602 class DerivedPointerEntry : public CHeapObj<mtCompiler> { |
0 | 603 private: |
604 oop* _location; // Location of derived pointer (also pointing to the base) | |
605 intptr_t _offset; // Offset from base pointer | |
606 public: | |
607 DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; } | |
608 oop* location() { return _location; } | |
609 intptr_t offset() { return _offset; } | |
610 }; | |
611 | |
612 | |
613 GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL; | |
614 bool DerivedPointerTable::_active = false; | |
615 | |
616 | |
617 void DerivedPointerTable::clear() { | |
618 // The first time, we create the list. Otherwise it should be | |
619 // empty. If not, then we have probably forgotton to call | |
620 // update_pointers after last GC/Scavenge. | |
621 assert (!_active, "should not be active"); | |
622 assert(_list == NULL || _list->length() == 0, "table not empty"); | |
623 if (_list == NULL) { | |
6197 | 624 _list = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<DerivedPointerEntry*>(10, true); // Allocated on C heap |
0 | 625 } |
626 _active = true; | |
627 } | |
628 | |
629 | |
630 // Returns value of location as an int | |
631 intptr_t value_of_loc(oop *pointer) { return (intptr_t)(*pointer); } | |
632 | |
633 | |
634 void DerivedPointerTable::add(oop *derived_loc, oop *base_loc) { | |
635 assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop"); | |
636 assert(derived_loc != base_loc, "Base and derived in same location"); | |
637 if (_active) { | |
638 assert(*derived_loc != (oop)base_loc, "location already added"); | |
639 assert(_list != NULL, "list must exist"); | |
640 intptr_t offset = value_of_loc(derived_loc) - value_of_loc(base_loc); | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
1972
diff
changeset
|
641 // This assert is invalid because derived pointers can be |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
1972
diff
changeset
|
642 // arbitrarily far away from their base. |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
1972
diff
changeset
|
643 // assert(offset >= -1000000, "wrong derived pointer info"); |
0 | 644 |
645 if (TraceDerivedPointers) { | |
646 tty->print_cr( | |
647 "Add derived pointer@" INTPTR_FORMAT | |
648 " - Derived: " INTPTR_FORMAT | |
649 " Base: " INTPTR_FORMAT " (@" INTPTR_FORMAT ") (Offset: %d)", | |
650 derived_loc, (address)*derived_loc, (address)*base_loc, base_loc, offset | |
651 ); | |
652 } | |
653 // Set derived oop location to point to base. | |
654 *derived_loc = (oop)base_loc; | |
655 assert_lock_strong(DerivedPointerTableGC_lock); | |
656 DerivedPointerEntry *entry = new DerivedPointerEntry(derived_loc, offset); | |
657 _list->append(entry); | |
658 } | |
659 } | |
660 | |
661 | |
662 void DerivedPointerTable::update_pointers() { | |
663 assert(_list != NULL, "list must exist"); | |
664 for(int i = 0; i < _list->length(); i++) { | |
665 DerivedPointerEntry* entry = _list->at(i); | |
666 oop* derived_loc = entry->location(); | |
667 intptr_t offset = entry->offset(); | |
668 // The derived oop was setup to point to location of base | |
669 oop base = **(oop**)derived_loc; | |
670 assert(Universe::heap()->is_in_or_null(base), "must be an oop"); | |
671 | |
672 *derived_loc = (oop)(((address)base) + offset); | |
673 assert(value_of_loc(derived_loc) - value_of_loc(&base) == offset, "sanity check"); | |
674 | |
675 if (TraceDerivedPointers) { | |
676 tty->print_cr("Updating derived pointer@" INTPTR_FORMAT | |
677 " - Derived: " INTPTR_FORMAT " Base: " INTPTR_FORMAT " (Offset: %d)", | |
678 derived_loc, (address)*derived_loc, (address)base, offset); | |
679 } | |
680 | |
681 // Delete entry | |
682 delete entry; | |
683 _list->at_put(i, NULL); | |
684 } | |
685 // Clear list, so it is ready for next traversal (this is an invariant) | |
686 if (TraceDerivedPointers && !_list->is_empty()) { | |
687 tty->print_cr("--------------------------"); | |
688 } | |
689 _list->clear(); | |
690 _active = false; | |
691 } | |
692 | |
693 #endif // COMPILER2 |