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