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