United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7114095 G1: assert(obj == oopDesc::load_decode_heap_oop(p)) failed: p should still be pointing to obj
JDK-7114095 : G1: assert(obj == oopDesc::load_decode_heap_oop(p)) failed: p should still be pointing to obj

Details
Type:
Bug
Submit Date:
2011-11-21
Status:
Closed
Updated Date:
2012-03-22
Project Name:
JDK
Resolved Date:
2012-01-20
Component:
hotspot
OS:
generic
Sub-Component:
gc
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
hs23
Fixed Versions:
hs23 (b08)

Related Reports
Backport:
Backport:
Relates:

Sub Tasks

Description
G1 crashes with 

assert(obj == oopDesc::load_decode_heap_oop(p)) failed: p should still be pointing to obj

Here is head dof hs_err file
;; Using jvm: "/export/local/common/jdk/baseline/solaris-amd64/jre/lib/amd64/server/libjvm.so"
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/tmp/jprt/P1/014930.jcoomes/source/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp:88), pid=22626, tid=6
#  assert(obj == oopDesc::load_decode_heap_oop(p)) failed: p should still be pointing to obj
#
# JRE version: 8.0
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.0-b06-fastdebug mixed mode solaris-amd64 compressed oops)
# Core dump written. Default location: /export/local/56370.HSX.PIT.VM_solaris-amd64_vm__server_mixed_vm.parallel_class_loading.testlist/results/ResultDir/init-simple/core or core.22626
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0x0000000000452800):  GCTaskThread [stack: 0x0000000000000000,0x0000000000000000] [id=6]

Stack: 
[error occurred during error reporting (printing stack bounds), id 0xe0000000]

Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x2703ff4]  void VMError::report(outputStream*)+0x8c8;;  void VMError::report(outputStream*)+0x8c8
V  [libjvm.so+0x2705139]  void VMError::report_and_die()+0x4fd;;  void VMError::report_and_die()+0x4fd
V  [libjvm.so+0xe87f7b]  void report_vm_error(const char*,int,const char*,const char*)+0x55f;;  void report_vm_error(const char*,int,const char*,const char*)+0x55f
V  [libjvm.so+0x2704b42]  void VMError::report(outputStream*)+0x1416;;  void VMError::report(outputStream*)+0x1416
V  [libjvm.so+0x2705139]  void VMError::report_and_die()+0x4fd;;  void VMError::report_and_die()+0x4fd
V  [libjvm.so+0xe87f7b]  void report_vm_error(const char*,int,const char*,const char*)+0x55f;;  void report_vm_error(const char*,int,const char*,const char*)+0x55f
V  [libjvm.so+0x142f522]  int instanceRefKlass::oop_oop_iterate_backwards_nv(oop,G1ParScanClosure*)+0x8d6e;;  int instanceRefKlass::oop_oop_iterate_backwards_nv(oop,G1ParScanClosure*)+0x8d6e
V  [libjvm.so+0x103d2ce]  oop G1ParCopyHelper::copy_to_survivor_space(oop,bool,bool)+0x1962;;  oop G1ParCopyHelper::copy_to_survivor_space(oop,bool,bool)+0x1962
V  [libjvm.so+0x107c1ef]  void G1ParCopyClosure<false,(G1Barrier)2,false>::do_oop_work<unsigned>(__type_3*)+0x4eb;;  void G1ParCopyClosure<false,(G1Barrier)2,false>::do_oop_work<unsigned>(__type_3*)+0x4eb
V  [libjvm.so+0x103e5f8]  void G1ParEvacuateFollowersClosure::do_void()+0x6a0;;  void G1ParEvacuateFollowersClosure::do_void()+0x6a0
V  [libjvm.so+0x104f914]  void G1ParTask::work(int)+0x6d8;;  void G1ParTask::work(int)+0x6d8
V  [libjvm.so+0x2745433]  void GangWorker::loop()+0x51f;;  void GangWorker::loop()+0x51f
V  [libjvm.so+0x215fea2]  java_start+0x6a6;;  java_start+0x6a6
C  [libc.so.1+0xd704b]  _thr_setup+0x5b;;  _thr_setup+0x5b
C  [libc.so.1+0xd7280]  ht_pause+0x10;;  _lwp_start+0x0

                                    

Comments
EVALUATION

The scan closure is applied to the discovered field (because "closure->apply_to_weak_ref_discovered_field()" returns true). The G1ParScanClosure::do_oop_nv() method pushes the discovered field on the _refs_to_scan queue. After this another worker thread "steals" the entry for the discovered field and starts evacuating the object it points to. The thread proceeds to look at the referent field (either discover the reference or apply the closure to it) and then applies the scan closure to the discovered field (for the second time since "ReferenceProcessor::pending_list_uses_discovered_field()" returns true). While the scan closure is being applied to the discovered field (for the second time), the evacuation of the object referenced by the discovered field completes and the field is updated.

Race between one worker thread evacuating and updating the discovered field of a reference object (which it stole) and another worker pushing the discovered field on to the _refs_to_scan queue for a second time.

Assert is too strong and needs to be weakened.
                                     
2011-11-29
EVALUATION

http://hg.openjdk.java.net/hsx/hotspot-gc/hotspot/rev/4406629aa157
                                     
2011-12-02
SUGGESTED FIX

Weaken the assert or ensure that the scan closure is applied to the discovered field only once by the code in instanceRefKlass.cpp. I chose to weaken the assert.
                                     
2011-12-05
EVALUATION

http://hg.openjdk.java.net/hsx/hotspot-emb/hotspot/rev/4406629aa157
                                     
2011-12-15
EVALUATION

http://hg.openjdk.java.net/lambda/lambda/hotspot/rev/4406629aa157
                                     
2012-03-22



Hardware and Software, Engineered to Work Together