ciMethodData.hpp revision 3602:da91efe96a93
1/*
2 * Copyright (c) 2001, 2012, 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_VM_CI_CIMETHODDATA_HPP
26#define SHARE_VM_CI_CIMETHODDATA_HPP
27
28#include "ci/ciClassList.hpp"
29#include "ci/ciKlass.hpp"
30#include "ci/ciObject.hpp"
31#include "ci/ciUtilities.hpp"
32#include "oops/methodData.hpp"
33#include "oops/oop.inline.hpp"
34
35class ciBitData;
36class ciCounterData;
37class ciJumpData;
38class ciReceiverTypeData;
39class ciRetData;
40class ciBranchData;
41class ciArrayData;
42class ciMultiBranchData;
43class ciArgInfoData;
44
45typedef ProfileData ciProfileData;
46
47class ciBitData : public BitData {
48public:
49  ciBitData(DataLayout* layout) : BitData(layout) {};
50};
51
52class ciCounterData : public CounterData {
53public:
54  ciCounterData(DataLayout* layout) : CounterData(layout) {};
55};
56
57class ciJumpData : public JumpData {
58public:
59  ciJumpData(DataLayout* layout) : JumpData(layout) {};
60};
61
62class ciReceiverTypeData : public ReceiverTypeData {
63public:
64  ciReceiverTypeData(DataLayout* layout) : ReceiverTypeData(layout) {};
65
66  void set_receiver(uint row, ciKlass* recv) {
67    assert((uint)row < row_limit(), "oob");
68    set_intptr_at(receiver0_offset + row * receiver_type_row_cell_count,
69                  (intptr_t) recv);
70  }
71
72  ciKlass* receiver(uint row) {
73    assert((uint)row < row_limit(), "oob");
74    ciKlass* recv = (ciKlass*)intptr_at(receiver0_offset + row * receiver_type_row_cell_count);
75    assert(recv == NULL || recv->is_klass(), "wrong type");
76    return recv;
77  }
78
79  // Copy & translate from oop based ReceiverTypeData
80  virtual void translate_from(ProfileData* data) {
81    translate_receiver_data_from(data);
82  }
83  void translate_receiver_data_from(ProfileData* data);
84#ifndef PRODUCT
85  void print_data_on(outputStream* st);
86  void print_receiver_data_on(outputStream* st);
87#endif
88};
89
90class ciVirtualCallData : public VirtualCallData {
91  // Fake multiple inheritance...  It's a ciReceiverTypeData also.
92  ciReceiverTypeData* rtd_super() { return (ciReceiverTypeData*) this; }
93
94public:
95  ciVirtualCallData(DataLayout* layout) : VirtualCallData(layout) {};
96
97  void set_receiver(uint row, ciKlass* recv) {
98    rtd_super()->set_receiver(row, recv);
99  }
100
101  ciKlass* receiver(uint row) {
102    return rtd_super()->receiver(row);
103  }
104
105  // Copy & translate from oop based VirtualCallData
106  virtual void translate_from(ProfileData* data) {
107    rtd_super()->translate_receiver_data_from(data);
108  }
109#ifndef PRODUCT
110  void print_data_on(outputStream* st);
111#endif
112};
113
114
115class ciRetData : public RetData {
116public:
117  ciRetData(DataLayout* layout) : RetData(layout) {};
118};
119
120class ciBranchData : public BranchData {
121public:
122  ciBranchData(DataLayout* layout) : BranchData(layout) {};
123};
124
125class ciArrayData : public ArrayData {
126public:
127  ciArrayData(DataLayout* layout) : ArrayData(layout) {};
128};
129
130class ciMultiBranchData : public MultiBranchData {
131public:
132  ciMultiBranchData(DataLayout* layout) : MultiBranchData(layout) {};
133};
134
135class ciArgInfoData : public ArgInfoData {
136public:
137  ciArgInfoData(DataLayout* layout) : ArgInfoData(layout) {};
138};
139
140// ciMethodData
141//
142// This class represents a MethodData* in the HotSpot virtual
143// machine.
144
145class ciMethodData : public ciMetadata {
146  CI_PACKAGE_ACCESS
147
148private:
149  // Size in bytes
150  int _data_size;
151  int _extra_data_size;
152
153  // Data entries
154  intptr_t* _data;
155
156  // Cached hint for data_before()
157  int _hint_di;
158
159  // Is data attached?  And is it mature?
160  enum { empty_state, immature_state, mature_state };
161  u_char _state;
162
163  // Set this true if empty extra_data slots are ever witnessed.
164  u_char _saw_free_extra_data;
165
166  // Support for interprocedural escape analysis
167  intx              _eflags;          // flags on escape information
168  intx              _arg_local;       // bit set of non-escaping arguments
169  intx              _arg_stack;       // bit set of stack-allocatable arguments
170  intx              _arg_returned;    // bit set of returned arguments
171
172  // Maturity of the oop when the snapshot is taken.
173  int _current_mileage;
174
175  // These counters hold the age of MDO in tiered. In tiered we can have the same method
176  // running at different compilation levels concurrently. So, in order to precisely measure
177  // its maturity we need separate counters.
178  int _invocation_counter;
179  int _backedge_counter;
180
181  // Coherent snapshot of original header.
182  MethodData _orig;
183
184  ciMethodData(MethodData* md);
185  ciMethodData();
186
187  // Accessors
188  int data_size() const { return _data_size; }
189  int extra_data_size() const { return _extra_data_size; }
190  intptr_t * data() const { return _data; }
191
192  MethodData* get_MethodData() const {
193    return (MethodData*)_metadata;
194  }
195
196  const char* type_string()                      { return "ciMethodData"; }
197
198  void print_impl(outputStream* st);
199
200  DataLayout* data_layout_at(int data_index) const {
201    assert(data_index % sizeof(intptr_t) == 0, "unaligned");
202    return (DataLayout*) (((address)_data) + data_index);
203  }
204
205  bool out_of_bounds(int data_index) {
206    return data_index >= data_size();
207  }
208
209  // hint accessors
210  int      hint_di() const  { return _hint_di; }
211  void set_hint_di(int di)  {
212    assert(!out_of_bounds(di), "hint_di out of bounds");
213    _hint_di = di;
214  }
215  ciProfileData* data_before(int bci) {
216    // avoid SEGV on this edge case
217    if (data_size() == 0)
218      return NULL;
219    int hint = hint_di();
220    if (data_layout_at(hint)->bci() <= bci)
221      return data_at(hint);
222    return first_data();
223  }
224
225
226  // What is the index of the first data entry?
227  int first_di() { return 0; }
228
229  ciArgInfoData *arg_info() const;
230
231public:
232  bool is_method_data() const { return true; }
233
234  void set_mature() { _state = mature_state; }
235
236  bool is_empty()  { return _state == empty_state; }
237  bool is_mature() { return _state == mature_state; }
238
239  int creation_mileage() { return _orig.creation_mileage(); }
240  int current_mileage()  { return _current_mileage; }
241
242  int invocation_count() { return _invocation_counter; }
243  int backedge_count()   { return _backedge_counter;   }
244  // Transfer information about the method to MethodData*.
245  // would_profile means we would like to profile this method,
246  // meaning it's not trivial.
247  void set_would_profile(bool p);
248  // Also set the numer of loops and blocks in the method.
249  // Again, this is used to determine if a method is trivial.
250  void set_compilation_stats(short loops, short blocks);
251
252  void load_data();
253
254  // Convert a dp (data pointer) to a di (data index).
255  int dp_to_di(address dp) {
256    return dp - ((address)_data);
257  }
258
259  // Get the data at an arbitrary (sort of) data index.
260  ciProfileData* data_at(int data_index);
261
262  // Walk through the data in order.
263  ciProfileData* first_data() { return data_at(first_di()); }
264  ciProfileData* next_data(ciProfileData* current);
265  bool is_valid(ciProfileData* current) { return current != NULL; }
266
267  // Get the data at an arbitrary bci, or NULL if there is none.
268  ciProfileData* bci_to_data(int bci);
269  ciProfileData* bci_to_extra_data(int bci, bool create_if_missing);
270
271  uint overflow_trap_count() const {
272    return _orig.overflow_trap_count();
273  }
274  uint overflow_recompile_count() const {
275    return _orig.overflow_recompile_count();
276  }
277  uint decompile_count() const {
278    return _orig.decompile_count();
279  }
280  uint trap_count(int reason) const {
281    return _orig.trap_count(reason);
282  }
283  uint trap_reason_limit() const { return _orig.trap_reason_limit(); }
284  uint trap_count_limit()  const { return _orig.trap_count_limit(); }
285
286  // Helpful query functions that decode trap_state.
287  int has_trap_at(ciProfileData* data, int reason);
288  int has_trap_at(int bci, int reason) {
289    return has_trap_at(bci_to_data(bci), reason);
290  }
291  int trap_recompiled_at(ciProfileData* data);
292  int trap_recompiled_at(int bci) {
293    return trap_recompiled_at(bci_to_data(bci));
294  }
295
296  void clear_escape_info();
297  bool has_escape_info();
298  void update_escape_info();
299
300  void set_eflag(MethodData::EscapeFlag f);
301  void clear_eflag(MethodData::EscapeFlag f);
302  bool eflag_set(MethodData::EscapeFlag f) const;
303
304  void set_arg_local(int i);
305  void set_arg_stack(int i);
306  void set_arg_returned(int i);
307  void set_arg_modified(int arg, uint val);
308
309  bool is_arg_local(int i) const;
310  bool is_arg_stack(int i) const;
311  bool is_arg_returned(int i) const;
312  uint arg_modified(int arg) const;
313
314  // Code generation helper
315  ByteSize offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data);
316  int      byte_offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) { return in_bytes(offset_of_slot(data, slot_offset_in_data)); }
317
318#ifndef PRODUCT
319  // printing support for method data
320  void print();
321  void print_data_on(outputStream* st);
322#endif
323};
324
325#endif // SHARE_VM_CI_CIMETHODDATA_HPP
326