Fri, 07 Apr 2017 02:15:31 +0900
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
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*) \