Default method resolution question

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Mon Sep 16 04:39:45 PDT 2013


Hi,

I hit an assert when doing CHA for a default method during JIT-compilation:
#  Internal Error (src/share/vm/code/dependencies.cpp:1411)
#  assert(wf.check_method_context(ctxk, m)) failed: proper context

Call stack:
Dependencies::find_unique_concrete_method
ciMethod::find_monomorphic_target
Compile::optimize_inlining
Compile::optimize_virtual_call
Parse::do_call
...

What does check_method_context do it resolves the method again and then 
do pointer comparison to check that result it the same. And it doesn't 
work for default methods:
  Dependency method not found in the associated context:
   context = javasoft.sqe.tests.api.java.util.TreeSet.SharedData$1
   method =  java.util.TreeSet::parallelStream
   found =  java.util.TreeSet::parallelStream

My main suspicion is that the problem is in check_method_context (the 
check is imprecise and already has a number of exceptions), but I want 
to double-check. Does method resolution behavior I see look normal?

Here are my observations.

Method passed into Dependencies::find_unique_concrete_method:
{method}
  - this oop:          0xb69eab58
  - method holder:     'java/util/TreeSet'
  - constants:         0xb69eacd8 constant pool [305] {0xb69eacdc} for 
'java/util/TreeSet' cache=0xb69eb2b8
  - access:            0x80001041  public volatile synthetic
  - name:              'parallelStream'
  - signature:         '()Ljava/util/stream/Stream;'
  - max stack:         2
  - max locals:        1
  - size of params:    1
  - method size:       14
  - highest level:     4
  - vtable index:      22
  - i2i entry:         0xfa00b940
  - adapters:          AHE at 0x081982ac: 0xa0000000 i2c: 0xfa0aaec0 c2i: 
0xfa0aaf49 c2iUV: 0xfa0aaf28
  - compiled entry     0xfa1704ec
  - code size:         5
  - code start:        0xb69eab44
  - code end (excl):   0xb69eab49
  - method data:       0xb6806b10
  - checked ex length: 0
  - localvar length:   0
  - compiled code: nmethod 584533  988 
java.util.TreeSet::parallelStream (5 bytes)

Method resolved in check_method_context:
{method}
  - this oop:          0xb69ea978
  - method holder:     'java/util/TreeSet'
  - constants:         0xb69eacd8 constant pool [305] {0xb69eacdc} for 
'java/util/TreeSet' cache=0xb69eb2b8
  - access:            0x1041  public volatile synthetic
  - name:              'parallelStream'
  - signature:         'Ljava/util/stream/Stream'
  - max stack:         2
  - max locals:        1
  - size of params:    1
  - method size:       14
  - vtable index:      22
  - i2i entry:         0xfa00b940
  - adapters:          AHE at 0x081982ac: 0xa0000000 i2c: 0xfa0aaec0 c2i: 
0xfa0aaf49 c2iUV: 0xfa0aaf28
  - compiled entry     0xfa0aaf49
  - code size:         5
  - code start:        0xb69ea964
  - code end (excl):   0xb69ea969
  - method data:       0xb6584270
  - checked ex length: 0
  - localvar length:   0

Class hierarchy:
javasoft.sqe.tests.api.java.util.TreeSet.SharedData$1 extends 
java.util.TreeSet<E>

java.util.TreeSet<E> extends java.util.AbstractSet<E>
		     implements java.util.NavigableSet<E>,
				java.lang.Cloneable,
				java.io.Serializable

public interface Collection<E> extends Iterable<E> {
     default Stream<E> parallelStream() { ... }

Original method pointer is acquired through ciMethod::resolve_invoke call.

resolved_method && CallInfo from LinkResolver::resolve_virtual_call:

(dbx) print resolved_method
resolved_method = {
     _value  = 0xb69ea978   <=============
     _thread = 0x8232c00
}

(dbx) print result
result = {
     _resolved_klass       = {
         _value = 0xb69ea618
     }
     _selected_klass       = {
         _value = 0xb69f3bb0
     }
     _resolved_method      = {
         _value  = 0xb69ea978 <===========
         _thread = 0x8232c00
     }
     _selected_method      = {
         _value  = 0xb69eab58 <===========
         _thread = 0x8232c00
     }
     _vtable_index         = 22
     _resolved_appendix    = {
         _handle = (nil)
     }
     _resolved_method_type = {
         _handle = (nil)
     }
}

_resolved_method is the same as computed in check_method_context.

_selected_method is loaded from vtable at linkResolver.cpp:943:
     selected_method = methodHandle(THREAD, 
inst->method_at_vtable(vtable_index));

Best regards,
Vladimir Ivanov


More information about the hotspot-runtime-dev mailing list