De-opt support and dependency tracking in HotSpot

Tom Rodriguez tom.rodriguez at
Wed Sep 22 12:43:16 PDT 2010

On Sep 22, 2010, at 12:22 PM, Douglas Simon wrote:

> I've already received one correction. I was not aware of the _dependencies field in instanceKlass that lists the nmethods that have a dependency on that class. That is, there's no traversal of the code cache (for this purpose).

That was an optimization we added a while back to reduce the overhead because the code cache can get quite large.  If I were going to rewrite the bookkeeping part I'd probably build a central database of dependencies instead of storing the information in the nmethod itself.  Scanning on the nmethods recorded by the class reduces the overhead but you still often end up checking the same dependency for each nmethod.  I think it would simplify the implementation quite a bit since we could skip the serialization machinery and the dependency logic could be easily captured by a base class with subclasses for the variants.  Each unique dependency would only be checked once as well.

The variety of dependencies is greater than just DepType, Klass though most of them fit within that schema.

int Dependencies::_dep_args[TYPE_LIMIT] = {
  -1,// end_marker
  1, // evol_method m
  1, // leaf_type ctxk
  2, // abstract_with_unique_concrete_subtype ctxk, k
  1, // abstract_with_no_concrete_subtype ctxk
  1, // concrete_with_no_concrete_subtype ctxk
  2, // unique_concrete_method ctxk, m
  3, // unique_concrete_subtypes_2 ctxk, k1, k2
  3, // unique_concrete_methods_2 ctxk, m1, m2
  1  // no_finalizable_subclasses ctxk

I don't think the _2 variants are currently in use.  The evol_method one is used to tracking inlining so that we can regenerate nmethods with classes are redefined, though this could be make more coarse grained by just recording the declaring klass.


> -Doug
> On Sep 22, 2010, at 5:20 PM, Douglas Simon wrote:
>> Hi,
>> We are currently implementing de-opt support in the Maxine VM. I've just spent some time browsing HotSpot source code to see how dependencies are tracked for the purpose of speculative opts and de-opt. A very brief summary of what I've deduced is below. Any corrections/feedback/pointers to (non-code-embedded) documentation on this part of HotSpot would be greatly appreciated!
>> -Doug
>> Dependency tracking in HotSpot
>> ==============================
>> A dependency is from a compiled method (i.e. nmethod) to a class (i.e. a klass). A dependency may be actually to specific method in a class but for the purpose of triggering dependency checking, it is the class in a dependency that matters. A compiled method can have more than one dependency and so each compiled method encodes a set of dependencies. A dependency is essentially a <DepType, klass> pair. For example, <concrete_with_no_concrete_subtype, java.util.HashMap>. When a new class is loaded, it is the root of a "dependency change set" (i.e. a DepChange) which is the super class hierarchy (including interfaces) rooted by the new class. The set of (live) compiled methods in the code cache is traversed just before the new class is registered in the system dictionary to see if any of them has a dependency in the dependency change set. If so and the assumption represented by the dependency is invalidated, then de-opt is triggered for the nmethod.
>> A potentially significant cost in this mechanism is the traversal of all methods in the code cache for each new class loaded. I assume this is done under the code cache lock. It may be that the cost of this in HotSpot is actually not so high as the number of nmethods code cache is relatively small (HotSpot has an interpreter). And it may also be mitigated by the fact that the cost of class loading dwarfs the cost of code cache traversals.

More information about the hotspot-dev mailing list