251 assert( len > 0, "must have pointer maps" );
252
253 // Scan through oopmaps. Stop when current offset is either equal or greater
254 // than the one we are looking for.
255 for( i = 0; i < len; i++) {
256 if( at(i)->offset() >= pc_offset )
257 break;
258 }
259
260 assert( i < len, "oopmap not found" );
261
262 OopMap* m = at(i);
263 assert( m->offset() == pc_offset, "oopmap not found" );
264 return m;
265 }
266
267 static void add_derived_oop(oop* base, oop* derived) {
268 #if !defined(TIERED) && !defined(INCLUDE_JVMCI)
269 COMPILER1_PRESENT(ShouldNotReachHere();)
270 #endif // !defined(TIERED) && !defined(INCLUDE_JVMCI)
271 #if defined(COMPILER2) || INCLUDE_JVMCI
272 DerivedPointerTable::add(derived, base);
273 #endif // COMPILER2 || INCLUDE_JVMCI
274 }
275
276
277 #ifndef PRODUCT
278 static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
279 // Print oopmap and regmap
280 tty->print_cr("------ ");
281 CodeBlob* cb = fr->cb();
282 const ImmutableOopMapSet* maps = cb->oop_maps();
283 const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
284 map->print();
285 if( cb->is_nmethod() ) {
286 nmethod* nm = (nmethod*)cb;
287 // native wrappers have no scope data, it is implied
288 if (nm->is_native_method()) {
289 tty->print("bci: 0 (native)");
290 } else {
291 ScopeDesc* scope = nm->scope_desc_at(fr->pc());
292 tty->print("bci: %d ",scope->bci());
293 }
444 DEBUG_ONLY(nof_callee++;)
445 }
446
447 // Check that runtime stubs save all callee-saved registers
448 #ifdef COMPILER2
449 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),
451 "must save all");
452 #endif // COMPILER2
453 }
454
455 //=============================================================================
456 // Non-Product code
457
458 #ifndef PRODUCT
459
460 bool ImmutableOopMap::has_derived_pointer() const {
461 #if !defined(TIERED) && !defined(INCLUDE_JVMCI)
462 COMPILER1_PRESENT(return false);
463 #endif // !TIERED
464 #if defined(COMPILER2) || INCLUDE_JVMCI
465 OopMapStream oms(this,OopMapValue::derived_oop_value);
466 return oms.is_done();
467 #else
468 return false;
469 #endif // COMPILER2 || INCLUDE_JVMCI
470 }
471
472 #endif //PRODUCT
473
474 // Printing code is present in product build for -XX:+PrintAssembly.
475
476 static
477 void print_register_type(OopMapValue::oop_types x, VMReg optional,
478 outputStream* st) {
479 switch( x ) {
480 case OopMapValue::oop_value:
481 st->print("Oop");
482 break;
483 case OopMapValue::narrowoop_value:
484 st->print("NarrowOop");
485 break;
486 case OopMapValue::callee_saved_value:
487 st->print("Callers_");
488 optional->print_on(st);
489 break;
709 return _new_set;
710 }
711
712 ImmutableOopMapSet* ImmutableOopMapBuilder::build() {
713 _required = heap_size();
714
715 // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
716 address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode);
717 return generate_into(buffer);
718 }
719
720 ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {
721 ResourceMark mark;
722 ImmutableOopMapBuilder builder(oopmap_set);
723 return builder.build();
724 }
725
726
727 //------------------------------DerivedPointerTable---------------------------
728
729 #if defined(COMPILER2) || INCLUDE_JVMCI
730
731 class DerivedPointerEntry : public CHeapObj<mtCompiler> {
732 private:
733 oop* _location; // Location of derived pointer (also pointing to the base)
734 intptr_t _offset; // Offset from base pointer
735 public:
736 DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; }
737 oop* location() { return _location; }
738 intptr_t offset() { return _offset; }
739 };
740
741
742 GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL;
743 bool DerivedPointerTable::_active = false;
744
745
746 void DerivedPointerTable::clear() {
747 // The first time, we create the list. Otherwise it should be
748 // empty. If not, then we have probably forgotton to call
749 // update_pointers after last GC/Scavenge.
802 assert(value_of_loc(derived_loc) - value_of_loc(&base) == offset, "sanity check");
803
804 if (TraceDerivedPointers) {
805 tty->print_cr("Updating derived pointer@" INTPTR_FORMAT
806 " - Derived: " INTPTR_FORMAT " Base: " INTPTR_FORMAT " (Offset: " INTX_FORMAT ")",
807 p2i(derived_loc), p2i((address)*derived_loc), p2i((address)base), offset);
808 }
809
810 // Delete entry
811 delete entry;
812 _list->at_put(i, NULL);
813 }
814 // Clear list, so it is ready for next traversal (this is an invariant)
815 if (TraceDerivedPointers && !_list->is_empty()) {
816 tty->print_cr("--------------------------");
817 }
818 _list->clear();
819 _active = false;
820 }
821
822 #endif // COMPILER2 || INCLUDE_JVMCI
|
251 assert( len > 0, "must have pointer maps" );
252
253 // Scan through oopmaps. Stop when current offset is either equal or greater
254 // than the one we are looking for.
255 for( i = 0; i < len; i++) {
256 if( at(i)->offset() >= pc_offset )
257 break;
258 }
259
260 assert( i < len, "oopmap not found" );
261
262 OopMap* m = at(i);
263 assert( m->offset() == pc_offset, "oopmap not found" );
264 return m;
265 }
266
267 static void add_derived_oop(oop* base, oop* derived) {
268 #if !defined(TIERED) && !defined(INCLUDE_JVMCI)
269 COMPILER1_PRESENT(ShouldNotReachHere();)
270 #endif // !defined(TIERED) && !defined(INCLUDE_JVMCI)
271 #if COMPILER2_OR_JVMCI
272 DerivedPointerTable::add(derived, base);
273 #endif // COMPILER2_OR_JVMCI
274 }
275
276
277 #ifndef PRODUCT
278 static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
279 // Print oopmap and regmap
280 tty->print_cr("------ ");
281 CodeBlob* cb = fr->cb();
282 const ImmutableOopMapSet* maps = cb->oop_maps();
283 const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
284 map->print();
285 if( cb->is_nmethod() ) {
286 nmethod* nm = (nmethod*)cb;
287 // native wrappers have no scope data, it is implied
288 if (nm->is_native_method()) {
289 tty->print("bci: 0 (native)");
290 } else {
291 ScopeDesc* scope = nm->scope_desc_at(fr->pc());
292 tty->print("bci: %d ",scope->bci());
293 }
444 DEBUG_ONLY(nof_callee++;)
445 }
446
447 // Check that runtime stubs save all callee-saved registers
448 #ifdef COMPILER2
449 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),
451 "must save all");
452 #endif // COMPILER2
453 }
454
455 //=============================================================================
456 // Non-Product code
457
458 #ifndef PRODUCT
459
460 bool ImmutableOopMap::has_derived_pointer() const {
461 #if !defined(TIERED) && !defined(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
474 // Printing code is present in product build for -XX:+PrintAssembly.
475
476 static
477 void print_register_type(OopMapValue::oop_types x, VMReg optional,
478 outputStream* st) {
479 switch( x ) {
480 case OopMapValue::oop_value:
481 st->print("Oop");
482 break;
483 case OopMapValue::narrowoop_value:
484 st->print("NarrowOop");
485 break;
486 case OopMapValue::callee_saved_value:
487 st->print("Callers_");
488 optional->print_on(st);
489 break;
709 return _new_set;
710 }
711
712 ImmutableOopMapSet* ImmutableOopMapBuilder::build() {
713 _required = heap_size();
714
715 // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
716 address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode);
717 return generate_into(buffer);
718 }
719
720 ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {
721 ResourceMark mark;
722 ImmutableOopMapBuilder builder(oopmap_set);
723 return builder.build();
724 }
725
726
727 //------------------------------DerivedPointerTable---------------------------
728
729 #if COMPILER2_OR_JVMCI
730
731 class DerivedPointerEntry : public CHeapObj<mtCompiler> {
732 private:
733 oop* _location; // Location of derived pointer (also pointing to the base)
734 intptr_t _offset; // Offset from base pointer
735 public:
736 DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; }
737 oop* location() { return _location; }
738 intptr_t offset() { return _offset; }
739 };
740
741
742 GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL;
743 bool DerivedPointerTable::_active = false;
744
745
746 void DerivedPointerTable::clear() {
747 // The first time, we create the list. Otherwise it should be
748 // empty. If not, then we have probably forgotton to call
749 // update_pointers after last GC/Scavenge.
802 assert(value_of_loc(derived_loc) - value_of_loc(&base) == offset, "sanity check");
803
804 if (TraceDerivedPointers) {
805 tty->print_cr("Updating derived pointer@" INTPTR_FORMAT
806 " - Derived: " INTPTR_FORMAT " Base: " INTPTR_FORMAT " (Offset: " INTX_FORMAT ")",
807 p2i(derived_loc), p2i((address)*derived_loc), p2i((address)base), offset);
808 }
809
810 // Delete entry
811 delete entry;
812 _list->at_put(i, NULL);
813 }
814 // Clear list, so it is ready for next traversal (this is an invariant)
815 if (TraceDerivedPointers && !_list->is_empty()) {
816 tty->print_cr("--------------------------");
817 }
818 _list->clear();
819 _active = false;
820 }
821
822 #endif // COMPILER2_OR_JVMCI
|