--- old/src/share/vm/gc/parallel/psCompactionManager.cpp 2017-03-16 13:22:45.417143554 +0100 +++ new/src/share/vm/gc/parallel/psCompactionManager.cpp 2017-03-16 13:22:45.277140633 +0100 @@ -295,10 +295,10 @@ void ValueArrayKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) { assert(obj->is_valueArray(),"must be a value array"); - cm->follow_klass(this); - if (contains_oops()) { - Unimplemented(); // Don't have embedded oops to test with just now + if (contains_oops()) { // CMH: parallel version (like objArrayTask) missing, treat as single obj for now + ParCompactionManager::MarkAndPushClosure cl(cm); + ValueArrayKlass::oop_oop_iterate_elements(valueArrayOop(obj), &cl); } } --- old/src/share/vm/gc/parallel/psParallelCompact.cpp 2017-03-16 13:22:45.829152150 +0100 +++ new/src/share/vm/gc/parallel/psParallelCompact.cpp 2017-03-16 13:22:45.693149313 +0100 @@ -3133,11 +3133,8 @@ void ValueArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) { assert(obj->is_valueArray(),"must be a value array"); if (contains_oops()) { - Unimplemented(); -#if 0 PSParallelCompact::AdjustPointerClosure closure(cm); oop_oop_iterate_elements(valueArrayOop(obj), &closure); -#endif } } --- old/src/share/vm/oops/klass.hpp 2017-03-16 13:22:46.241160747 +0100 +++ new/src/share/vm/oops/klass.hpp 2017-03-16 13:22:46.133158493 +0100 @@ -79,7 +79,7 @@ // distinct bytes, as follows: // MSB:[tag, hsz, ebt, log2(esz)]:LSB // where: - // tag is 0x80 if the elements are oops, 0xC0 if non-oops + // tag is 0x80 if the elements are oops, 0xC0 if non-oops, 0xA0 if value types // hsz is array header size in bytes (i.e., offset of first element) // ebt is the BasicType of the elements // esz is the element size in bytes @@ -316,13 +316,11 @@ _lh_header_size_shift = BitsPerByte*2, _lh_header_size_mask = right_n_bits(BitsPerByte), // shifted mask - // Additional array type bits - _lh_valuetype_bit = 29, // maybe objArray or valueArrayOop - - _lh_array_tag_bits = 2, + _lh_array_tag_bits = 3, _lh_array_tag_shift = BitsPerInt - _lh_array_tag_bits, - _lh_array_tag_type_value = ~0x00, // 0xC0000000 >> 30 - _lh_array_tag_obj_value = ~0x01 // 0x80000000 >> 30 + _lh_array_tag_type_value = ~0x3, // bits ~100 compare as int, ie. sign extended + _lh_array_tag_vt_value = ~0x2, // bits ~101 + _lh_array_tag_obj_value = ~0x1, // bits ~110 }; static int layout_helper_size_in_bytes(jint lh) { @@ -346,7 +344,7 @@ return _lh_array_tag_obj_value == (lh >> _lh_array_tag_shift); } static bool layout_helper_is_valueArray(jint lh) { - return (lh >> _lh_valuetype_bit) & 1; + return _lh_array_tag_vt_value == (lh >> _lh_array_tag_shift); } static int layout_helper_header_size(jint lh) { assert(lh < (jint)_lh_neutral_value, "must be array"); --- old/src/share/vm/oops/objArrayKlass.cpp 2017-03-16 13:22:46.657169427 +0100 +++ new/src/share/vm/oops/objArrayKlass.cpp 2017-03-16 13:22:46.525166673 +0100 @@ -476,7 +476,8 @@ guarantee(element_klass()->is_klass(), "should be klass"); guarantee(bottom_klass()->is_klass(), "should be klass"); Klass* bk = bottom_klass(); - guarantee(bk->is_instance_klass() || bk->is_typeArray_klass(), "invalid bottom klass"); + guarantee(bk->is_instance_klass() || bk->is_typeArray_klass() || bk->is_valueArray_klass(), + "invalid bottom klass"); } void ObjArrayKlass::oop_verify_on(oop obj, outputStream* st) { --- old/src/share/vm/oops/valueArrayKlass.cpp 2017-03-16 13:22:47.061177857 +0100 +++ new/src/share/vm/oops/valueArrayKlass.cpp 2017-03-16 13:22:46.925175019 +0100 @@ -131,12 +131,11 @@ jint ValueArrayKlass::array_layout_helper(ValueKlass* vk) { BasicType etype = T_VALUETYPE; - int atag = _lh_array_tag_type_value; + int atag = _lh_array_tag_vt_value; int esize = upper_log2(vk->raw_value_byte_size()); int hsize = arrayOopDesc::base_offset_in_bytes(etype); int lh = (atag << _lh_array_tag_shift) - | (1 << _lh_valuetype_bit) | (hsize << _lh_header_size_shift) | ((int)etype << _lh_element_type_shift) | ((esize) << _lh_log2_element_size_shift); @@ -144,9 +143,10 @@ assert(lh < (int)_lh_neutral_value, "must look like an array layout"); assert(layout_helper_is_array(lh), "correct kind"); assert(layout_helper_is_valueArray(lh), "correct kind"); + assert(!layout_helper_is_typeArray(lh), "correct kind"); + assert(!layout_helper_is_objArray(lh), "correct kind"); assert(layout_helper_header_size(lh) == hsize, "correct decode"); assert(layout_helper_element_type(lh) == etype, "correct decode"); - assert(layout_helper_is_typeArray(lh), "correct kind"); assert(layout_helper_log2_element_size(lh) == esize, "correct decode"); assert((1 << esize) < BytesPerLong || is_size_aligned(hsize, HeapWordsPerLong), "unaligned base"); --- old/src/share/vm/oops/valueArrayKlass.hpp 2017-03-16 13:22:47.401184952 +0100 +++ new/src/share/vm/oops/valueArrayKlass.hpp 2017-03-16 13:22:47.297182782 +0100 @@ -73,7 +73,6 @@ int element_byte_size() const { return 1 << layout_helper_log2_element_size(_layout_helper); } int element_value_store_size() const { return _element_value_store_size; } - bool is_typeArray_klass_slow() const { return true; } bool is_valueArray_klass_slow() const { return true; } bool contains_oops() { return element_klass()->contains_oops(); } --- old/test/runtime/valhalla/valuetypes/ValueOops.java 2017-03-16 13:22:47.849194301 +0100 +++ new/test/runtime/valhalla/valuetypes/ValueOops.java 2017-03-16 13:22:47.705191296 +0100 @@ -46,6 +46,12 @@ * @run main/othervm -Xint -noverify -XX:+UseG1GC -Xmx128m * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * runtime.valhalla.valuetypes.ValueOops + * @run main/othervm -Xint -noverify -XX:+UseParallelGC -Xmx128m + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * runtime.valhalla.valuetypes.ValueOops + * @run main/othervm -Xint -noverify -XX:+UseConcMarkSweepGC -Xmx128m + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * runtime.valhalla.valuetypes.ValueOops */ public class ValueOops {