46 #include "opto/optoreg.hpp" |
46 #include "opto/optoreg.hpp" |
47 #endif |
47 #endif |
48 |
48 |
49 // OopMapStream |
49 // OopMapStream |
50 |
50 |
51 OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) { |
51 OopMapStream::OopMapStream(OopMap* oop_map) { |
52 _stream = new CompressedReadStream(oop_map->write_stream()->buffer()); |
52 _stream = new CompressedReadStream(oop_map->write_stream()->buffer()); |
53 _mask = oop_types_mask; |
|
54 _size = oop_map->omv_count(); |
53 _size = oop_map->omv_count(); |
55 _position = 0; |
54 _position = 0; |
56 _valid_omv = false; |
55 _valid_omv = false; |
57 } |
56 } |
58 |
57 |
59 OopMapStream::OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask) { |
58 OopMapStream::OopMapStream(const ImmutableOopMap* oop_map) { |
60 _stream = new CompressedReadStream(oop_map->data_addr()); |
59 _stream = new CompressedReadStream(oop_map->data_addr()); |
61 _mask = oop_types_mask; |
|
62 _size = oop_map->count(); |
60 _size = oop_map->count(); |
63 _position = 0; |
61 _position = 0; |
64 _valid_omv = false; |
62 _valid_omv = false; |
65 } |
63 } |
66 |
64 |
67 void OopMapStream::find_next() { |
65 void OopMapStream::find_next() { |
68 while(_position++ < _size) { |
66 if (_position++ < _size) { |
69 _omv.read_from(_stream); |
67 _omv.read_from(_stream); |
70 if(((int)_omv.type() & _mask) > 0) { |
68 _valid_omv = true; |
71 _valid_omv = true; |
69 return; |
72 return; |
|
73 } |
|
74 } |
70 } |
75 _valid_omv = false; |
71 _valid_omv = false; |
76 } |
72 } |
77 |
73 |
78 |
74 |
138 |
134 |
139 assert(reg->value() < _locs_length, "too big reg value for stack size"); |
135 assert(reg->value() < _locs_length, "too big reg value for stack size"); |
140 assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" ); |
136 assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" ); |
141 debug_only( _locs_used[reg->value()] = x; ) |
137 debug_only( _locs_used[reg->value()] = x; ) |
142 |
138 |
143 OopMapValue o(reg, x); |
139 OopMapValue o(reg, x, optional); |
144 |
|
145 if(x == OopMapValue::callee_saved_value) { |
|
146 // This can never be a stack location, so we don't need to transform it. |
|
147 assert(optional->is_reg(), "Trying to callee save a stack location"); |
|
148 o.set_content_reg(optional); |
|
149 } else if(x == OopMapValue::derived_oop_value) { |
|
150 o.set_content_reg(optional); |
|
151 } |
|
152 |
|
153 o.write_on(write_stream()); |
140 o.write_on(write_stream()); |
154 increment_count(); |
141 increment_count(); |
155 } |
142 } |
156 |
143 |
157 |
144 |
158 void OopMap::set_oop(VMReg reg) { |
145 void OopMap::set_oop(VMReg reg) { |
159 set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad()); |
146 set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad()); |
160 } |
|
161 |
|
162 |
|
163 void OopMap::set_value(VMReg reg) { |
|
164 // At this time, we don't need value entries in our OopMap. |
|
165 } |
147 } |
166 |
148 |
167 |
149 |
168 void OopMap::set_narrowoop(VMReg reg) { |
150 void OopMap::set_narrowoop(VMReg reg) { |
169 set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad()); |
151 set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad()); |
326 |
308 |
327 // handle derived pointers first (otherwise base pointer may be |
309 // handle derived pointers first (otherwise base pointer may be |
328 // changed before derived pointer offset has been collected) |
310 // changed before derived pointer offset has been collected) |
329 OopMapValue omv; |
311 OopMapValue omv; |
330 { |
312 { |
331 OopMapStream oms(map,OopMapValue::derived_oop_value); |
313 OopMapStream oms(map); |
332 if (!oms.is_done()) { |
314 if (!oms.is_done()) { |
333 #ifndef TIERED |
315 #ifndef TIERED |
334 COMPILER1_PRESENT(ShouldNotReachHere();) |
316 COMPILER1_PRESENT(ShouldNotReachHere();) |
335 #if INCLUDE_JVMCI |
317 #if INCLUDE_JVMCI |
336 if (UseJVMCICompiler) { |
318 if (UseJVMCICompiler) { |
338 } |
320 } |
339 #endif |
321 #endif |
340 #endif // !TIERED |
322 #endif // !TIERED |
341 do { |
323 do { |
342 omv = oms.current(); |
324 omv = oms.current(); |
343 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); |
325 if (omv.type() == OopMapValue::derived_oop_value) { |
344 guarantee(loc != NULL, "missing saved register"); |
326 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); |
345 oop *derived_loc = loc; |
327 guarantee(loc != NULL, "missing saved register"); |
346 oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); |
328 oop *derived_loc = loc; |
347 // Ignore NULL oops and decoded NULL narrow oops which |
329 oop *base_loc = fr->oopmapreg_to_location(omv.content_reg(), reg_map); |
348 // equal to CompressedOops::base() when a narrow oop |
330 // Ignore NULL oops and decoded NULL narrow oops which |
349 // implicit null check is used in compiled code. |
331 // equal to CompressedOops::base() when a narrow oop |
350 // The narrow_oop_base could be NULL or be the address |
332 // implicit null check is used in compiled code. |
351 // of the page below heap depending on compressed oops mode. |
333 // The narrow_oop_base could be NULL or be the address |
352 if (base_loc != NULL && *base_loc != NULL && !CompressedOops::is_base(*base_loc)) { |
334 // of the page below heap depending on compressed oops mode. |
353 derived_oop_fn(base_loc, derived_loc); |
335 if (base_loc != NULL && *base_loc != NULL && !CompressedOops::is_base(*base_loc)) { |
|
336 derived_oop_fn(base_loc, derived_loc); |
|
337 } |
354 } |
338 } |
355 oms.next(); |
339 oms.next(); |
356 } while (!oms.is_done()); |
340 } while (!oms.is_done()); |
357 } |
341 } |
358 } |
342 } |
359 |
343 |
360 // We want coop and oop oop_types |
|
361 int mask = OopMapValue::oop_value | OopMapValue::narrowoop_value; |
|
362 { |
344 { |
363 for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) { |
345 // We want coop and oop oop_types |
|
346 for (OopMapStream oms(map); !oms.is_done(); oms.next()) { |
364 omv = oms.current(); |
347 omv = oms.current(); |
365 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); |
348 oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map); |
366 // It should be an error if no location can be found for a |
349 // It should be an error if no location can be found for a |
367 // register mentioned as contained an oop of some kind. Maybe |
350 // register mentioned as contained an oop of some kind. Maybe |
368 // this was allowed previously because value_value items might |
351 // this was allowed previously because value_value items might |
377 // The narrow_oop_base could be NULL or be the address |
360 // The narrow_oop_base could be NULL or be the address |
378 // of the page below heap depending on compressed oops mode. |
361 // of the page below heap depending on compressed oops mode. |
379 continue; |
362 continue; |
380 } |
363 } |
381 #ifdef ASSERT |
364 #ifdef ASSERT |
382 // We can not verify the oop here if we are using ZGC, the oop |
365 if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || |
383 // will be bad in case we had a safepoint between a load and a |
366 !Universe::heap()->is_in_or_null(*loc)) { |
384 // load barrier. |
|
385 if (!UseZGC && |
|
386 ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || |
|
387 !Universe::heap()->is_in_or_null(*loc))) { |
|
388 tty->print_cr("# Found non oop pointer. Dumping state at failure"); |
367 tty->print_cr("# Found non oop pointer. Dumping state at failure"); |
389 // try to dump out some helpful debugging information |
368 // try to dump out some helpful debugging information |
390 trace_codeblob_maps(fr, reg_map); |
369 trace_codeblob_maps(fr, reg_map); |
391 omv.print(); |
370 omv.print(); |
392 tty->print_cr("register r"); |
371 tty->print_cr("register r"); |
438 address pc = fr->pc(); |
417 address pc = fr->pc(); |
439 const ImmutableOopMap* map = cb->oop_map_for_return_address(pc); |
418 const ImmutableOopMap* map = cb->oop_map_for_return_address(pc); |
440 assert(map != NULL, "no ptr map found"); |
419 assert(map != NULL, "no ptr map found"); |
441 DEBUG_ONLY(int nof_callee = 0;) |
420 DEBUG_ONLY(int nof_callee = 0;) |
442 |
421 |
443 for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { |
422 for (OopMapStream oms(map); !oms.is_done(); oms.next()) { |
444 OopMapValue omv = oms.current(); |
423 OopMapValue omv = oms.current(); |
445 VMReg reg = omv.content_reg(); |
424 if (omv.type() == OopMapValue::callee_saved_value) { |
446 oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map); |
425 VMReg reg = omv.content_reg(); |
447 reg_map->set_location(reg, (address) loc); |
426 oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map); |
448 DEBUG_ONLY(nof_callee++;) |
427 reg_map->set_location(reg, (address) loc); |
|
428 DEBUG_ONLY(nof_callee++;) |
|
429 } |
449 } |
430 } |
450 |
431 |
451 // Check that runtime stubs save all callee-saved registers |
432 // Check that runtime stubs save all callee-saved registers |
452 #ifdef COMPILER2 |
433 #ifdef COMPILER2 |
453 assert(cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() || |
434 assert(cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() || |
454 (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT), |
435 (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT), |
455 "must save all"); |
436 "must save all"); |
456 #endif // COMPILER2 |
437 #endif // COMPILER2 |
457 } |
438 } |
458 |
|
459 //============================================================================= |
|
460 // Non-Product code |
|
461 |
|
462 #ifndef PRODUCT |
|
463 |
|
464 bool ImmutableOopMap::has_derived_pointer() const { |
|
465 #if !defined(TIERED) && !INCLUDE_JVMCI |
|
466 COMPILER1_PRESENT(return false); |
|
467 #endif // !TIERED |
|
468 #if COMPILER2_OR_JVMCI |
|
469 OopMapStream oms(this,OopMapValue::derived_oop_value); |
|
470 return oms.is_done(); |
|
471 #else |
|
472 return false; |
|
473 #endif // COMPILER2_OR_JVMCI |
|
474 } |
|
475 |
|
476 #endif //PRODUCT |
|
477 |
439 |
478 // Printing code is present in product build for -XX:+PrintAssembly. |
440 // Printing code is present in product build for -XX:+PrintAssembly. |
479 |
441 |
480 static |
442 static |
481 void print_register_type(OopMapValue::oop_types x, VMReg optional, |
443 void print_register_type(OopMapValue::oop_types x, VMReg optional, |
734 |
696 |
735 ImmutableOopMapSet* ImmutableOopMapBuilder::build() { |
697 ImmutableOopMapSet* ImmutableOopMapBuilder::build() { |
736 _required = heap_size(); |
698 _required = heap_size(); |
737 |
699 |
738 // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps |
700 // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps |
739 address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode); |
701 address buffer = NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode); |
740 return generate_into(buffer); |
702 return generate_into(buffer); |
741 } |
703 } |
742 |
704 |
743 ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) { |
705 ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) { |
744 ResourceMark mark; |
706 ResourceMark mark; |