1 /* 2 * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_RUNTIME_RUNTIME_UPCALLS_HPP 26 #define SHARE_RUNTIME_RUNTIME_UPCALLS_HPP 27 28 #include "memory/allStatic.hpp" 29 #include "memory/resourceArea.hpp" 30 #include "runtime/methodDetails.hpp" 31 #include "utilities/macros.hpp" 32 33 enum RuntimeUpcallType{ 34 onMethodEntry = 0, // Upcalls triggered on method entry AFTER tracing 35 onMethodExit, // Not implemented yet 36 numTypes 37 }; 38 39 typedef void (*RuntimeUpcall)(JavaThread* current); 40 typedef bool (*RuntimeUpcallMethodFilterCallback)(MethodDetails& method); 41 42 class RuntimeUpcallInfo: public CHeapObj<mtInternal>{ 43 const char* _upcall_name; 44 const RuntimeUpcall _upcall; 45 const RuntimeUpcallMethodFilterCallback _method_filter; 46 address _address; 47 int _index; 48 49 RuntimeUpcallInfo(const char* upcall_name, 50 const RuntimeUpcall upcall, 51 const RuntimeUpcallMethodFilterCallback method_filter) 52 : _upcall_name(upcall_name), 53 _upcall(upcall), 54 _method_filter(method_filter), 55 _index(-1) { 56 _address = CAST_FROM_FN_PTR(address, upcall); 57 } 58 59 private: 60 friend class RuntimeUpcalls; 61 void set_index(const int index) { _index = index; } 62 int get_index() const { assert(_index >= 0, "invalid index"); return _index; } 63 64 public: 65 static RuntimeUpcallInfo* create(const char* upcall_name, const RuntimeUpcall upcall, const RuntimeUpcallMethodFilterCallback method_filter) { 66 assert(upcall_name != nullptr, "upcall name must be provided"); 67 assert(upcall != nullptr, "upcall must be provided"); 68 assert(method_filter != nullptr, "method filter must be provided"); 69 return new RuntimeUpcallInfo(upcall_name, upcall, method_filter); 70 } 71 72 RuntimeUpcall upcall() const { return _upcall; } 73 const char* upcall_name() const { return _upcall_name; } 74 address upcall_address() const { return _address; } 75 76 bool includes(MethodDetails& method_details) const { 77 return _method_filter(method_details); 78 } 79 }; 80 81 class RuntimeUpcalls: AllStatic { 82 private: 83 84 enum State { 85 Uninitialized, 86 Open, 87 Closed 88 }; 89 90 static GrowableArray<RuntimeUpcallInfo*>* _upcalls[RuntimeUpcallType::numTypes]; 91 static State _state; 92 93 static void mark_for_upcalls(RuntimeUpcallType upcall_type, const methodHandle& method); 94 static bool register_upcall(RuntimeUpcallType upcall_type, RuntimeUpcallInfo* info); 95 static void upcall_redirect(RuntimeUpcallType upcall_type, JavaThread* current, Method* method); 96 97 static int get_num_upcalls(RuntimeUpcallType upcall_type); 98 99 static void on_method_entry_upcall_redirect(JavaThread* current, Method* method); 100 static void on_method_exit_upcall_redirect(JavaThread* current, Method* method); 101 102 public: 103 104 static bool open_upcall_registration(); 105 static bool register_upcall(RuntimeUpcallType upcall_type, const char* upcall_name, RuntimeUpcall upcall, RuntimeUpcallMethodFilterCallback method_filter_callback = nullptr); 106 static void close_upcall_registration(); 107 108 static void install_upcalls(const methodHandle& method); 109 110 static RuntimeUpcallInfo* get_first_upcall(RuntimeUpcallType upcall_type, MethodDetails& method_details); 111 static RuntimeUpcallInfo* get_next_upcall(RuntimeUpcallType upcall_type, MethodDetails& method_details, RuntimeUpcallInfo* prev_upcall_info = nullptr); 112 113 static address on_method_entry_upcall_address(); 114 static address on_method_exit_upcall_address(); 115 116 static bool does_upcall_need_method_parameter(address upcall_address); 117 118 static const char* get_name_for_upcall_address(address upcall_address); 119 }; 120 121 #endif // SHARE_RUNTIME_RUNTIME_UPCALLS_HPP