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
39 #ifdef COMPILER2
40 #include "opto/optoreg.hpp"
41 #endif
42
43 // OopMapStream
44
45 OopMapStream::OopMapStream(OopMap* oop_map) {
46 if(oop_map->omv_data() == NULL) {
47 _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
48 } else {
49 _stream = new CompressedReadStream(oop_map->omv_data());
50 }
51 _mask = OopMapValue::type_mask_in_place;
52 _size = oop_map->omv_count();
53 _position = 0;
54 _valid_omv = false;
55 }
56
57
58 OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
59 if(oop_map->omv_data() == NULL) {
60 _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
61 } else {
62 _stream = new CompressedReadStream(oop_map->omv_data());
63 }
64 _mask = oop_types_mask;
65 _size = oop_map->omv_count();
66 _position = 0;
67 _valid_omv = false;
68 }
69
70
71 void OopMapStream::find_next() {
72 while(_position++ < _size) {
73 _omv.read_from(_stream);
74 if(((int)_omv.type() & _mask) > 0) {
75 _valid_omv = true;
76 return;
77 }
78 }
79 _valid_omv = false;
80 }
81
82
83 // OopMap
84
85 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
86 // slots to hold 4-byte values like ints and floats in the LP64 build.
87 OopMap::OopMap(int frame_size, int arg_count) {
88 // OopMaps are usually quite so small, so pick a small initial size
89 set_write_stream(new CompressedWriteStream(32));
90 set_omv_data(NULL);
91 set_omv_count(0);
92
93 #ifdef ASSERT
94 _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;
95 _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
96 for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
97 #endif
98 }
99
100
101 OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {
102 // This constructor does a deep copy
103 // of the source OopMap.
104 set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
105 set_omv_data(NULL);
106 set_omv_count(0);
107 set_offset(source->offset());
108
109 #ifdef ASSERT
110 _locs_length = source->_locs_length;
111 _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
112 for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
113 #endif
114
115 // We need to copy the entries too.
116 for (OopMapStream oms(source); !oms.is_done(); oms.next()) {
117 OopMapValue omv = oms.current();
118 omv.write_on(write_stream());
119 increment_count();
120 }
121 }
122
123
124 OopMap* OopMap::deep_copy() {
125 return new OopMap(_deep_copy_token, this);
126 }
127
128
129 void OopMap::copy_to(address addr) {
130 memcpy(addr,this,sizeof(OopMap));
131 memcpy(addr + sizeof(OopMap),write_stream()->buffer(),write_stream()->position());
132 OopMap* new_oop = (OopMap*)addr;
133 new_oop->set_omv_data_size(write_stream()->position());
134 new_oop->set_omv_data((unsigned char *)(addr + sizeof(OopMap)));
135 new_oop->set_write_stream(NULL);
136 }
137
138
139 int OopMap::heap_size() const {
140 int size = sizeof(OopMap);
141 int align = sizeof(void *) - 1;
142 if(write_stream() != NULL) {
143 size += write_stream()->position();
144 } else {
145 size += omv_data_size();
146 }
147 // Align to a reasonable ending point
148 size = ((size+align) & ~align);
149 return size;
150 }
151
152 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
153 // slots to hold 4-byte values like ints and floats in the LP64 build.
154 void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {
155
156 assert(reg->value() < _locs_length, "too big reg value for stack size");
157 assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );
158 debug_only( _locs_used[reg->value()] = x; )
159
160 OopMapValue o(reg, x);
161
162 if(x == OopMapValue::callee_saved_value) {
163 // This can never be a stack location, so we don't need to transform it.
164 assert(optional->is_reg(), "Trying to callee save a stack location");
165 o.set_content_reg(optional);
166 } else if(x == OopMapValue::derived_oop_value) {
205
206 // OopMapSet
207
208 OopMapSet::OopMapSet() {
209 set_om_size(MinOopMapAllocation);
210 set_om_count(0);
211 OopMap** temp = NEW_RESOURCE_ARRAY(OopMap*, om_size());
212 set_om_data(temp);
213 }
214
215
216 void OopMapSet::grow_om_data() {
217 int new_size = om_size() * 2;
218 OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size);
219 memcpy(new_data,om_data(),om_size() * sizeof(OopMap*));
220 set_om_size(new_size);
221 set_om_data(new_data);
222 }
223
224
225 void OopMapSet::copy_to(address addr) {
226 address temp = addr;
227 int align = sizeof(void *) - 1;
228 // Copy this
229 memcpy(addr,this,sizeof(OopMapSet));
230 temp += sizeof(OopMapSet);
231 temp = (address)((intptr_t)(temp + align) & ~align);
232 // Do the needed fixups to the new OopMapSet
233 OopMapSet* new_set = (OopMapSet*)addr;
234 new_set->set_om_data((OopMap**)temp);
235 // Allow enough space for the OopMap pointers
236 temp += (om_count() * sizeof(OopMap*));
237
238 for(int i=0; i < om_count(); i++) {
239 OopMap* map = at(i);
240 map->copy_to((address)temp);
241 new_set->set(i,(OopMap*)temp);
242 temp += map->heap_size();
243 }
244 // This "locks" the OopMapSet
245 new_set->set_om_size(-1);
246 }
247
248
249 void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
250 assert(om_size() != -1,"Cannot grow a fixed OopMapSet");
251
252 if(om_count() >= om_size()) {
253 grow_om_data();
254 }
255 map->set_offset(pc_offset);
256
257 #ifdef ASSERT
258 if(om_count() > 0) {
259 OopMap* last = at(om_count()-1);
260 if (last->offset() == map->offset() ) {
261 fatal("OopMap inserted twice");
262 }
263 if(last->offset() > map->offset()) {
264 tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d",
265 om_count(),last->offset(),om_count()+1,map->offset());
266 }
267 }
268 #endif // ASSERT
317 void do_oop(oop* p) {}
318 void do_oop(narrowOop* p) {}
319 };
320 static DoNothingClosure do_nothing;
321
322 static void add_derived_oop(oop* base, oop* derived) {
323 #ifndef TIERED
324 COMPILER1_PRESENT(ShouldNotReachHere();)
325 #endif // TIERED
326 #ifdef COMPILER2
327 DerivedPointerTable::add(derived, base);
328 #endif // COMPILER2
329 }
330
331
332 #ifndef PRODUCT
333 static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
334 // Print oopmap and regmap
335 tty->print_cr("------ ");
336 CodeBlob* cb = fr->cb();
337 OopMapSet* maps = cb->oop_maps();
338 OopMap* map = cb->oop_map_for_return_address(fr->pc());
339 map->print();
340 if( cb->is_nmethod() ) {
341 nmethod* nm = (nmethod*)cb;
342 // native wrappers have no scope data, it is implied
343 if (nm->is_native_method()) {
344 tty->print("bci: 0 (native)");
345 } else {
346 ScopeDesc* scope = nm->scope_desc_at(fr->pc());
347 tty->print("bci: %d ",scope->bci());
348 }
349 }
350 tty->cr();
351 fr->print_on(tty);
352 tty->print(" ");
353 cb->print_value_on(tty); tty->cr();
354 reg_map->print();
355 tty->print_cr("------ ");
356
357 }
358 #endif // PRODUCT
359
360 void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) {
361 // add derived oops to a table
362 all_do(fr, reg_map, f, add_derived_oop, &do_nothing);
363 }
364
365
366 void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
367 OopClosure* oop_fn, void derived_oop_fn(oop*, oop*),
368 OopClosure* value_fn) {
369 CodeBlob* cb = fr->cb();
370 assert(cb != NULL, "no codeblob");
371
372 NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
373
374 OopMapSet* maps = cb->oop_maps();
375 OopMap* map = cb->oop_map_for_return_address(fr->pc());
376 assert(map != NULL, "no ptr map found");
377
378 // handle derived pointers first (otherwise base pointer may be
379 // changed before derived pointer offset has been collected)
380 OopMapValue omv;
381 {
382 OopMapStream oms(map,OopMapValue::derived_oop_value);
383 if (!oms.is_done()) {
384 #ifndef TIERED
385 COMPILER1_PRESENT(ShouldNotReachHere();)
386 #endif // !TIERED
387 // Protect the operation on the derived pointers. This
388 // protects the addition of derived pointers to the shared
389 // derived pointer table in DerivedPointerTable::add().
390 MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag);
391 do {
392 omv = oms.current();
393 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
394 if ( loc != NULL ) {
395 oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
466 // Update callee-saved register info for the following frame
467 void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) {
468 ResourceMark rm;
469 CodeBlob* cb = fr->cb();
470 assert(cb != NULL, "no codeblob");
471
472 // Any reg might be saved by a safepoint handler (see generate_handler_blob).
473 assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id),
474 "already updated this map; do not 'update' it twice!" );
475 debug_only(reg_map->_update_for_id = fr->id());
476
477 // Check if caller must update oop argument
478 assert((reg_map->include_argument_oops() ||
479 !cb->caller_must_gc_arguments(reg_map->thread())),
480 "include_argument_oops should already be set");
481
482 // Scan through oopmap and find location of all callee-saved registers
483 // (we do not do update in place, since info could be overwritten)
484
485 address pc = fr->pc();
486 OopMap* map = cb->oop_map_for_return_address(pc);
487 assert(map != NULL, "no ptr map found");
488 DEBUG_ONLY(int nof_callee = 0;)
489
490 for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
491 OopMapValue omv = oms.current();
492 VMReg reg = omv.content_reg();
493 oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map);
494 reg_map->set_location(reg, (address) loc);
495 DEBUG_ONLY(nof_callee++;)
496 }
497
498 // Check that runtime stubs save all callee-saved registers
499 #ifdef COMPILER2
500 assert(cb->is_compiled_by_c1() || !cb->is_runtime_stub() ||
501 (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),
502 "must save all");
503 #endif // COMPILER2
504 }
505
506 //=============================================================================
507 // Non-Product code
508
509 #ifndef PRODUCT
510
511 bool OopMap::has_derived_pointer() const {
512 #ifndef TIERED
513 COMPILER1_PRESENT(return false);
514 #endif // !TIERED
515 #ifdef COMPILER2
516 OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
517 return oms.is_done();
518 #else
519 return false;
520 #endif // COMPILER2
521 }
522
523 #endif //PRODUCT
524
525 // Printing code is present in product build for -XX:+PrintAssembly.
526
527 static
528 void print_register_type(OopMapValue::oop_types x, VMReg optional,
529 outputStream* st) {
530 switch( x ) {
531 case OopMapValue::oop_value:
533 break;
534 case OopMapValue::value_value:
535 st->print("Value");
536 break;
537 case OopMapValue::narrowoop_value:
538 st->print("NarrowOop");
539 break;
540 case OopMapValue::callee_saved_value:
541 st->print("Callers_");
542 optional->print_on(st);
543 break;
544 case OopMapValue::derived_oop_value:
545 st->print("Derived_oop_");
546 optional->print_on(st);
547 break;
548 default:
549 ShouldNotReachHere();
550 }
551 }
552
553
554 void OopMapValue::print_on(outputStream* st) const {
555 reg()->print_on(st);
556 st->print("=");
557 print_register_type(type(),content_reg(),st);
558 st->print(" ");
559 }
560
561
562 void OopMap::print_on(outputStream* st) const {
563 OopMapValue omv;
564 st->print("OopMap{");
565 for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {
566 omv = oms.current();
567 omv.print_on(st);
568 }
569 st->print("off=%d}", (int) offset());
570 }
571
572
573 void OopMapSet::print_on(outputStream* st) const {
574 int i, len = om_count();
575
576 st->print_cr("OopMapSet contains %d OopMaps\n",len);
577
578 for( i = 0; i < len; i++) {
579 OopMap* m = at(i);
580 st->print_cr("#%d ",i);
581 m->print_on(st);
582 st->cr();
583 }
584 }
585
586
587
588 //------------------------------DerivedPointerTable---------------------------
589
590 #ifdef COMPILER2
591
592 class DerivedPointerEntry : public CHeapObj<mtCompiler> {
593 private:
594 oop* _location; // Location of derived pointer (also pointing to the base)
595 intptr_t _offset; // Offset from base pointer
596 public:
597 DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; }
598 oop* location() { return _location; }
599 intptr_t offset() { return _offset; }
600 };
601
602
603 GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL;
604 bool DerivedPointerTable::_active = false;
605
|
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
39 #ifdef COMPILER2
40 #include "opto/optoreg.hpp"
41 #endif
42
43 // OopMapStream
44
45 OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
46 _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
47 _mask = oop_types_mask;
48 _size = oop_map->omv_count();
49 _position = 0;
50 _valid_omv = false;
51 }
52
53 OopMapStream::OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask) {
54 _stream = new CompressedReadStream(oop_map->data_addr());
55 _mask = oop_types_mask;
56 _size = oop_map->count();
57 _position = 0;
58 _valid_omv = false;
59 }
60
61
62 void OopMapStream::find_next() {
63 while(_position++ < _size) {
64 _omv.read_from(_stream);
65 if(((int)_omv.type() & _mask) > 0) {
66 _valid_omv = true;
67 return;
68 }
69 }
70 _valid_omv = false;
71 }
72
73
74 // OopMap
75
76 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
77 // slots to hold 4-byte values like ints and floats in the LP64 build.
78 OopMap::OopMap(int frame_size, int arg_count) {
79 // OopMaps are usually quite so small, so pick a small initial size
80 set_write_stream(new CompressedWriteStream(32));
81 set_omv_count(0);
82
83 #ifdef ASSERT
84 _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;
85 _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
86 for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
87 #endif
88 }
89
90
91 OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {
92 // This constructor does a deep copy
93 // of the source OopMap.
94 set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
95 set_omv_count(0);
96 set_offset(source->offset());
97
98 #ifdef ASSERT
99 _locs_length = source->_locs_length;
100 _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
101 for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
102 #endif
103
104 // We need to copy the entries too.
105 for (OopMapStream oms(source); !oms.is_done(); oms.next()) {
106 OopMapValue omv = oms.current();
107 omv.write_on(write_stream());
108 increment_count();
109 }
110 }
111
112
113 OopMap* OopMap::deep_copy() {
114 return new OopMap(_deep_copy_token, this);
115 }
116
117 void OopMap::copy_data_to(address addr) const {
118 memcpy(addr, write_stream()->buffer(), write_stream()->position());
119 }
120
121 int OopMap::heap_size() const {
122 int size = sizeof(OopMap);
123 int align = sizeof(void *) - 1;
124 size += write_stream()->position();
125 // Align to a reasonable ending point
126 size = ((size+align) & ~align);
127 return size;
128 }
129
130 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
131 // slots to hold 4-byte values like ints and floats in the LP64 build.
132 void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {
133
134 assert(reg->value() < _locs_length, "too big reg value for stack size");
135 assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );
136 debug_only( _locs_used[reg->value()] = x; )
137
138 OopMapValue o(reg, x);
139
140 if(x == OopMapValue::callee_saved_value) {
141 // This can never be a stack location, so we don't need to transform it.
142 assert(optional->is_reg(), "Trying to callee save a stack location");
143 o.set_content_reg(optional);
144 } else if(x == OopMapValue::derived_oop_value) {
183
184 // OopMapSet
185
186 OopMapSet::OopMapSet() {
187 set_om_size(MinOopMapAllocation);
188 set_om_count(0);
189 OopMap** temp = NEW_RESOURCE_ARRAY(OopMap*, om_size());
190 set_om_data(temp);
191 }
192
193
194 void OopMapSet::grow_om_data() {
195 int new_size = om_size() * 2;
196 OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size);
197 memcpy(new_data,om_data(),om_size() * sizeof(OopMap*));
198 set_om_size(new_size);
199 set_om_data(new_data);
200 }
201
202
203 void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
204 assert(om_size() != -1,"Cannot grow a fixed OopMapSet");
205
206 if(om_count() >= om_size()) {
207 grow_om_data();
208 }
209 map->set_offset(pc_offset);
210
211 #ifdef ASSERT
212 if(om_count() > 0) {
213 OopMap* last = at(om_count()-1);
214 if (last->offset() == map->offset() ) {
215 fatal("OopMap inserted twice");
216 }
217 if(last->offset() > map->offset()) {
218 tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d",
219 om_count(),last->offset(),om_count()+1,map->offset());
220 }
221 }
222 #endif // ASSERT
271 void do_oop(oop* p) {}
272 void do_oop(narrowOop* p) {}
273 };
274 static DoNothingClosure do_nothing;
275
276 static void add_derived_oop(oop* base, oop* derived) {
277 #ifndef TIERED
278 COMPILER1_PRESENT(ShouldNotReachHere();)
279 #endif // TIERED
280 #ifdef COMPILER2
281 DerivedPointerTable::add(derived, base);
282 #endif // COMPILER2
283 }
284
285
286 #ifndef PRODUCT
287 static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
288 // Print oopmap and regmap
289 tty->print_cr("------ ");
290 CodeBlob* cb = fr->cb();
291 ImmutableOopMapSet* maps = cb->oop_maps();
292 const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
293 map->print();
294 if( cb->is_nmethod() ) {
295 nmethod* nm = (nmethod*)cb;
296 // native wrappers have no scope data, it is implied
297 if (nm->is_native_method()) {
298 tty->print("bci: 0 (native)");
299 } else {
300 ScopeDesc* scope = nm->scope_desc_at(fr->pc());
301 tty->print("bci: %d ",scope->bci());
302 }
303 }
304 tty->cr();
305 fr->print_on(tty);
306 tty->print(" ");
307 cb->print_value_on(tty); tty->cr();
308 reg_map->print();
309 tty->print_cr("------ ");
310
311 }
312 #endif // PRODUCT
313
314 void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) {
315 // add derived oops to a table
316 all_do(fr, reg_map, f, add_derived_oop, &do_nothing);
317 }
318
319
320 void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
321 OopClosure* oop_fn, void derived_oop_fn(oop*, oop*),
322 OopClosure* value_fn) {
323 CodeBlob* cb = fr->cb();
324 assert(cb != NULL, "no codeblob");
325
326 NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
327
328 ImmutableOopMapSet* maps = cb->oop_maps();
329 const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
330 assert(map != NULL, "no ptr map found");
331
332 // handle derived pointers first (otherwise base pointer may be
333 // changed before derived pointer offset has been collected)
334 OopMapValue omv;
335 {
336 OopMapStream oms(map,OopMapValue::derived_oop_value);
337 if (!oms.is_done()) {
338 #ifndef TIERED
339 COMPILER1_PRESENT(ShouldNotReachHere();)
340 #endif // !TIERED
341 // Protect the operation on the derived pointers. This
342 // protects the addition of derived pointers to the shared
343 // derived pointer table in DerivedPointerTable::add().
344 MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag);
345 do {
346 omv = oms.current();
347 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
348 if ( loc != NULL ) {
349 oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
420 // Update callee-saved register info for the following frame
421 void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) {
422 ResourceMark rm;
423 CodeBlob* cb = fr->cb();
424 assert(cb != NULL, "no codeblob");
425
426 // Any reg might be saved by a safepoint handler (see generate_handler_blob).
427 assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id),
428 "already updated this map; do not 'update' it twice!" );
429 debug_only(reg_map->_update_for_id = fr->id());
430
431 // Check if caller must update oop argument
432 assert((reg_map->include_argument_oops() ||
433 !cb->caller_must_gc_arguments(reg_map->thread())),
434 "include_argument_oops should already be set");
435
436 // Scan through oopmap and find location of all callee-saved registers
437 // (we do not do update in place, since info could be overwritten)
438
439 address pc = fr->pc();
440 const ImmutableOopMap* map = cb->oop_map_for_return_address(pc);
441 assert(map != NULL, "no ptr map found");
442 DEBUG_ONLY(int nof_callee = 0;)
443
444 for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
445 OopMapValue omv = oms.current();
446 VMReg reg = omv.content_reg();
447 oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map);
448 reg_map->set_location(reg, (address) loc);
449 DEBUG_ONLY(nof_callee++;)
450 }
451
452 // Check that runtime stubs save all callee-saved registers
453 #ifdef COMPILER2
454 assert(cb->is_compiled_by_c1() || !cb->is_runtime_stub() ||
455 (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),
456 "must save all");
457 #endif // COMPILER2
458 }
459
460 //=============================================================================
461 // Non-Product code
462
463 #ifndef PRODUCT
464
465 bool ImmutableOopMap::has_derived_pointer() const {
466 #ifndef TIERED
467 COMPILER1_PRESENT(return false);
468 #endif // !TIERED
469 #ifdef COMPILER2
470 OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
471 return oms.is_done();
472 #else
473 return false;
474 #endif // COMPILER2
475 }
476
477 #endif //PRODUCT
478
479 // Printing code is present in product build for -XX:+PrintAssembly.
480
481 static
482 void print_register_type(OopMapValue::oop_types x, VMReg optional,
483 outputStream* st) {
484 switch( x ) {
485 case OopMapValue::oop_value:
487 break;
488 case OopMapValue::value_value:
489 st->print("Value");
490 break;
491 case OopMapValue::narrowoop_value:
492 st->print("NarrowOop");
493 break;
494 case OopMapValue::callee_saved_value:
495 st->print("Callers_");
496 optional->print_on(st);
497 break;
498 case OopMapValue::derived_oop_value:
499 st->print("Derived_oop_");
500 optional->print_on(st);
501 break;
502 default:
503 ShouldNotReachHere();
504 }
505 }
506
507 void OopMapValue::print_on(outputStream* st) const {
508 reg()->print_on(st);
509 st->print("=");
510 print_register_type(type(),content_reg(),st);
511 st->print(" ");
512 }
513
514 void ImmutableOopMap::print_on(outputStream* st) const {
515 OopMapValue omv;
516 st->print("ImmutableOopMap{");
517 for(OopMapStream oms(this); !oms.is_done(); oms.next()) {
518 omv = oms.current();
519 omv.print_on(st);
520 }
521 st->print("}");
522 }
523
524 void OopMap::print_on(outputStream* st) const {
525 OopMapValue omv;
526 st->print("OopMap{");
527 for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {
528 omv = oms.current();
529 omv.print_on(st);
530 }
531 st->print("off=%d}", (int) offset());
532 }
533
534 void ImmutableOopMapSet::print_on(outputStream* st) const {
535 const ImmutableOopMap* last = NULL;
536 for (int i = 0; i < _count; ++i) {
537 const ImmutableOopMapPair* pair = pair_at(i);
538 const ImmutableOopMap* map = pair->get_from(this);
539 if (map != last) {
540 st->cr();
541 map->print_on(st);
542 st->print("pc offsets: ");
543 }
544 last = map;
545 st->print("%d ", pair->pc_offset());
546 }
547 }
548
549 void OopMapSet::print_on(outputStream* st) const {
550 int i, len = om_count();
551
552 st->print_cr("OopMapSet contains %d OopMaps\n",len);
553
554 for( i = 0; i < len; i++) {
555 OopMap* m = at(i);
556 st->print_cr("#%d ",i);
557 m->print_on(st);
558 st->cr();
559 }
560 }
561
562 bool OopMap::equals(const OopMap* other) const {
563 if (other->_omv_count != _omv_count) {
564 return false;
565 }
566 if (other->write_stream()->position() != write_stream()->position()) {
567 return false;
568 }
569 if (memcmp(other->write_stream()->buffer(), write_stream()->buffer(), write_stream()->position()) != 0) {
570 return false;
571 }
572 return true;
573 }
574
575 const ImmutableOopMap* ImmutableOopMapSet::find_map_at_offset(int pc_offset) const {
576 ImmutableOopMapPair* pairs = get_pairs();
577 ImmutableOopMapPair* last = NULL;
578
579 for (int i = 0; i < _count; ++i) {
580 if (pairs[i].pc_offset() >= pc_offset) {
581 last = &pairs[i];
582 break;
583 }
584 }
585
586 assert(last->pc_offset() == pc_offset, "oopmap not found");
587 return last->get_from(this);
588 }
589
590 const ImmutableOopMap* ImmutableOopMapPair::get_from(const ImmutableOopMapSet* set) const {
591 return set->oopmap_at_offset(_oopmap_offset);
592 }
593
594 ImmutableOopMap::ImmutableOopMap(const OopMap* oopmap) : _count(oopmap->count()) {
595 address addr = data_addr();
596 oopmap->copy_data_to(addr);
597 }
598
599 class ImmutableOopMapBuilder {
600 public:
601 /* Used for bookkeeping when building ImmutableOopMaps */
602 class Mapping : public ResourceObj {
603 public:
604 enum kind_t { OOPMAP_UNKNOWN = 0, OOPMAP_NEW = 1, OOPMAP_EMPTY = 2, OOPMAP_DUPLICATE = 3 };
605
606 Mapping() : _kind(OOPMAP_UNKNOWN), _offset(-1), _size(-1), _map(NULL) {}
607
608 void set(kind_t kind, int offset, int size, const OopMap* map = 0, const OopMap* other = 0) {
609 _kind = kind;
610 _offset = offset;
611 _size = size;
612 _map = map;
613 _other = other;
614 }
615
616 kind_t _kind;
617 int _offset;
618 int _size;
619 const OopMap* _map;
620 const OopMap* _other;
621 };
622
623 ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _new_set(NULL), _empty(NULL), _last(NULL), _empty_offset(-1), _last_offset(-1), _offset(0) {
624 _mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size());
625 }
626
627 int heap_size();
628 ImmutableOopMapSet* build();
629 private:
630 bool is_empty(const OopMap* map) const {
631 return map->count() == 0;
632 }
633
634 bool is_last_duplicate(const OopMap* map) {
635 if (_last != NULL && _last->count() > 0 && _last->equals(map)) {
636 return true;
637 }
638 return false;
639 }
640
641 void verify(address buffer, int size);
642
643 bool has_empty() const {
644 return _empty_offset != -1;
645 }
646
647 int size_for(const OopMap* map) const;
648 void fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset);
649 int fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset);
650 void fill(ImmutableOopMapSet* set, int size);
651
652 const OopMapSet* _set;
653 const OopMap* _empty;
654 const OopMap* _last;
655 int _empty_offset;
656 int _last_offset;
657 int _offset;
658 Mapping* _mapping;
659 ImmutableOopMapSet* _new_set;
660 };
661
662 int ImmutableOopMapBuilder::size_for(const OopMap* map) const {
663 return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8);
664 }
665
666 int ImmutableOopMapBuilder::heap_size() {
667 int base = sizeof(ImmutableOopMapSet);
668 base = align_size_up(base, 8);
669
670 // all of ours pc / offset pairs
671 int pairs = _set->size() * sizeof(ImmutableOopMapPair);
672 pairs = align_size_up(pairs, 8);
673
674 for (int i = 0; i < _set->size(); ++i) {
675 int size = 0;
676 OopMap* map = _set->at(i);
677
678 if (is_empty(map)) {
679 /* only keep a single empty map in the set */
680 if (has_empty()) {
681 _mapping[i].set(Mapping::OOPMAP_EMPTY, _empty_offset, 0, map, _empty);
682 } else {
683 _empty_offset = _offset;
684 _empty = map;
685 size = size_for(map);
686 _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
687 }
688 } else if (is_last_duplicate(map)) {
689 /* if this entry is identical to the previous one, just point it there */
690 _mapping[i].set(Mapping::OOPMAP_DUPLICATE, _last_offset, 0, map, _last);
691 } else {
692 /* not empty, not an identical copy of the previous entry */
693 size = size_for(map);
694 _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
695 _last_offset = _offset;
696 _last = map;
697 }
698
699 assert(_mapping[i]._map == map, "check");
700 _offset += size;
701 }
702
703 int total = base + pairs + _offset;
704 DEBUG_ONLY(total += 8);
705 return total;
706 }
707
708 void ImmutableOopMapBuilder::fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset) {
709 new ((address) pair) ImmutableOopMapPair(map->offset(), offset);
710 }
711
712 int ImmutableOopMapBuilder::fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset) {
713 fill_pair(pair, map, offset);
714 address addr = (address) pair->get_from(_new_set); // location of the ImmutableOopMap
715
716 new (addr) ImmutableOopMap(map);
717 return align_size_up(sizeof(ImmutableOopMap) + map->data_size(), 8);
718 }
719
720 void ImmutableOopMapBuilder::fill(ImmutableOopMapSet* set, int sz) {
721 ImmutableOopMapPair* pairs = set->get_pairs();
722
723 for (int i = 0; i < set->count(); ++i) {
724 const OopMap* map = _mapping[i]._map;
725 ImmutableOopMapPair* pair = NULL;
726 int size = 0;
727
728 if (_mapping[i]._kind == Mapping::OOPMAP_NEW) {
729 size = fill_map(&pairs[i], map, _mapping[i]._offset);
730 } else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) {
731 fill_pair(&pairs[i], map, _mapping[i]._offset);
732 }
733
734 const ImmutableOopMap* nv = set->find_map_at_offset(map->offset());
735 assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity");
736 }
737 }
738
739 void ImmutableOopMapBuilder::verify(address buffer, int size) {
740 for (int i = 0; i < 8; ++i) {
741 assert(buffer[size - 8 + i] == (unsigned char) 0xff, "overwritten memory check");
742 }
743 }
744
745 ImmutableOopMapSet* ImmutableOopMapBuilder::build() {
746 int required = heap_size();
747
748 // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
749 address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, required, mtCode);
750 DEBUG_ONLY(memset(&buffer[required-8], 0xff, 8));
751
752 _new_set = new (buffer) ImmutableOopMapSet(_set, required);
753 fill(_new_set, required);
754
755 DEBUG_ONLY(verify(buffer, required));
756
757 return _new_set;
758 }
759
760 ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {
761 ImmutableOopMapBuilder builder(oopmap_set);
762 return builder.build();
763 }
764
765
766 //------------------------------DerivedPointerTable---------------------------
767
768 #ifdef COMPILER2
769
770 class DerivedPointerEntry : public CHeapObj<mtCompiler> {
771 private:
772 oop* _location; // Location of derived pointer (also pointing to the base)
773 intptr_t _offset; // Offset from base pointer
774 public:
775 DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; }
776 oop* location() { return _location; }
777 intptr_t offset() { return _offset; }
778 };
779
780
781 GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL;
782 bool DerivedPointerTable::_active = false;
783
|