Fri, 30 Mar 2018 20:09:45 +0000
8199406: Performance drop with Java JDK 1.8.0_162-b32
Summary: Improve the nmethod unloading times by optimizing the search for an itable stub in VtableStubs array
Reviewed-by: kvn, coleenp, tschatzl
1.1 --- a/src/share/vm/code/codeBlob.cpp Wed Mar 21 12:05:05 2018 -0700 1.2 +++ b/src/share/vm/code/codeBlob.cpp Fri Mar 30 20:09:45 2018 +0000 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 1998, 2018, 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 @@ -289,6 +289,28 @@ 1.11 return blob; 1.12 } 1.13 1.14 +VtableBlob::VtableBlob(const char* name, int size) : 1.15 + BufferBlob(name, size) { 1.16 +} 1.17 + 1.18 +VtableBlob* VtableBlob::create(const char* name, int buffer_size) { 1.19 + ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock 1.20 + 1.21 + VtableBlob* blob = NULL; 1.22 + unsigned int size = sizeof(VtableBlob); 1.23 + // align the size to CodeEntryAlignment 1.24 + size = align_code_offset(size); 1.25 + size += round_to(buffer_size, oopSize); 1.26 + assert(name != NULL, "must provide a name"); 1.27 + { 1.28 + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 1.29 + blob = new (size) VtableBlob(name, size); 1.30 + } 1.31 + // Track memory usage statistic after releasing CodeCache_lock 1.32 + MemoryService::track_code_cache_memory_usage(); 1.33 + 1.34 + return blob; 1.35 +} 1.36 1.37 //---------------------------------------------------------------------------------------------------- 1.38 // Implementation of MethodHandlesAdapterBlob
2.1 --- a/src/share/vm/code/codeBlob.hpp Wed Mar 21 12:05:05 2018 -0700 2.2 +++ b/src/share/vm/code/codeBlob.hpp Fri Mar 30 20:09:45 2018 +0000 2.3 @@ -1,5 +1,5 @@ 2.4 /* 2.5 - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * Copyright (c) 1998, 2018, 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 @@ -101,6 +101,7 @@ 2.11 virtual bool is_exception_stub() const { return false; } 2.12 virtual bool is_safepoint_stub() const { return false; } 2.13 virtual bool is_adapter_blob() const { return false; } 2.14 + virtual bool is_vtable_blob() const { return false; } 2.15 virtual bool is_method_handles_adapter_blob() const { return false; } 2.16 2.17 virtual bool is_compiled_by_c2() const { return false; } 2.18 @@ -202,6 +203,7 @@ 2.19 class BufferBlob: public CodeBlob { 2.20 friend class VMStructs; 2.21 friend class AdapterBlob; 2.22 + friend class VtableBlob; 2.23 friend class MethodHandlesAdapterBlob; 2.24 2.25 private: 2.26 @@ -246,6 +248,18 @@ 2.27 virtual bool is_adapter_blob() const { return true; } 2.28 }; 2.29 2.30 +//--------------------------------------------------------------------------------------------------- 2.31 +class VtableBlob: public BufferBlob { 2.32 +private: 2.33 + VtableBlob(const char*, int); 2.34 + 2.35 +public: 2.36 + // Creation 2.37 + static VtableBlob* create(const char* name, int buffer_size); 2.38 + 2.39 + // Typing 2.40 + virtual bool is_vtable_blob() const { return true; } 2.41 +}; 2.42 2.43 //---------------------------------------------------------------------------------------------------- 2.44 // MethodHandlesAdapterBlob: used to hold MethodHandles adapters
3.1 --- a/src/share/vm/code/compiledIC.cpp Wed Mar 21 12:05:05 2018 -0700 3.2 +++ b/src/share/vm/code/compiledIC.cpp Fri Mar 30 20:09:45 2018 +0000 3.3 @@ -1,5 +1,5 @@ 3.4 /* 3.5 - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. 3.6 + * Copyright (c) 1997, 2018, 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 @@ -232,7 +232,7 @@ 3.11 assert(k->verify_itable_index(itable_index), "sanity check"); 3.12 #endif //ASSERT 3.13 CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(), 3.14 - call_info->resolved_klass()()); 3.15 + call_info->resolved_klass()(), false); 3.16 holder->claim(); 3.17 InlineCacheBuffer::create_transition_stub(this, holder, entry); 3.18 } else { 3.19 @@ -270,7 +270,7 @@ 3.20 assert(!is_optimized(), "an optimized call cannot be megamorphic"); 3.21 3.22 // Cannot rely on cached_value. It is either an interface or a method. 3.23 - return VtableStubs::is_entry_point(ic_destination()); 3.24 + return VtableStubs::entry_point(ic_destination()) != NULL; 3.25 } 3.26 3.27 bool CompiledIC::is_call_to_compiled() const { 3.28 @@ -534,9 +534,11 @@ 3.29 return true; 3.30 } 3.31 // itable stubs also use CompiledICHolder 3.32 - if (VtableStubs::is_entry_point(entry) && VtableStubs::stub_containing(entry)->is_itable_stub()) { 3.33 - return true; 3.34 + if (cb != NULL && cb->is_vtable_blob()) { 3.35 + VtableStub* s = VtableStubs::entry_point(entry); 3.36 + return (s != NULL) && s->is_itable_stub(); 3.37 } 3.38 + 3.39 return false; 3.40 } 3.41
4.1 --- a/src/share/vm/code/vtableStubs.cpp Wed Mar 21 12:05:05 2018 -0700 4.2 +++ b/src/share/vm/code/vtableStubs.cpp Fri Mar 30 20:09:45 2018 +0000 4.3 @@ -1,5 +1,5 @@ 4.4 /* 4.5 - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 4.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 4.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.8 * 4.9 * This code is free software; you can redistribute it and/or modify it 4.10 @@ -60,7 +60,7 @@ 4.11 4.12 // There is a dependency on the name of the blob in src/share/vm/prims/jvmtiCodeBlobEvents.cpp 4.13 // If changing the name, update the other file accordingly. 4.14 - BufferBlob* blob = BufferBlob::create("vtable chunks", bytes); 4.15 + VtableBlob* blob = VtableBlob::create("vtable chunks", bytes); 4.16 if (blob == NULL) { 4.17 return NULL; 4.18 } 4.19 @@ -167,17 +167,18 @@ 4.20 _number_of_vtable_stubs++; 4.21 } 4.22 4.23 - 4.24 -bool VtableStubs::is_entry_point(address pc) { 4.25 +VtableStub* VtableStubs::entry_point(address pc) { 4.26 MutexLocker ml(VtableStubs_lock); 4.27 VtableStub* stub = (VtableStub*)(pc - VtableStub::entry_offset()); 4.28 uint hash = VtableStubs::hash(stub->is_vtable_stub(), stub->index()); 4.29 VtableStub* s; 4.30 for (s = _table[hash]; s != NULL && s != stub; s = s->next()) {} 4.31 - return s == stub; 4.32 + if (s == stub) { 4.33 + return s; 4.34 + } 4.35 + return NULL; 4.36 } 4.37 4.38 - 4.39 bool VtableStubs::contains(address pc) { 4.40 // simple solution for now - we may want to use 4.41 // a faster way if this function is called often
5.1 --- a/src/share/vm/code/vtableStubs.hpp Wed Mar 21 12:05:05 2018 -0700 5.2 +++ b/src/share/vm/code/vtableStubs.hpp Fri Mar 30 20:09:45 2018 +0000 5.3 @@ -1,5 +1,5 @@ 5.4 /* 5.5 - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 5.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.8 * 5.9 * This code is free software; you can redistribute it and/or modify it 5.10 @@ -126,7 +126,7 @@ 5.11 public: 5.12 static address find_vtable_stub(int vtable_index) { return find_stub(true, vtable_index); } 5.13 static address find_itable_stub(int itable_index) { return find_stub(false, itable_index); } 5.14 - static bool is_entry_point(address pc); // is pc a vtable stub entry point? 5.15 + static VtableStub* entry_point(address pc); // vtable stub entry point for a pc 5.16 static bool contains(address pc); // is pc within any stub? 5.17 static VtableStub* stub_containing(address pc); // stub containing pc or NULL 5.18 static int number_of_vtable_stubs() { return _number_of_vtable_stubs; }
6.1 --- a/src/share/vm/oops/compiledICHolder.cpp Wed Mar 21 12:05:05 2018 -0700 6.2 +++ b/src/share/vm/oops/compiledICHolder.cpp Fri Mar 30 20:09:45 2018 +0000 6.3 @@ -1,5 +1,5 @@ 6.4 /* 6.5 - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 6.6 + * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. 6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.8 * 6.9 * This code is free software; you can redistribute it and/or modify it 6.10 @@ -24,30 +24,12 @@ 6.11 6.12 #include "precompiled.hpp" 6.13 #include "oops/compiledICHolder.hpp" 6.14 -#include "oops/klass.hpp" 6.15 -#include "oops/method.hpp" 6.16 #include "oops/oop.inline2.hpp" 6.17 6.18 volatile int CompiledICHolder::_live_count; 6.19 volatile int CompiledICHolder::_live_not_claimed_count; 6.20 6.21 6.22 -bool CompiledICHolder::is_loader_alive(BoolObjectClosure* is_alive) { 6.23 - if (_holder_metadata->is_method()) { 6.24 - if (!((Method*)_holder_metadata)->method_holder()->is_loader_alive(is_alive)) { 6.25 - return false; 6.26 - } 6.27 - } else if (_holder_metadata->is_klass()) { 6.28 - if (!((Klass*)_holder_metadata)->is_loader_alive(is_alive)) { 6.29 - return false; 6.30 - } 6.31 - } 6.32 - if (!_holder_klass->is_loader_alive(is_alive)) { 6.33 - return false; 6.34 - } 6.35 - return true; 6.36 -} 6.37 - 6.38 // Printing 6.39 6.40 void CompiledICHolder::print_on(outputStream* st) const {
7.1 --- a/src/share/vm/oops/compiledICHolder.hpp Wed Mar 21 12:05:05 2018 -0700 7.2 +++ b/src/share/vm/oops/compiledICHolder.hpp Fri Mar 30 20:09:45 2018 +0000 7.3 @@ -1,5 +1,5 @@ 7.4 /* 7.5 - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. 7.6 + * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. 7.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.8 * 7.9 * This code is free software; you can redistribute it and/or modify it 7.10 @@ -26,6 +26,8 @@ 7.11 #define SHARE_VM_OOPS_COMPILEDICHOLDEROOP_HPP 7.12 7.13 #include "oops/oop.hpp" 7.14 +#include "oops/klass.hpp" 7.15 +#include "oops/method.hpp" 7.16 7.17 // A CompiledICHolder* is a helper object for the inline cache implementation. 7.18 // It holds: 7.19 @@ -48,11 +50,12 @@ 7.20 Metadata* _holder_metadata; 7.21 Klass* _holder_klass; // to avoid name conflict with oopDesc::_klass 7.22 CompiledICHolder* _next; 7.23 + bool _is_metadata_method; 7.24 7.25 public: 7.26 // Constructor 7.27 - CompiledICHolder(Metadata* metadata, Klass* klass) 7.28 - : _holder_metadata(metadata), _holder_klass(klass) { 7.29 + CompiledICHolder(Metadata* metadata, Klass* klass, bool is_method = true) 7.30 + : _holder_metadata(metadata), _holder_klass(klass), _is_metadata_method(is_method) { 7.31 #ifdef ASSERT 7.32 Atomic::inc(&_live_count); 7.33 Atomic::inc(&_live_not_claimed_count); 7.34 @@ -82,7 +85,16 @@ 7.35 CompiledICHolder* next() { return _next; } 7.36 void set_next(CompiledICHolder* n) { _next = n; } 7.37 7.38 - bool is_loader_alive(BoolObjectClosure* is_alive); 7.39 + inline bool is_loader_alive(BoolObjectClosure* is_alive) { 7.40 + Klass* k = _is_metadata_method ? ((Method*)_holder_metadata)->method_holder() : (Klass*)_holder_metadata; 7.41 + if (!k->is_loader_alive(is_alive)) { 7.42 + return false; 7.43 + } 7.44 + if (!_holder_klass->is_loader_alive(is_alive)) { 7.45 + return false; 7.46 + } 7.47 + return true; 7.48 + } 7.49 7.50 // Verify 7.51 void verify_on(outputStream* st);