--- old/src/hotspot/share/oops/valueKlass.cpp 2017-10-31 09:39:50.428981269 -0400 +++ new/src/hotspot/share/oops/valueKlass.cpp 2017-10-31 09:39:50.196980118 -0400 @@ -27,6 +27,7 @@ #include "interpreter/interpreter.hpp" #include "logging/log.hpp" #include "memory/metadataFactory.hpp" +#include "oops/instanceKlass.hpp" #include "oops/oop.inline.hpp" #include "oops/fieldStreams.hpp" #include "oops/method.hpp" @@ -35,6 +36,9 @@ #include "oops/valueArrayKlass.hpp" #include "runtime/signature.hpp" #include "utilities/copy.hpp" +#if INCLUDE_ALL_GCS +#include "gc/g1/g1SATBCardTableModRefBS.hpp" +#endif // INCLUDE_ALL_GCS int ValueKlass::first_field_offset() const { #ifdef ASSERT @@ -226,32 +230,79 @@ * */ void ValueKlass::value_store(void* src, void* dst, size_t raw_byte_size, bool dst_heap, bool dst_uninitialized) { - if (contains_oops() && dst_heap) { - // src/dst aren't oops, need offset to adjust oop map offset - const address dst_oop_addr = ((address) dst) - first_field_offset(); - - // Pre-barriers... - OopMapBlock* map = start_of_nonstatic_oop_maps(); - OopMapBlock* const end = map + nonstatic_oop_map_count(); - while (map != end) { - // Shame we can't just use the existing oop iterator...src/dst aren't oop - address doop_address = dst_oop_addr + map->offset(); - if (UseCompressedOops) { - oopDesc::bs()->write_ref_array_pre((narrowOop*) doop_address, map->count(), dst_uninitialized); - } else { - oopDesc::bs()->write_ref_array_pre((oop*) doop_address, map->count(), dst_uninitialized); + if (contains_oops()) { + if (dst_heap) { + // src/dst aren't oops, need offset to adjust oop map offset + const address dst_oop_addr = ((address) dst) - first_field_offset(); + + // Pre-barriers... + OopMapBlock* map = start_of_nonstatic_oop_maps(); + OopMapBlock* const end = map + nonstatic_oop_map_count(); + while (map != end) { + // Shame we can't just use the existing oop iterator...src/dst aren't oop + address doop_address = dst_oop_addr + map->offset(); + if (UseCompressedOops) { + oopDesc::bs()->write_ref_array_pre((narrowOop*) doop_address, map->count(), dst_uninitialized); + } else { + oopDesc::bs()->write_ref_array_pre((oop*) doop_address, map->count(), dst_uninitialized); + } + map++; } - map++; - } - raw_field_copy(src, dst, raw_byte_size); + raw_field_copy(src, dst, raw_byte_size); - // Post-barriers... - map = start_of_nonstatic_oop_maps(); - while (map != end) { - address doop_address = dst_oop_addr + map->offset(); - oopDesc::bs()->write_ref_array((HeapWord*) doop_address, map->count()); - map++; + // Post-barriers... + map = start_of_nonstatic_oop_maps(); + while (map != end) { + address doop_address = dst_oop_addr + map->offset(); + oopDesc::bs()->write_ref_array((HeapWord*) doop_address, map->count()); + map++; + } + } else { // Buffered value case + if (UseG1GC) { + OopMapBlock* map = start_of_nonstatic_oop_maps(); + OopMapBlock* const end_map = map + nonstatic_oop_map_count(); + + if (!UseCompressedOops) { + for (; map < end_map; map++) { + oop* p = (oop*) (((char*)(oopDesc*)src) + map->offset() - first_field_offset()); + oop* q = (oop*) (((char*)(oopDesc*)dst) + map->offset() - first_field_offset()); + oop* const end = p + map->count(); + for (; p < end; ++p) { + assert(oopDesc::is_oop_or_null(*p), "Sanity check"); + if (*p != NULL) { + G1SATBCardTableModRefBS::enqueue(*p); + } + assert(oopDesc::is_oop_or_null(*q), "Sanity check"); + if (*q != NULL && *q != *p) { + G1SATBCardTableModRefBS::enqueue(*q); + } + } + } + } else { + for (; map < end_map; map++) { + narrowOop* p = (narrowOop*) (((char*)(oopDesc*)src) + map->offset() - first_field_offset()); + narrowOop* q = (narrowOop*) (((char*)(oopDesc*)dst) + map->offset() - first_field_offset()); + narrowOop* const end = p + map->count(); + for (; p < end; ++p, ++q) { + oop o = oopDesc::decode_heap_oop(*p); + assert(Universe::heap()->is_in_reserved_or_null(o), "Sanity check"); + assert(oopDesc::is_oop_or_null(o), "Sanity check"); + if (o != NULL) { + G1SATBCardTableModRefBS::enqueue(o); + } + oop o2 = oopDesc::decode_heap_oop(*q); + assert(Universe::heap()->is_in_reserved_or_null(o2), "Sanity check"); + assert(oopDesc::is_oop_or_null(o2), "Sanity check"); + if (o2 != NULL && o2 != o) { + G1SATBCardTableModRefBS::enqueue(o2); + } + + } + } + } + } + raw_field_copy(src, dst, raw_byte_size); } } else { // Primitive-only case... raw_field_copy(src, dst, raw_byte_size); @@ -602,3 +653,37 @@ #endif return NULL; } + +void ValueKlass::iterate_over_inside_oops(OopClosure* f, oop value) { + assert(!Universe::heap()->is_in_reserved(value), "This method is used on buffered values"); + + oop* addr_mirror = (oop*)(value)->mark_addr(); + f->do_oop_no_buffering(addr_mirror); + + if (!contains_oops()) return; + + OopMapBlock* map = start_of_nonstatic_oop_maps(); + OopMapBlock* const end_map = map + nonstatic_oop_map_count(); + + if (!UseCompressedOops) { + for (; map < end_map; map++) { + oop* p = (oop*) (((char*)(oopDesc*)value) + map->offset()); + oop* const end = p + map->count(); + for (; p < end; ++p) { + assert(oopDesc::is_oop_or_null(*p), "Sanity check"); + f->do_oop(p); + } + } + } else { + for (; map < end_map; map++) { + narrowOop* p = (narrowOop*) (((char*)(oopDesc*)value) + map->offset()); + narrowOop* const end = p + map->count(); + for (; p < end; ++p) { + oop o = oopDesc::decode_heap_oop(*p); + assert(Universe::heap()->is_in_reserved_or_null(o), "Sanity check"); + assert(oopDesc::is_oop_or_null(o), "Sanity check"); + f->do_oop(p); + } + } + } +}