提交 5ff99bc1 编写于 作者: D dbuck

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
上级 baef4286
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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) { ...@@ -254,7 +254,8 @@ bool ExceptionCache::match_exception_with_space(Handle exception) {
address ExceptionCache::test_address(address addr) { address ExceptionCache::test_address(address addr) {
for (int i=0; i<count(); i++) { int limit = count();
for (int i = 0; i < limit; i++) {
if (pc_at(i) == addr) { if (pc_at(i) == addr) {
return handler_at(i); return handler_at(i);
} }
...@@ -265,9 +266,11 @@ address ExceptionCache::test_address(address addr) { ...@@ -265,9 +266,11 @@ address ExceptionCache::test_address(address addr) {
bool ExceptionCache::add_address_and_handler(address addr, address handler) { bool ExceptionCache::add_address_and_handler(address addr, address handler) {
if (test_address(addr) == handler) return true; if (test_address(addr) == handler) return true;
if (count() < cache_size) {
set_pc_at(count(),addr); int index = count();
set_handler_at(count(), handler); if (index < cache_size) {
set_pc_at(index, addr);
set_handler_at(index, handler);
increment_count(); increment_count();
return true; return true;
} }
...@@ -380,10 +383,11 @@ void nmethod::add_exception_cache_entry(ExceptionCache* new_entry) { ...@@ -380,10 +383,11 @@ void nmethod::add_exception_cache_entry(ExceptionCache* new_entry) {
assert(new_entry != NULL,"Must be non null"); assert(new_entry != NULL,"Must be non null");
assert(new_entry->next() == NULL, "Must be null"); assert(new_entry->next() == NULL, "Must be null");
if (exception_cache() != NULL) { ExceptionCache *ec = exception_cache();
new_entry->set_next(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) { void nmethod::clean_exception_cache(BoolObjectClosure* is_alive) {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,15 +39,16 @@ class ExceptionCache : public CHeapObj<mtCode> { ...@@ -39,15 +39,16 @@ class ExceptionCache : public CHeapObj<mtCode> {
Klass* _exception_type; Klass* _exception_type;
address _pc[cache_size]; address _pc[cache_size];
address _handler[cache_size]; address _handler[cache_size];
int _count; volatile int _count;
ExceptionCache* _next; ExceptionCache* _next;
address pc_at(int index) { assert(index >= 0 && index < count(),""); return _pc[index]; } 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; } 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]; } 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; } void set_handler_at(int index, address a) { assert(index >= 0 && index < cache_size,""); _handler[index] = a; }
int count() { return _count; } int count() { return OrderAccess::load_acquire(&_count); }
void increment_count() { _count++; } // increment_count is only called under lock, but there may be concurrent readers.
void increment_count() { OrderAccess::release_store(&_count, _count + 1); }
public: public:
...@@ -237,7 +238,7 @@ class nmethod : public CodeBlob { ...@@ -237,7 +238,7 @@ class nmethod : public CodeBlob {
// counter is decreased (by 1) while sweeping. // counter is decreased (by 1) while sweeping.
int _hotness_counter; int _hotness_counter;
ExceptionCache *_exception_cache; ExceptionCache * volatile _exception_cache;
PcDescCache _pc_desc_cache; PcDescCache _pc_desc_cache;
// These are used for compiled synchronized native methods to // These are used for compiled synchronized native methods to
...@@ -433,7 +434,7 @@ class nmethod : public CodeBlob { ...@@ -433,7 +434,7 @@ class nmethod : public CodeBlob {
// flag accessing and manipulation // flag accessing and manipulation
bool is_in_use() const { return _state == in_use; } 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_not_entrant() const { return _state == not_entrant; }
bool is_zombie() const { return _state == zombie; } bool is_zombie() const { return _state == zombie; }
bool is_unloaded() const { return _state == unloaded; } bool is_unloaded() const { return _state == unloaded; }
...@@ -555,8 +556,10 @@ public: ...@@ -555,8 +556,10 @@ public:
void set_stack_traversal_mark(long l) { _stack_traversal_mark = l; } void set_stack_traversal_mark(long l) { _stack_traversal_mark = l; }
// Exception cache support // Exception cache support
// Note: _exception_cache may be read concurrently. We rely on memory_order_consume here.
ExceptionCache* exception_cache() const { return _exception_cache; } ExceptionCache* exception_cache() const { return _exception_cache; }
void set_exception_cache(ExceptionCache *ec) { _exception_cache = ec; } 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); address handler_for_exception_and_pc(Handle exception, address pc);
void add_handler_for_exception_and_pc(Handle exception, address pc, address handler); void add_handler_for_exception_and_pc(Handle exception, address pc, address handler);
void clean_exception_cache(BoolObjectClosure* is_alive); void clean_exception_cache(BoolObjectClosure* is_alive);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -879,7 +879,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable; ...@@ -879,7 +879,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
nonstatic_field(nmethod, _stack_traversal_mark, long) \ nonstatic_field(nmethod, _stack_traversal_mark, long) \
nonstatic_field(nmethod, _compile_id, int) \ nonstatic_field(nmethod, _compile_id, int) \
nonstatic_field(nmethod, _comp_level, 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) \ nonstatic_field(nmethod, _marked_for_deoptimization, bool) \
\ \
unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \ unchecked_c2_static_field(Deoptimization, _trap_reason_name, void*) \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册