8153267: nmethod's exception cache not multi-thread safe

Fri, 07 Apr 2017 02:15:31 +0900

author
dbuck
date
Fri, 07 Apr 2017 02:15:31 +0900
changeset 8734
c73c5d205d0a
parent 8733
92cb89e23f3e
child 8735
dcaab7b518c4

8153267: nmethod's exception cache not multi-thread safe
8143897: Weblogic12medrec assert(handler_address == SharedRuntime::compute_compiled_exc_handler(nm, pc, exception, force_unwind, true)) failed: Must be the same
Reviewed-by: kvn, mdoerr

src/share/vm/code/nmethod.cpp file | annotate | diff | comparison | revisions
src/share/vm/code/nmethod.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/vmStructs.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/code/nmethod.cpp	Tue Apr 04 02:49:51 2017 -0700
     1.2 +++ b/src/share/vm/code/nmethod.cpp	Fri Apr 07 02:15:31 2017 +0900
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -254,7 +254,8 @@
    1.11  
    1.12  
    1.13  address ExceptionCache::test_address(address addr) {
    1.14 -  for (int i=0; i<count(); i++) {
    1.15 +  int limit = count();
    1.16 +  for (int i = 0; i < limit; i++) {
    1.17      if (pc_at(i) == addr) {
    1.18        return handler_at(i);
    1.19      }
    1.20 @@ -265,9 +266,11 @@
    1.21  
    1.22  bool ExceptionCache::add_address_and_handler(address addr, address handler) {
    1.23    if (test_address(addr) == handler) return true;
    1.24 -  if (count() < cache_size) {
    1.25 -    set_pc_at(count(),addr);
    1.26 -    set_handler_at(count(), handler);
    1.27 +
    1.28 +  int index = count();
    1.29 +  if (index < cache_size) {
    1.30 +    set_pc_at(index, addr);
    1.31 +    set_handler_at(index, handler);
    1.32      increment_count();
    1.33      return true;
    1.34    }
    1.35 @@ -380,10 +383,11 @@
    1.36    assert(new_entry != NULL,"Must be non null");
    1.37    assert(new_entry->next() == NULL, "Must be null");
    1.38  
    1.39 -  if (exception_cache() != NULL) {
    1.40 -    new_entry->set_next(exception_cache());
    1.41 +  ExceptionCache *ec = exception_cache();
    1.42 +  if (ec != NULL) {
    1.43 +    new_entry->set_next(ec);
    1.44    }
    1.45 -  set_exception_cache(new_entry);
    1.46 +  release_set_exception_cache(new_entry);
    1.47  }
    1.48  
    1.49  void nmethod::clean_exception_cache(BoolObjectClosure* is_alive) {
     2.1 --- a/src/share/vm/code/nmethod.hpp	Tue Apr 04 02:49:51 2017 -0700
     2.2 +++ b/src/share/vm/code/nmethod.hpp	Fri Apr 07 02:15:31 2017 +0900
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -39,15 +39,16 @@
    2.11    Klass*   _exception_type;
    2.12    address  _pc[cache_size];
    2.13    address  _handler[cache_size];
    2.14 -  int      _count;
    2.15 +  volatile int _count;
    2.16    ExceptionCache* _next;
    2.17  
    2.18    address pc_at(int index)                     { assert(index >= 0 && index < count(),""); return _pc[index]; }
    2.19    void    set_pc_at(int index, address a)      { assert(index >= 0 && index < cache_size,""); _pc[index] = a; }
    2.20    address handler_at(int index)                { assert(index >= 0 && index < count(),""); return _handler[index]; }
    2.21    void    set_handler_at(int index, address a) { assert(index >= 0 && index < cache_size,""); _handler[index] = a; }
    2.22 -  int     count()                              { return _count; }
    2.23 -  void    increment_count()                    { _count++; }
    2.24 +  int     count()                              { return OrderAccess::load_acquire(&_count); }
    2.25 +  // increment_count is only called under lock, but there may be concurrent readers.
    2.26 +  void    increment_count()                    { OrderAccess::release_store(&_count, _count + 1); }
    2.27  
    2.28   public:
    2.29  
    2.30 @@ -237,7 +238,7 @@
    2.31    // counter is decreased (by 1) while sweeping.
    2.32    int _hotness_counter;
    2.33  
    2.34 -  ExceptionCache *_exception_cache;
    2.35 +  ExceptionCache * volatile _exception_cache;
    2.36    PcDescCache     _pc_desc_cache;
    2.37  
    2.38    // These are used for compiled synchronized native methods to
    2.39 @@ -433,7 +434,7 @@
    2.40  
    2.41    // flag accessing and manipulation
    2.42    bool  is_in_use() const                         { return _state == in_use; }
    2.43 -  bool  is_alive() const                          { return _state == in_use || _state == not_entrant; }
    2.44 +  bool  is_alive() const                          { unsigned char s = _state; return s == in_use || s == not_entrant; }
    2.45    bool  is_not_entrant() const                    { return _state == not_entrant; }
    2.46    bool  is_zombie() const                         { return _state == zombie; }
    2.47    bool  is_unloaded() const                       { return _state == unloaded;   }
    2.48 @@ -555,8 +556,10 @@
    2.49    void  set_stack_traversal_mark(long l)          { _stack_traversal_mark = l; }
    2.50  
    2.51    // Exception cache support
    2.52 +  // Note: _exception_cache may be read concurrently. We rely on memory_order_consume here.
    2.53    ExceptionCache* exception_cache() const         { return _exception_cache; }
    2.54    void set_exception_cache(ExceptionCache *ec)    { _exception_cache = ec; }
    2.55 +  void release_set_exception_cache(ExceptionCache *ec) { OrderAccess::release_store_ptr(&_exception_cache, ec); }
    2.56    address handler_for_exception_and_pc(Handle exception, address pc);
    2.57    void add_handler_for_exception_and_pc(Handle exception, address pc, address handler);
    2.58    void clean_exception_cache(BoolObjectClosure* is_alive);
     3.1 --- a/src/share/vm/runtime/vmStructs.cpp	Tue Apr 04 02:49:51 2017 -0700
     3.2 +++ b/src/share/vm/runtime/vmStructs.cpp	Fri Apr 07 02:15:31 2017 +0900
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -879,7 +879,7 @@
    3.11    nonstatic_field(nmethod,             _stack_traversal_mark,                         long)                                  \
    3.12    nonstatic_field(nmethod,             _compile_id,                                   int)                                   \
    3.13    nonstatic_field(nmethod,             _comp_level,                                   int)                                   \
    3.14 -  nonstatic_field(nmethod,             _exception_cache,                              ExceptionCache*)                       \
    3.15 +  volatile_nonstatic_field(nmethod,    _exception_cache,                              ExceptionCache*)                       \
    3.16    nonstatic_field(nmethod,             _marked_for_deoptimization,                    bool)                                  \
    3.17                                                                                                                               \
    3.18    unchecked_c2_static_field(Deoptimization,         _trap_reason_name,                   void*)                              \

mercurial