1 /*
  2  * Copyright (c) 2011, 2020, 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 #include "precompiled.hpp"
 26 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
 27 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
 28 #include "jfr/recorder/repository/jfrChunkWriter.hpp"
 29 #include "jfr/recorder/stacktrace/jfrStackTrace.hpp"
 30 #include "jfr/support/jfrMethodLookup.hpp"
 31 #include "memory/allocation.inline.hpp"
 32 #include "oops/instanceKlass.inline.hpp"
 33 #include "runtime/vframe.inline.hpp"
 34 
 35 static void copy_frames(JfrStackFrame** lhs_frames, u4 length, const JfrStackFrame* rhs_frames) {
 36   assert(lhs_frames != NULL, "invariant");
 37   assert(rhs_frames != NULL, "invariant");
 38   if (length > 0) {
 39     *lhs_frames = NEW_C_HEAP_ARRAY(JfrStackFrame, length, mtTracing);
 40     memcpy(*lhs_frames, rhs_frames, length * sizeof(JfrStackFrame));
 41   }
 42 }
 43 
 44 JfrStackFrame::JfrStackFrame(const traceid& id, int bci, int type, const InstanceKlass* ik) :
 45   _klass(ik), _methodid(id), _line(0), _bci(bci), _type(type) {}
 46 
 47 JfrStackFrame::JfrStackFrame(const traceid& id, int bci, int type, int lineno, const InstanceKlass* ik) :
 48   _klass(ik), _methodid(id), _line(lineno), _bci(bci), _type(type) {}
 49 
 50 JfrStackTrace::JfrStackTrace(JfrStackFrame* frames, u4 max_frames) :
 51   _next(NULL),
 52   _frames(frames),
 53   _id(0),
 54   _hash(0),
 55   _nr_of_frames(0),
 56   _max_frames(max_frames),
 57   _frames_ownership(false),
 58   _reached_root(false),
 59   _lineno(false),
 60   _written(false) {}
 61 
 62 JfrStackTrace::JfrStackTrace(traceid id, const JfrStackTrace& trace, const JfrStackTrace* next) :
 63   _next(next),
 64   _frames(NULL),
 65   _id(id),
 66   _hash(trace._hash),
 67   _nr_of_frames(trace._nr_of_frames),
 68   _max_frames(trace._max_frames),
 69   _frames_ownership(true),
 70   _reached_root(trace._reached_root),
 71   _lineno(trace._lineno),
 72   _written(false) {
 73   copy_frames(&_frames, trace._nr_of_frames, trace._frames);
 74 }
 75 
 76 JfrStackTrace::~JfrStackTrace() {
 77   if (_frames_ownership) {
 78     FREE_C_HEAP_ARRAY(JfrStackFrame, _frames);
 79   }
 80 }
 81 
 82 template <typename Writer>
 83 static void write_stacktrace(Writer& w, traceid id, bool reached_root, u4 nr_of_frames, const JfrStackFrame* frames) {
 84   w.write((u8)id);
 85   w.write((u1)!reached_root);
 86   w.write(nr_of_frames);
 87   for (u4 i = 0; i < nr_of_frames; ++i) {
 88     frames[i].write(w);
 89   }
 90 }
 91 
 92 void JfrStackTrace::write(JfrChunkWriter& sw) const {
 93   assert(!_written, "invariant");
 94   write_stacktrace(sw, _id, _reached_root, _nr_of_frames, _frames);
 95   _written = true;
 96 }
 97 
 98 void JfrStackTrace::write(JfrCheckpointWriter& cpw) const {
 99   write_stacktrace(cpw, _id, _reached_root, _nr_of_frames, _frames);
100 }
101 
102 bool JfrStackFrame::equals(const JfrStackFrame& rhs) const {
103   return _methodid == rhs._methodid && _bci == rhs._bci && _type == rhs._type;
104 }
105 
106 bool JfrStackTrace::equals(const JfrStackTrace& rhs) const {
107   if (_reached_root != rhs._reached_root || _nr_of_frames != rhs._nr_of_frames || _hash != rhs._hash) {
108     return false;
109   }
110   for (u4 i = 0; i < _nr_of_frames; ++i) {
111     if (!_frames[i].equals(rhs._frames[i])) {
112       return false;
113     }
114   }
115   return true;
116 }
117 
118 template <typename Writer>
119 static void write_frame(Writer& w, traceid methodid, int line, int bci, u1 type) {
120   w.write((u8)methodid);
121   w.write((u4)line);
122   w.write((u4)bci);
123   w.write((u8)type);
124 }
125 
126 void JfrStackFrame::write(JfrChunkWriter& cw) const {
127   write_frame(cw, _methodid, _line, _bci, _type);
128 }
129 
130 void JfrStackFrame::write(JfrCheckpointWriter& cpw) const {
131   write_frame(cpw, _methodid, _line, _bci, _type);
132 }
133 
134 class vframeStreamSamples : public vframeStreamCommon {
135  public:
136   // constructor that starts with sender of frame fr (top_frame)
137   vframeStreamSamples(JavaThread *jt, frame fr, bool stop_at_java_call_stub) : vframeStreamCommon(jt, false /* process_frames */) {
138     _stop_at_java_call_stub = stop_at_java_call_stub;
139     _frame = fr;
140 
141     // We must always have a valid frame to start filling
142     bool filled_in = fill_from_frame();
143     assert(filled_in, "invariant");
144   }
145   void samples_next();
146   void stop() {}
147 };
148 
149 // Solaris SPARC Compiler1 needs an additional check on the grandparent
150 // of the top_frame when the parent of the top_frame is interpreted and
151 // the grandparent is compiled. However, in this method we do not know
152 // the relationship of the current _frame relative to the top_frame so
153 // we implement a more broad sanity check. When the previous callee is
154 // interpreted and the current sender is compiled, we verify that the
155 // current sender is also walkable. If it is not walkable, then we mark
156 // the current vframeStream as at the end.
157 void vframeStreamSamples::samples_next() {
158   // handle frames with inlining
159   if (_mode == compiled_mode &&
160     vframeStreamCommon::fill_in_compiled_inlined_sender()) {
161     return;
162   }
163 
164   // handle general case
165   u4 loop_count = 0;
166   u4 loop_max = MAX_STACK_DEPTH * 2;
167   do {
168     loop_count++;
169     // By the time we get here we should never see unsafe but better safe then segv'd
170     if (loop_count > loop_max || !_frame.safe_for_sender(_thread)) {
171       _mode = at_end_mode;
172       return;
173     }
174     _frame = _frame.sender(&_reg_map);
175   } while (!fill_from_frame());
176 }
177 
178 bool JfrStackTrace::record_thread(JavaThread& thread, frame& frame) {
179   vframeStreamSamples st(&thread, frame, false);
180   u4 count = 0;
181   _reached_root = true;
182 
183   _hash = 1;
184   while (!st.at_end()) {
185     if (count >= _max_frames) {
186       _reached_root = false;
187       break;
188     }
189     const Method* method = st.method();
190     if (!Method::is_valid_method(method)) {
191       // we throw away everything we've gathered in this sample since
192       // none of it is safe
193       return false;
194     }
195     const traceid mid = JfrTraceId::load(method);
196     int type = st.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
197     int bci = 0;
198     if (method->is_native()) {
199       type = JfrStackFrame::FRAME_NATIVE;
200     } else {
201       bci = st.bci();
202     }
203 
204     intptr_t* frame_id = st.frame_id();
205     st.samples_next();
206     if (type == JfrStackFrame::FRAME_JIT && !st.at_end() && frame_id == st.frame_id()) {
207       // This frame and the caller frame are both the same physical
208       // frame, so this frame is inlined into the caller.
209       type = JfrStackFrame::FRAME_INLINE;
210     }
211 
212     const int lineno = method->line_number_from_bci(bci);
213     _hash = (_hash * 31) + mid;
214     _hash = (_hash * 31) + bci;
215     _hash = (_hash * 31) + type;
216     _frames[count] = JfrStackFrame(mid, bci, type, lineno, method->method_holder());
217     count++;
218   }
219 
220   _lineno = true;
221   _nr_of_frames = count;
222   return true;
223 }
224 
225 void JfrStackFrame::resolve_lineno() const {
226   assert(_klass, "no klass pointer");
227   assert(_line == 0, "already have linenumber");
228   const Method* const method = JfrMethodLookup::lookup(_klass, _methodid);
229   assert(method != NULL, "invariant");
230   assert(method->method_holder() == _klass, "invariant");
231   _line = method->line_number_from_bci(_bci);
232 }
233 
234 void JfrStackTrace::resolve_linenos() const {
235   for (unsigned int i = 0; i < _nr_of_frames; i++) {
236     _frames[i].resolve_lineno();
237   }
238   _lineno = true;
239 }
240 
241 bool JfrStackTrace::record_safe(JavaThread* thread, int skip) {
242   assert(thread == Thread::current(), "Thread stack needs to be walkable");
243   vframeStream vfs(thread, false /* stop_at_java_call_stub */, false /* process_frames */);
244   u4 count = 0;
245   _reached_root = true;
246   for (int i = 0; i < skip; i++) {
247     if (vfs.at_end()) {
248       break;
249     }
250     vfs.next();
251   }
252 
253   _hash = 1;
254   while (!vfs.at_end()) {
255     if (count >= _max_frames) {
256       _reached_root = false;
257       break;
258     }
259     const Method* method = vfs.method();
260     const traceid mid = JfrTraceId::load(method);
261     int type = vfs.is_interpreted_frame() ? JfrStackFrame::FRAME_INTERPRETER : JfrStackFrame::FRAME_JIT;
262     int bci = 0;
263     if (method->is_native()) {
264       type = JfrStackFrame::FRAME_NATIVE;
265     }
266     else {
267       bci = vfs.bci();
268     }
269     intptr_t* frame_id = vfs.frame_id();
270     vfs.next();
271     if (type == JfrStackFrame::FRAME_JIT && !vfs.at_end() && frame_id == vfs.frame_id()) {
272       // This frame and the caller frame are both the same physical
273       // frame, so this frame is inlined into the caller.
274       type = JfrStackFrame::FRAME_INLINE;
275     }
276 
277     _hash = (_hash * 31) + mid;
278     _hash = (_hash * 31) + bci;
279     _hash = (_hash * 31) + type;
280     _frames[count] = JfrStackFrame(mid, bci, type, method->method_holder());
281     count++;
282   }
283 
284   _nr_of_frames = count;
285   return true;
286 }
287