From 34edc7358f733cdf433d0ff50921bcb5a94c5e35 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Sat, 3 Aug 2024 06:21:28 +0000 Subject: [PATCH] 8337396: Cleanup usage of ExternalAddess Co-authored-by: Fei Yang Reviewed-by: vlivanov, adinn --- .../cpu/aarch64/macroAssembler_aarch64.cpp | 8 +- .../cpu/aarch64/stubGenerator_aarch64.cpp | 2 +- .../templateInterpreterGenerator_aarch64.cpp | 12 +-- .../cpu/riscv/macroAssembler_riscv.cpp | 4 +- src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 2 +- .../templateInterpreterGenerator_riscv.cpp | 6 +- src/hotspot/cpu/x86/stubGenerator_x86_64.cpp | 2 +- .../x86/templateInterpreterGenerator_x86.cpp | 6 +- src/hotspot/cpu/x86/templateTable_x86.cpp | 18 ++-- src/hotspot/share/code/oopRecorder.cpp | 92 ++++++++++++++++++- 10 files changed, 117 insertions(+), 35 deletions(-) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index f90aefc8fd3..e210c8b3de0 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -736,7 +736,7 @@ void MacroAssembler::reserved_stack_check() { br(Assembler::LO, no_reserved_zone_enabling); enter(); // LR and FP are live. - lea(rscratch1, CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone)); + lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone))); mov(c_rarg0, rthread); blr(rscratch1); leave(); @@ -1879,7 +1879,7 @@ void MacroAssembler::_verify_oop(Register reg, const char* s, const char* file, movptr(rscratch1, (uintptr_t)(address)b); // call indirectly to solve generation ordering problem - lea(rscratch2, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); + lea(rscratch2, RuntimeAddress(StubRoutines::verify_oop_subroutine_entry_address())); ldr(rscratch2, Address(rscratch2)); blr(rscratch2); @@ -1918,7 +1918,7 @@ void MacroAssembler::_verify_oop_addr(Address addr, const char* s, const char* f movptr(rscratch1, (uintptr_t)(address)b); // call indirectly to solve generation ordering problem - lea(rscratch2, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); + lea(rscratch2, RuntimeAddress(StubRoutines::verify_oop_subroutine_entry_address())); ldr(rscratch2, Address(rscratch2)); blr(rscratch2); @@ -6454,7 +6454,7 @@ void MacroAssembler::verify_cross_modify_fence_not_required() { Label fence_not_required; cbz(rscratch1, fence_not_required); // If it does then fail. - lea(rscratch1, CAST_FROM_FN_PTR(address, JavaThread::verify_cross_modify_fence_failure)); + lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::verify_cross_modify_fence_failure))); mov(c_rarg0, rthread); blr(rscratch1); bind(fence_not_required); diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 3f1a4423b5e..5e2ef97e4a3 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -7045,7 +7045,7 @@ class StubGenerator: public StubCodeGenerator { Label thaw_success; // rscratch2 contains the size of the frames to thaw, 0 if overflow or no more frames __ cbnz(rscratch2, thaw_success); - __ lea(rscratch1, ExternalAddress(StubRoutines::throw_StackOverflowError_entry())); + __ lea(rscratch1, RuntimeAddress(StubRoutines::throw_StackOverflowError_entry())); __ br(rscratch1); __ bind(thaw_success); diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 89f5fbd281b..d639d9cf17e 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1337,8 +1337,8 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { { Label L; __ ldr(r10, Address(rmethod, Method::native_function_offset())); - address unsatisfied = (SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); - __ mov(rscratch2, unsatisfied); + ExternalAddress unsatisfied(SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); + __ lea(rscratch2, unsatisfied); __ ldr(rscratch2, rscratch2); __ cmp(r10, rscratch2); __ br(Assembler::NE, L); @@ -1432,7 +1432,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // hand. // __ mov(c_rarg0, rthread); - __ mov(rscratch2, CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)); + __ lea(rscratch2, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); __ blr(rscratch2); __ get_method(rmethod); __ reinit_heapbase(); @@ -1482,7 +1482,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ push_call_clobbered_registers(); __ mov(c_rarg0, rthread); - __ mov(rscratch2, CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)); + __ lea(rscratch2, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); __ blr(rscratch2); __ pop_call_clobbered_registers(); @@ -2085,7 +2085,7 @@ void TemplateInterpreterGenerator::trace_bytecode(Template* t) { assert(Interpreter::trace_code(t->tos_in()) != nullptr, "entry must have been generated"); - __ bl(Interpreter::trace_code(t->tos_in())); + __ bl(RuntimeAddress(Interpreter::trace_code(t->tos_in()))); __ reinit_heapbase(); } diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index e349eab3177..cd7a4ecf228 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -547,7 +547,7 @@ void MacroAssembler::_verify_oop(Register reg, const char* s, const char* file, } // call indirectly to solve generation ordering problem - ExternalAddress target(StubRoutines::verify_oop_subroutine_entry_address()); + RuntimeAddress target(StubRoutines::verify_oop_subroutine_entry_address()); relocate(target.rspec(), [&] { int32_t offset; la(t1, target.target(), offset); @@ -592,7 +592,7 @@ void MacroAssembler::_verify_oop_addr(Address addr, const char* s, const char* f } // call indirectly to solve generation ordering problem - ExternalAddress target(StubRoutines::verify_oop_subroutine_entry_address()); + RuntimeAddress target(StubRoutines::verify_oop_subroutine_entry_address()); relocate(target.rspec(), [&] { int32_t offset; la(t1, target.target(), offset); diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index f78d7261e40..198835d733f 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -3774,7 +3774,7 @@ class StubGenerator: public StubCodeGenerator { Label thaw_success; // t1 contains the size of the frames to thaw, 0 if overflow or no more frames __ bnez(t1, thaw_success); - __ la(t0, ExternalAddress(StubRoutines::throw_StackOverflowError_entry())); + __ la(t0, RuntimeAddress(StubRoutines::throw_StackOverflowError_entry())); __ jr(t0); __ bind(thaw_success); diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index 769e4dc5ccc..f01945bc6a3 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -1111,8 +1111,8 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { { Label L; __ ld(x28, Address(xmethod, Method::native_function_offset())); - address unsatisfied = (SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); - __ mv(t, unsatisfied); + ExternalAddress unsatisfied(SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); + __ la(t, unsatisfied); __ load_long_misaligned(t1, Address(t, 0), t0, 2); // 2 bytes aligned, but not 4 or 8 __ bne(x28, t1, L); @@ -1815,7 +1815,7 @@ void TemplateInterpreterGenerator::trace_bytecode(Template* t) { // the tosca in-state for the given template. assert(Interpreter::trace_code(t->tos_in()) != nullptr, "entry must have been generated"); - __ call(Interpreter::trace_code(t->tos_in())); + __ rt_call(Interpreter::trace_code(t->tos_in())); __ reinit_heapbase(); } diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index c9c4b056eb5..a7404b298f6 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -3702,7 +3702,7 @@ address StubGenerator::generate_cont_thaw(const char* label, Continuation::thaw_ Label L_thaw_success; __ testptr(rbx, rbx); __ jccb(Assembler::notZero, L_thaw_success); - __ jump(ExternalAddress(StubRoutines::throw_StackOverflowError_entry())); + __ jump(RuntimeAddress(StubRoutines::throw_StackOverflowError_entry())); __ bind(L_thaw_success); // Make room for the thawed frames and align the stack. diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index fe2bf67afc9..3b32d577d44 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -178,7 +178,7 @@ address TemplateInterpreterGenerator::generate_exception_handler_common( rarg, rarg2); } // throw exception - __ jump(ExternalAddress(Interpreter::throw_exception_entry())); + __ jump(RuntimeAddress(Interpreter::throw_exception_entry())); return entry; } @@ -546,7 +546,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(void) { // Note: the restored frame is not necessarily interpreted. // Use the shared runtime version of the StackOverflowError. assert(StubRoutines::throw_StackOverflowError_entry() != nullptr, "stub not yet generated"); - __ jump(ExternalAddress(StubRoutines::throw_StackOverflowError_entry())); + __ jump(RuntimeAddress(StubRoutines::throw_StackOverflowError_entry())); // all done with frame size check __ bind(after_frame_check_pop); NOT_LP64(__ pop(rsi)); diff --git a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp index 6446ec65987..fc6844aedd6 100644 --- a/src/hotspot/cpu/x86/templateTable_x86.cpp +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -774,7 +774,7 @@ void TemplateTable::index_check_without_pop(Register array, Register index) { __ jccb(Assembler::below, skip); // Pass array to create more detailed exceptions. __ mov(NOT_LP64(rax) LP64_ONLY(c_rarg1), array); - __ jump(ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); + __ jump(RuntimeAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); __ bind(skip); } @@ -1152,7 +1152,7 @@ void TemplateTable::aastore() { // Come here on failure // object is at TOS - __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); + __ jump(RuntimeAddress(Interpreter::_throw_ArrayStoreException_entry)); // Come here on success __ bind(ok_is_subtype); @@ -1432,7 +1432,7 @@ void TemplateTable::ldiv() { // generate explicit div0 check __ testq(rcx, rcx); __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + RuntimeAddress(Interpreter::_throw_ArithmeticException_entry)); // Note: could xor rax and rcx and compare with (-1 ^ min_int). If // they are not equal, one could do a normal division (no correction // needed), which may speed up this implementation for the common case. @@ -1445,7 +1445,7 @@ void TemplateTable::ldiv() { // check if y = 0 __ orl(rax, rdx); __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + RuntimeAddress(Interpreter::_throw_ArithmeticException_entry)); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); __ addptr(rsp, 4 * wordSize); // take off temporaries #endif @@ -1458,7 +1458,7 @@ void TemplateTable::lrem() { __ pop_l(rax); __ testq(rcx, rcx); __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + RuntimeAddress(Interpreter::_throw_ArithmeticException_entry)); // Note: could xor rax and rcx and compare with (-1 ^ min_int). If // they are not equal, one could do a normal division (no correction // needed), which may speed up this implementation for the common case. @@ -1472,7 +1472,7 @@ void TemplateTable::lrem() { // check if y = 0 __ orl(rax, rdx); __ jump_cc(Assembler::zero, - ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); + RuntimeAddress(Interpreter::_throw_ArithmeticException_entry)); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); __ addptr(rsp, 4 * wordSize); #endif @@ -4222,7 +4222,7 @@ void TemplateTable::checkcast() { // Come here on failure __ push_ptr(rdx); // object is at TOS - __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry)); + __ jump(RuntimeAddress(Interpreter::_throw_ClassCastException_entry)); // Come here on success __ bind(ok_is_subtype); @@ -4340,7 +4340,7 @@ void TemplateTable::_breakpoint() { void TemplateTable::athrow() { transition(atos, vtos); __ null_check(rax); - __ jump(ExternalAddress(Interpreter::throw_exception_entry())); + __ jump(RuntimeAddress(Interpreter::throw_exception_entry())); } //----------------------------------------------------------------------------- diff --git a/src/hotspot/share/code/oopRecorder.cpp b/src/hotspot/share/code/oopRecorder.cpp index fd13b105041..1849493974c 100644 --- a/src/hotspot/share/code/oopRecorder.cpp +++ b/src/hotspot/share/code/oopRecorder.cpp @@ -32,6 +32,7 @@ #include "oops/oop.inline.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/os.hpp" #include "utilities/copy.hpp" #ifdef ASSERT @@ -220,6 +221,11 @@ ExternalsRecorder* ExternalsRecorder::_recorder = nullptr; ExternalsRecorder::ExternalsRecorder(): _arena(mtCode), _externals(&_arena) {} +#ifndef PRODUCT +static int total_access_count = 0; +static GrowableArray* extern_hist = nullptr; +#endif + void ExternalsRecorder_init() { ExternalsRecorder::initialize(); } @@ -228,30 +234,106 @@ void ExternalsRecorder::initialize() { // After Mutex and before CodeCache are initialized assert(_recorder == nullptr, "should initialize only once"); _recorder = new ExternalsRecorder(); +#ifndef PRODUCT + if (PrintNMethodStatistics) { + Arena* arena = &_recorder->_arena; + extern_hist = new(arena) GrowableArray(arena, 512, 512, 0); + } +#endif } int ExternalsRecorder::find_index(address adr) { - MutexLocker ml(ExternalsRecorder_lock, Mutex::_no_safepoint_check_flag); assert(_recorder != nullptr, "sanity"); - return _recorder->_externals.find_index(adr); + MutexLocker ml(ExternalsRecorder_lock, Mutex::_no_safepoint_check_flag); + int index = _recorder->_externals.find_index(adr); +#ifndef PRODUCT + if (PrintNMethodStatistics) { + total_access_count++; + int n = extern_hist->at_grow(index, 0); + extern_hist->at_put(index, (n + 1)); + } +#endif + return index; } address ExternalsRecorder::at(int index) { + assert(_recorder != nullptr, "sanity"); // find_index() may resize array by reallocating it and freeing old, // we need loock here to make sure we not accessing to old freed array. MutexLocker ml(ExternalsRecorder_lock, Mutex::_no_safepoint_check_flag); - assert(_recorder != nullptr, "sanity"); return _recorder->_externals.at(index); } int ExternalsRecorder::count() { - MutexLocker ml(ExternalsRecorder_lock, Mutex::_no_safepoint_check_flag); assert(_recorder != nullptr, "sanity"); + MutexLocker ml(ExternalsRecorder_lock, Mutex::_no_safepoint_check_flag); return _recorder->_externals.count(); } #ifndef PRODUCT +extern "C" { + // Order from large to small values + static int count_cmp(const void *i, const void *j) { + int a = *(int*)i; + int b = *(int*)j; + return a < b ? 1 : a > b ? -1 : 0; + } +} + void ExternalsRecorder::print_statistics() { - tty->print_cr("External addresses table: %d entries", count()); + int cnt = count(); + tty->print_cr("External addresses table: %d entries, %d accesses", cnt, total_access_count); + { // Print most accessed entries in the table. + int* array = NEW_C_HEAP_ARRAY(int, (2 * cnt), mtCode); + for (int i = 0; i < cnt; i++) { + array[(2 * i) + 0] = extern_hist->at(i); + array[(2 * i) + 1] = i; + } + // Reverse sort to have "hottest" addresses first. + qsort(array, cnt, 2*sizeof(int), count_cmp); + // Print all entries with Verbose flag otherwise only top 5. + int limit = (Verbose || cnt <= 5) ? cnt : 5; + int j = 0; + for (int i = 0; i < limit; i++) { + int index = array[(2 * i) + 1]; + int n = extern_hist->at(index); + if (n > 0) { + address addr = at(index); + tty->print("%d: %8d " INTPTR_FORMAT " :", j++, n, p2i(addr)); + if (addr != nullptr) { + if (StubRoutines::contains(addr)) { + StubCodeDesc* desc = StubCodeDesc::desc_for(addr); + if (desc == nullptr) { + desc = StubCodeDesc::desc_for(addr + frame::pc_return_offset); + } + const char* stub_name = (desc != nullptr) ? desc->name() : ""; + tty->print(" stub: %s", stub_name); + } else { + ResourceMark rm; + const int buflen = 1024; + char* buf = NEW_RESOURCE_ARRAY(char, buflen); + int offset = 0; + if (os::dll_address_to_function_name(addr, buf, buflen, &offset)) { + tty->print(" extn: %s", buf); + if (offset != 0) { + tty->print("+%d", offset); + } + } else { + if (CodeCache::contains((void*)addr)) { + // Something in CodeCache + tty->print(" in CodeCache"); + } else { + // It could be string + memcpy(buf, (char*)addr, 80); + buf[80] = '\0'; + tty->print(" '%s'", buf); + } + } + } + } + tty->cr(); + } + } + } } #endif