1 /*
  2  * Copyright (c) 2020, 2023, 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 #include "precompiled.hpp"
 25 #include "ci/ciMethod.hpp"
 26 #include "compiler/compilerEvent.hpp"
 27 #include "jfr/jfr.hpp"
 28 #include "jfr/jfrEvents.hpp"
 29 #include "jfr/metadata/jfrSerializer.hpp"
 30 #include "runtime/interfaceSupport.inline.hpp"
 31 #include "runtime/javaThread.hpp"
 32 #include "runtime/os.hpp"
 33 #include "runtime/semaphore.inline.hpp"
 34 #include "utilities/growableArray.hpp"
 35 
 36 // Synchronizes access to phases_names.
 37 class PhaseTypeGuard : public StackObj {
 38  private:
 39   static Semaphore _mutex_semaphore;
 40   bool _enabled;
 41  public:
 42   PhaseTypeGuard(bool enabled=true) {
 43     if (enabled) {
 44       _mutex_semaphore.wait();
 45       _enabled = true;
 46     } else {
 47       _enabled = false;
 48     }
 49   }
 50   ~PhaseTypeGuard() {
 51     if (_enabled) {
 52       _mutex_semaphore.signal();
 53     }
 54   }
 55 };
 56 
 57 Semaphore PhaseTypeGuard::_mutex_semaphore(1);
 58 
 59 // Table for mapping compiler phases names to int identifiers.
 60 static GrowableArray<const char*>* cphase_names = nullptr;
 61 
 62 class CompilerPhaseTypeConstant : public JfrSerializer {
 63  public:
 64   void serialize(JfrCheckpointWriter& writer) {
 65     PhaseTypeGuard guard;
 66     assert(cphase_names != nullptr, "invariant");
 67     assert(cphase_names->is_nonempty(), "invariant");
 68     const u4 nof_entries = cphase_names->length();
 69     writer.write_count(nof_entries);
 70     for (u4 i = 0; i < nof_entries; i++) {
 71       writer.write_key(i);
 72       writer.write(cphase_names->at(i));
 73     }
 74   }
 75 };
 76 
 77 static int lookup_phase(const char* cphase_name) {
 78   for (int i = 0; i < cphase_names->length(); i++) {
 79     const char* name = cphase_names->at(i);
 80     if (strcmp(name, cphase_name) == 0) {
 81       return i;
 82     }
 83   }
 84   return -1;
 85 }
 86 
 87 int CompilerEvent::PhaseEvent::get_phase_id(const char* cphase_name, bool may_exist, bool use_strdup, bool sync) {
 88   int index;
 89   bool register_jfr_serializer = false;
 90   {
 91     PhaseTypeGuard guard(sync);
 92     if (cphase_names == nullptr) {
 93       cphase_names = new (mtInternal) GrowableArray<const char*>(100, mtCompiler);
 94       register_jfr_serializer = true;
 95     } else if (may_exist) {
 96       index = lookup_phase(cphase_name);
 97       if (index != -1) {
 98         return index;
 99       }
100     } else {
101       assert((index = lookup_phase(cphase_name)) == -1, "phase name \"%s\" already registered: %d", cphase_name, index);
102     }
103 
104     index = cphase_names->length();
105     cphase_names->append(use_strdup ? os::strdup(cphase_name) : cphase_name);
106   }
107   if (register_jfr_serializer) {
108     JfrSerializer::register_serializer(TYPE_COMPILERPHASETYPE, false, new CompilerPhaseTypeConstant());
109   } else if (Jfr::is_recording()) {
110     // serialize new phase.
111     JfrCheckpointWriter writer;
112     writer.write_type(TYPE_COMPILERPHASETYPE);
113     writer.write_count(1);
114     writer.write_key(index);
115     writer.write(cphase_name);
116   }
117   return index;
118 }
119 
120 // As part of event commit, a Method* is tagged as a function of an epoch.
121 // Epochs evolve during safepoints. To ensure the event is tagged in the correct epoch,
122 // that is, to avoid a race, the thread will participate in the safepoint protocol
123 // by doing the commit while the thread is _thread_in_vm.
124 template <typename EventType>
125 static inline void commit(EventType& event) {
126   JavaThread* thread = JavaThread::current();
127   JavaThreadState state = thread->thread_state();
128   if (state == _thread_in_native) {
129     ThreadInVMfromNative transition(thread);
130     event.commit();
131   } else {
132     assert(state == _thread_in_vm, "coming from wrong thread state %d", state);
133     event.commit();
134   }
135  }
136 
137 void CompilerEvent::CompilationEvent::post(EventCompilation& event, int compile_id, CompilerType compiler_type, Method* method, int compile_level, bool success, bool is_osr, int code_size, int inlined_bytecodes) {
138   event.set_compileId(compile_id);
139   event.set_compiler(compiler_type);
140   event.set_method(method);
141   event.set_compileLevel((short)compile_level);
142   event.set_succeded(success);
143   event.set_isOsr(is_osr);
144   event.set_codeSize(code_size);
145   event.set_inlinedBytes(inlined_bytecodes);
146   commit(event);
147 }
148 
149 void CompilerEvent::CompilationFailureEvent::post(EventCompilationFailure& event, int compile_id, const char* reason) {
150   event.set_compileId(compile_id);
151   event.set_failureMessage(reason);
152   event.commit();
153 }
154 
155 void CompilerEvent::PhaseEvent::post(EventCompilerPhase& event, const Ticks& start_time, int phase, int compile_id, int level) {
156   event.set_starttime(start_time);
157   event.set_phase((u1) phase);
158   event.set_compileId(compile_id);
159   event.set_phaseLevel((short)level);
160   event.commit();
161 }
162 
163 void CompilerEvent::InlineEvent::post(EventCompilerInlining& event, int compile_id, Method* caller, const JfrStructCalleeMethod& callee, bool success, const char* msg, int bci) {
164   event.set_compileId(compile_id);
165   event.set_caller(caller);
166   event.set_callee(callee);
167   event.set_succeeded(success);
168   event.set_message(msg);
169   event.set_bci(bci);
170   commit(event);
171 }
172 
173 void CompilerEvent::InlineEvent::post(EventCompilerInlining& event, int compile_id, Method* caller, Method* callee, bool success, const char* msg, int bci) {
174   JfrStructCalleeMethod callee_struct;
175   callee_struct.set_type(callee->klass_name()->as_utf8());
176   callee_struct.set_name(callee->name()->as_utf8());
177   callee_struct.set_descriptor(callee->signature()->as_utf8());
178   post(event, compile_id, caller, callee_struct, success, msg, bci);
179 }
180 
181 void CompilerEvent::InlineEvent::post(EventCompilerInlining& event, int compile_id, Method* caller, ciMethod* callee, bool success, const char* msg, int bci) {
182   JfrStructCalleeMethod callee_struct;
183   callee_struct.set_type(callee->holder()->name()->as_utf8());
184   callee_struct.set_name(callee->name()->as_utf8());
185   callee_struct.set_descriptor(callee->signature()->as_symbol()->as_utf8());
186   post(event, compile_id, caller, callee_struct, success, msg, bci);
187 }
--- EOF ---