8014447: Object.hashCode intrinsic breaks inline caches

Fri, 27 Sep 2013 11:52:24 +0400

author
shade
date
Fri, 27 Sep 2013 11:52:24 +0400
changeset 5798
29bdcf12457c
parent 5797
f2512d89ad0c
child 5799
d8d059e90ec1

8014447: Object.hashCode intrinsic breaks inline caches
Summary: Try to inline as normal method first, then fall back to intrinsic.
Reviewed-by: kvn, twisti

src/share/vm/opto/callGenerator.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/doCall.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/library_call.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/callGenerator.hpp	Sat Sep 28 12:42:22 2013 -0700
     1.2 +++ b/src/share/vm/opto/callGenerator.hpp	Fri Sep 27 11:52:24 2013 +0400
     1.3 @@ -65,6 +65,8 @@
     1.4    virtual bool      is_predicted() const        { return false; }
     1.5    // is_trap: Does not return to the caller.  (E.g., uncommon trap.)
     1.6    virtual bool      is_trap() const             { return false; }
     1.7 +  // does_virtual_dispatch: Should try inlining as normal method first.
     1.8 +  virtual bool      does_virtual_dispatch() const     { return false; }
     1.9  
    1.10    // is_late_inline: supports conversion of call into an inline
    1.11    virtual bool      is_late_inline() const      { return false; }
     2.1 --- a/src/share/vm/opto/doCall.cpp	Sat Sep 28 12:42:22 2013 -0700
     2.2 +++ b/src/share/vm/opto/doCall.cpp	Fri Sep 27 11:52:24 2013 +0400
     2.3 @@ -110,6 +110,7 @@
     2.4    // then we return it as the inlined version of the call.
     2.5    // We do this before the strict f.p. check below because the
     2.6    // intrinsics handle strict f.p. correctly.
     2.7 +  CallGenerator* cg_intrinsic = NULL;
     2.8    if (allow_inline && allow_intrinsics) {
     2.9      CallGenerator* cg = find_intrinsic(callee, call_does_dispatch);
    2.10      if (cg != NULL) {
    2.11 @@ -121,7 +122,16 @@
    2.12            cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg);
    2.13          }
    2.14        }
    2.15 -      return cg;
    2.16 +
    2.17 +      // If intrinsic does the virtual dispatch, we try to use the type profile
    2.18 +      // first, and hopefully inline it as the regular virtual call below.
    2.19 +      // We will retry the intrinsic if nothing had claimed it afterwards.
    2.20 +      if (cg->does_virtual_dispatch()) {
    2.21 +        cg_intrinsic = cg;
    2.22 +        cg = NULL;
    2.23 +      } else {
    2.24 +        return cg;
    2.25 +      }
    2.26      }
    2.27    }
    2.28  
    2.29 @@ -266,6 +276,13 @@
    2.30      }
    2.31    }
    2.32  
    2.33 +  // Nothing claimed the intrinsic, we go with straight-forward inlining
    2.34 +  // for already discovered intrinsic.
    2.35 +  if (allow_inline && allow_intrinsics && cg_intrinsic != NULL) {
    2.36 +    assert(cg_intrinsic->does_virtual_dispatch(), "sanity");
    2.37 +    return cg_intrinsic;
    2.38 +  }
    2.39 +
    2.40    // There was no special inlining tactic, or it bailed out.
    2.41    // Use a more generic tactic, like a simple call.
    2.42    if (call_does_dispatch) {
     3.1 --- a/src/share/vm/opto/library_call.cpp	Sat Sep 28 12:42:22 2013 -0700
     3.2 +++ b/src/share/vm/opto/library_call.cpp	Fri Sep 27 11:52:24 2013 +0400
     3.3 @@ -47,19 +47,22 @@
     3.4   private:
     3.5    bool             _is_virtual;
     3.6    bool             _is_predicted;
     3.7 +  bool             _does_virtual_dispatch;
     3.8    vmIntrinsics::ID _intrinsic_id;
     3.9  
    3.10   public:
    3.11 -  LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, vmIntrinsics::ID id)
    3.12 +  LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, bool does_virtual_dispatch, vmIntrinsics::ID id)
    3.13      : InlineCallGenerator(m),
    3.14        _is_virtual(is_virtual),
    3.15        _is_predicted(is_predicted),
    3.16 +      _does_virtual_dispatch(does_virtual_dispatch),
    3.17        _intrinsic_id(id)
    3.18    {
    3.19    }
    3.20    virtual bool is_intrinsic() const { return true; }
    3.21    virtual bool is_virtual()   const { return _is_virtual; }
    3.22    virtual bool is_predicted()   const { return _is_predicted; }
    3.23 +  virtual bool does_virtual_dispatch()   const { return _does_virtual_dispatch; }
    3.24    virtual JVMState* generate(JVMState* jvms);
    3.25    virtual Node* generate_predicate(JVMState* jvms);
    3.26    vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
    3.27 @@ -355,6 +358,7 @@
    3.28    }
    3.29  
    3.30    bool is_predicted = false;
    3.31 +  bool does_virtual_dispatch = false;
    3.32  
    3.33    switch (id) {
    3.34    case vmIntrinsics::_compareTo:
    3.35 @@ -381,8 +385,10 @@
    3.36      break;
    3.37    case vmIntrinsics::_hashCode:
    3.38      if (!InlineObjectHash)  return NULL;
    3.39 +    does_virtual_dispatch = true;
    3.40      break;
    3.41    case vmIntrinsics::_clone:
    3.42 +    does_virtual_dispatch = true;
    3.43    case vmIntrinsics::_copyOf:
    3.44    case vmIntrinsics::_copyOfRange:
    3.45      if (!InlineObjectCopy)  return NULL;
    3.46 @@ -541,7 +547,7 @@
    3.47      if (!InlineUnsafeOps)  return NULL;
    3.48    }
    3.49  
    3.50 -  return new LibraryIntrinsic(m, is_virtual, is_predicted, (vmIntrinsics::ID) id);
    3.51 +  return new LibraryIntrinsic(m, is_virtual, is_predicted, does_virtual_dispatch, (vmIntrinsics::ID) id);
    3.52  }
    3.53  
    3.54  //----------------------register_library_intrinsics-----------------------

mercurial