From 5ff99bc13a12cc7bcb7e854a34ba94ca89f1e555 Mon Sep 17 00:00:00 2001 From: dbuck Date: Fri, 7 Apr 2017 02:15:31 +0900 Subject: [PATCH] 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 | 20 ++++++++++++-------- src/share/vm/code/nmethod.hpp | 15 +++++++++------ src/share/vm/runtime/vmStructs.cpp | 4 ++-- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/share/vm/code/nmethod.cpp b/src/share/vm/code/nmethod.cpp index e88ce9775..b897b6a7a 100644 --- a/src/share/vm/code/nmethod.cpp +++ b/src/share/vm/code/nmethod.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -254,7 +254,8 @@ bool ExceptionCache::match_exception_with_space(Handle exception) { address ExceptionCache::test_address(address addr) { - for (int i=0; inext() == NULL, "Must be null"); - if (exception_cache() != NULL) { - new_entry->set_next(exception_cache()); + ExceptionCache *ec = exception_cache(); + if (ec != NULL) { + new_entry->set_next(ec); } - set_exception_cache(new_entry); + release_set_exception_cache(new_entry); } void nmethod::clean_exception_cache(BoolObjectClosure* is_alive) { diff --git a/src/share/vm/code/nmethod.hpp b/src/share/vm/code/nmethod.hpp index b7d689005..5b16f3334 100644 --- a/src/share/vm/code/nmethod.hpp +++ b/src/share/vm/code/nmethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,15 +39,16 @@ class ExceptionCache : public CHeapObj { Klass* _exception_type; address _pc[cache_size]; address _handler[cache_size]; - int _count; + volatile int _count; ExceptionCache* _next; address pc_at(int index) { assert(index >= 0 && index < count(),""); return _pc[index]; } void set_pc_at(int index, address a) { assert(index >= 0 && index < cache_size,""); _pc[index] = a; } address handler_at(int index) { assert(index >= 0 && index < count(),""); return _handler[index]; } void set_handler_at(int index, address a) { assert(index >= 0 && index < cache_size,""); _handler[index] = a; } - int count() { return _count; } - void increment_count() { _count++; } + int count() { return OrderAccess::load_acquire(&_count); } + // increment_count is only called under lock, but there may be concurrent readers. + void increment_count() { OrderAccess::release_store(&_count, _count + 1); } public: @@ -237,7 +238,7 @@ class nmethod : public CodeBlob { // counter is decreased (by 1) while sweeping. int _hotness_counter; - ExceptionCache *_exception_cache; + ExceptionCache * volatile _exception_cache; PcDescCache _pc_desc_cache; // These are used for compiled synchronized native methods to @@ -433,7 +434,7 @@ class nmethod : public CodeBlob { // flag accessing and manipulation bool is_in_use() const { return _state == in_use; } - bool is_alive() const { return _state == in_use || _state == not_entrant; } + bool is_alive() const { unsigned char s = _state; return s == in_use || s == not_entrant; } bool is_not_entrant() const { return _state == not_entrant; } bool is_zombie() const { return _state == zombie; } bool is_unloaded() const { return _state == unloaded; } @@ -555,8 +556,10 @@ public: void set_stack_traversal_mark(long l) { _stack_traversal_mark = l; } // Exception cache support + // Note: _exception_cache may be read concurrently. We rely on memory_order_consume here. ExceptionCache* exception_cache() const { return _exception_cache; } void set_exception_cache(ExceptionCache *ec) { _exception_cache = ec; } + void release_set_exception_cache(ExceptionCache *ec) { OrderAccess::release_store_ptr(&_exception_cache, ec); } address handler_for_exception_and_pc(Handle exception, address pc); void add_handler_for_exception_and_pc(Handle exception, address pc, address handler); void clean_exception_cache(BoolObjectClosure* is_alive); diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp index 80b01150b..dff404fc9 100644 --- a/src/share/vm/runtime/vmStructs.cpp +++ b/src/share/vm/runtime/vmStructs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -879,7 +879,7 @@ typedef TwoOopHashtable SymbolTwoOopHashtable; nonstatic_field(nmethod, _stack_traversal_mark, long) \ nonstatic_field(nmethod, _compile_id, int) \ nonstatic_field(nmethod, _comp_level, int) \ - nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \ + volatile_nonstatic_field(nmethod, _exception_cache, ExceptionCache*) \ nonstatic_field(nmethod, _marked_for_deoptimization, bool) \ \ unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \ -- GitLab