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