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 |
434 address pc = fr->pc(); |
417 address pc = fr->pc(); |
435 const ImmutableOopMap* map = cb->oop_map_for_return_address(pc); |
418 const ImmutableOopMap* map = cb->oop_map_for_return_address(pc); |
436 assert(map != NULL, "no ptr map found"); |
419 assert(map != NULL, "no ptr map found"); |
437 DEBUG_ONLY(int nof_callee = 0;) |
420 DEBUG_ONLY(int nof_callee = 0;) |
438 |
421 |
439 for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) { |
422 for (OopMapStream oms(map); !oms.is_done(); oms.next()) { |
440 OopMapValue omv = oms.current(); |
423 OopMapValue omv = oms.current(); |
441 VMReg reg = omv.content_reg(); |
424 if (omv.type() == OopMapValue::callee_saved_value) { |
442 oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map); |
425 VMReg reg = omv.content_reg(); |
443 reg_map->set_location(reg, (address) loc); |
426 oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map); |
444 DEBUG_ONLY(nof_callee++;) |
427 reg_map->set_location(reg, (address) loc); |
|
428 DEBUG_ONLY(nof_callee++;) |
|
429 } |
445 } |
430 } |
446 |
431 |
447 // Check that runtime stubs save all callee-saved registers |
432 // Check that runtime stubs save all callee-saved registers |
448 #ifdef COMPILER2 |
433 #ifdef COMPILER2 |
449 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() || |
450 (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), |
451 "must save all"); |
436 "must save all"); |
452 #endif // COMPILER2 |
437 #endif // COMPILER2 |
453 } |
438 } |
454 |
|
455 //============================================================================= |
|
456 // Non-Product code |
|
457 |
|
458 #ifndef PRODUCT |
|
459 |
|
460 bool ImmutableOopMap::has_derived_pointer() const { |
|
461 #if !defined(TIERED) && !INCLUDE_JVMCI |
|
462 COMPILER1_PRESENT(return false); |
|
463 #endif // !TIERED |
|
464 #if COMPILER2_OR_JVMCI |
|
465 OopMapStream oms(this,OopMapValue::derived_oop_value); |
|
466 return oms.is_done(); |
|
467 #else |
|
468 return false; |
|
469 #endif // COMPILER2_OR_JVMCI |
|
470 } |
|
471 |
|
472 #endif //PRODUCT |
|
473 |
439 |
474 // Printing code is present in product build for -XX:+PrintAssembly. |
440 // Printing code is present in product build for -XX:+PrintAssembly. |
475 |
441 |
476 static |
442 static |
477 void print_register_type(OopMapValue::oop_types x, VMReg optional, |
443 void print_register_type(OopMapValue::oop_types x, VMReg optional, |