|
1 /* |
|
2 * Copyright 2001-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 #include "incls/_precompiled.incl" |
|
26 #include "incls/_ciMethodData.cpp.incl" |
|
27 |
|
28 // ciMethodData |
|
29 |
|
30 // ------------------------------------------------------------------ |
|
31 // ciMethodData::ciMethodData |
|
32 // |
|
33 ciMethodData::ciMethodData(methodDataHandle h_md) : ciObject(h_md) { |
|
34 assert(h_md() != NULL, "no null method data"); |
|
35 Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord)); |
|
36 _data = NULL; |
|
37 _data_size = 0; |
|
38 _extra_data_size = 0; |
|
39 _current_mileage = 0; |
|
40 _state = empty_state; |
|
41 _saw_free_extra_data = false; |
|
42 // Set an initial hint. Don't use set_hint_di() because |
|
43 // first_di() may be out of bounds if data_size is 0. |
|
44 _hint_di = first_di(); |
|
45 } |
|
46 |
|
47 // ------------------------------------------------------------------ |
|
48 // ciMethodData::ciMethodData |
|
49 // |
|
50 // No methodDataOop. |
|
51 ciMethodData::ciMethodData() : ciObject() { |
|
52 Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord)); |
|
53 _data = NULL; |
|
54 _data_size = 0; |
|
55 _extra_data_size = 0; |
|
56 _current_mileage = 0; |
|
57 _state = empty_state; |
|
58 _saw_free_extra_data = false; |
|
59 // Set an initial hint. Don't use set_hint_di() because |
|
60 // first_di() may be out of bounds if data_size is 0. |
|
61 _hint_di = first_di(); |
|
62 } |
|
63 |
|
64 void ciMethodData::load_data() { |
|
65 methodDataOop mdo = get_methodDataOop(); |
|
66 if (mdo == NULL) return; |
|
67 |
|
68 // To do: don't copy the data if it is not "ripe" -- require a minimum # |
|
69 // of invocations. |
|
70 |
|
71 // Snapshot the data -- actually, take an approximate snapshot of |
|
72 // the data. Any concurrently executing threads may be changing the |
|
73 // data as we copy it. |
|
74 int skip_header = oopDesc::header_size(); |
|
75 Copy::disjoint_words((HeapWord*) mdo + skip_header, |
|
76 (HeapWord*) &_orig + skip_header, |
|
77 sizeof(_orig) / HeapWordSize - skip_header); |
|
78 DEBUG_ONLY(*_orig.adr_method() = NULL); // no dangling oops, please |
|
79 Arena* arena = CURRENT_ENV->arena(); |
|
80 _data_size = mdo->data_size(); |
|
81 _extra_data_size = mdo->extra_data_size(); |
|
82 int total_size = _data_size + _extra_data_size; |
|
83 _data = (intptr_t *) arena->Amalloc(total_size); |
|
84 Copy::disjoint_words((HeapWord*) mdo->data_base(), (HeapWord*) _data, total_size / HeapWordSize); |
|
85 |
|
86 // Traverse the profile data, translating any oops into their |
|
87 // ci equivalents. |
|
88 ResourceMark rm; |
|
89 ciProfileData* ci_data = first_data(); |
|
90 ProfileData* data = mdo->first_data(); |
|
91 while (is_valid(ci_data)) { |
|
92 ci_data->translate_from(data); |
|
93 ci_data = next_data(ci_data); |
|
94 data = mdo->next_data(data); |
|
95 } |
|
96 // Note: Extra data are all BitData, and do not need translation. |
|
97 _current_mileage = methodDataOopDesc::mileage_of(mdo->method()); |
|
98 _state = mdo->is_mature()? mature_state: immature_state; |
|
99 |
|
100 _eflags = mdo->eflags(); |
|
101 _arg_local = mdo->arg_local(); |
|
102 _arg_stack = mdo->arg_stack(); |
|
103 _arg_returned = mdo->arg_returned(); |
|
104 } |
|
105 |
|
106 void ciReceiverTypeData::translate_receiver_data_from(ProfileData* data) { |
|
107 for (uint row = 0; row < row_limit(); row++) { |
|
108 klassOop k = data->as_ReceiverTypeData()->receiver(row); |
|
109 if (k != NULL) { |
|
110 ciKlass* klass = CURRENT_ENV->get_object(k)->as_klass(); |
|
111 set_receiver(row, klass); |
|
112 } |
|
113 } |
|
114 } |
|
115 |
|
116 |
|
117 // Get the data at an arbitrary (sort of) data index. |
|
118 ciProfileData* ciMethodData::data_at(int data_index) { |
|
119 if (out_of_bounds(data_index)) { |
|
120 return NULL; |
|
121 } |
|
122 DataLayout* data_layout = data_layout_at(data_index); |
|
123 |
|
124 switch (data_layout->tag()) { |
|
125 case DataLayout::no_tag: |
|
126 default: |
|
127 ShouldNotReachHere(); |
|
128 return NULL; |
|
129 case DataLayout::bit_data_tag: |
|
130 return new ciBitData(data_layout); |
|
131 case DataLayout::counter_data_tag: |
|
132 return new ciCounterData(data_layout); |
|
133 case DataLayout::jump_data_tag: |
|
134 return new ciJumpData(data_layout); |
|
135 case DataLayout::receiver_type_data_tag: |
|
136 return new ciReceiverTypeData(data_layout); |
|
137 case DataLayout::virtual_call_data_tag: |
|
138 return new ciVirtualCallData(data_layout); |
|
139 case DataLayout::ret_data_tag: |
|
140 return new ciRetData(data_layout); |
|
141 case DataLayout::branch_data_tag: |
|
142 return new ciBranchData(data_layout); |
|
143 case DataLayout::multi_branch_data_tag: |
|
144 return new ciMultiBranchData(data_layout); |
|
145 }; |
|
146 } |
|
147 |
|
148 // Iteration over data. |
|
149 ciProfileData* ciMethodData::next_data(ciProfileData* current) { |
|
150 int current_index = dp_to_di(current->dp()); |
|
151 int next_index = current_index + current->size_in_bytes(); |
|
152 ciProfileData* next = data_at(next_index); |
|
153 return next; |
|
154 } |
|
155 |
|
156 // Translate a bci to its corresponding data, or NULL. |
|
157 ciProfileData* ciMethodData::bci_to_data(int bci) { |
|
158 ciProfileData* data = data_before(bci); |
|
159 for ( ; is_valid(data); data = next_data(data)) { |
|
160 if (data->bci() == bci) { |
|
161 set_hint_di(dp_to_di(data->dp())); |
|
162 return data; |
|
163 } else if (data->bci() > bci) { |
|
164 break; |
|
165 } |
|
166 } |
|
167 // bci_to_extra_data(bci) ... |
|
168 DataLayout* dp = data_layout_at(data_size()); |
|
169 DataLayout* end = data_layout_at(data_size() + extra_data_size()); |
|
170 for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) { |
|
171 if (dp->tag() == DataLayout::no_tag) { |
|
172 _saw_free_extra_data = true; // observed an empty slot (common case) |
|
173 return NULL; |
|
174 } |
|
175 if (dp->bci() == bci) { |
|
176 assert(dp->tag() == DataLayout::bit_data_tag, "sane"); |
|
177 return new ciBitData(dp); |
|
178 } |
|
179 } |
|
180 return NULL; |
|
181 } |
|
182 |
|
183 // Conservatively decode the trap_state of a ciProfileData. |
|
184 int ciMethodData::has_trap_at(ciProfileData* data, int reason) { |
|
185 typedef Deoptimization::DeoptReason DR_t; |
|
186 int per_bc_reason |
|
187 = Deoptimization::reason_recorded_per_bytecode_if_any((DR_t) reason); |
|
188 if (trap_count(reason) == 0) { |
|
189 // Impossible for this trap to have occurred, regardless of trap_state. |
|
190 // Note: This happens if the MDO is empty. |
|
191 return 0; |
|
192 } else if (per_bc_reason == Deoptimization::Reason_none) { |
|
193 // We cannot conclude anything; a trap happened somewhere, maybe here. |
|
194 return -1; |
|
195 } else if (data == NULL) { |
|
196 // No profile here, not even an extra_data record allocated on the fly. |
|
197 // If there are empty extra_data records, and there had been a trap, |
|
198 // there would have been a non-null data pointer. If there are no |
|
199 // free extra_data records, we must return a conservative -1. |
|
200 if (_saw_free_extra_data) |
|
201 return 0; // Q.E.D. |
|
202 else |
|
203 return -1; // bail with a conservative answer |
|
204 } else { |
|
205 return Deoptimization::trap_state_has_reason(data->trap_state(), per_bc_reason); |
|
206 } |
|
207 } |
|
208 |
|
209 int ciMethodData::trap_recompiled_at(ciProfileData* data) { |
|
210 if (data == NULL) { |
|
211 return (_saw_free_extra_data? 0: -1); // (see previous method) |
|
212 } else { |
|
213 return Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0; |
|
214 } |
|
215 } |
|
216 |
|
217 void ciMethodData::clear_escape_info() { |
|
218 VM_ENTRY_MARK; |
|
219 methodDataOop mdo = get_methodDataOop(); |
|
220 if (mdo != NULL) |
|
221 mdo->clear_escape_info(); |
|
222 _eflags = _arg_local = _arg_stack = _arg_returned = 0; |
|
223 } |
|
224 |
|
225 // copy our escape info to the methodDataOop if it exists |
|
226 void ciMethodData::update_escape_info() { |
|
227 VM_ENTRY_MARK; |
|
228 methodDataOop mdo = get_methodDataOop(); |
|
229 if ( mdo != NULL) { |
|
230 mdo->set_eflags(_eflags); |
|
231 mdo->set_arg_local(_arg_local); |
|
232 mdo->set_arg_stack(_arg_stack); |
|
233 mdo->set_arg_returned(_arg_returned); |
|
234 } |
|
235 } |
|
236 |
|
237 bool ciMethodData::has_escape_info() { |
|
238 return eflag_set(methodDataOopDesc::estimated); |
|
239 } |
|
240 |
|
241 void ciMethodData::set_eflag(methodDataOopDesc::EscapeFlag f) { |
|
242 set_bits(_eflags, f); |
|
243 } |
|
244 |
|
245 void ciMethodData::clear_eflag(methodDataOopDesc::EscapeFlag f) { |
|
246 clear_bits(_eflags, f); |
|
247 } |
|
248 |
|
249 bool ciMethodData::eflag_set(methodDataOopDesc::EscapeFlag f) const { |
|
250 return mask_bits(_eflags, f) != 0; |
|
251 } |
|
252 |
|
253 void ciMethodData::set_arg_local(int i) { |
|
254 set_nth_bit(_arg_local, i); |
|
255 } |
|
256 |
|
257 void ciMethodData::set_arg_stack(int i) { |
|
258 set_nth_bit(_arg_stack, i); |
|
259 } |
|
260 |
|
261 void ciMethodData::set_arg_returned(int i) { |
|
262 set_nth_bit(_arg_returned, i); |
|
263 } |
|
264 |
|
265 bool ciMethodData::is_arg_local(int i) const { |
|
266 return is_set_nth_bit(_arg_local, i); |
|
267 } |
|
268 |
|
269 bool ciMethodData::is_arg_stack(int i) const { |
|
270 return is_set_nth_bit(_arg_stack, i); |
|
271 } |
|
272 |
|
273 bool ciMethodData::is_arg_returned(int i) const { |
|
274 return is_set_nth_bit(_arg_returned, i); |
|
275 } |
|
276 |
|
277 ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) { |
|
278 // Get offset within methodDataOop of the data array |
|
279 ByteSize data_offset = methodDataOopDesc::data_offset(); |
|
280 |
|
281 // Get cell offset of the ProfileData within data array |
|
282 int cell_offset = dp_to_di(data->dp()); |
|
283 |
|
284 // Add in counter_offset, the # of bytes into the ProfileData of counter or flag |
|
285 int offset = in_bytes(data_offset) + cell_offset + in_bytes(slot_offset_in_data); |
|
286 |
|
287 return in_ByteSize(offset); |
|
288 } |
|
289 |
|
290 // Implementation of the print method. |
|
291 void ciMethodData::print_impl(outputStream* st) { |
|
292 ciObject::print_impl(st); |
|
293 } |
|
294 |
|
295 #ifndef PRODUCT |
|
296 void ciMethodData::print() { |
|
297 print_data_on(tty); |
|
298 } |
|
299 |
|
300 void ciMethodData::print_data_on(outputStream* st) { |
|
301 ResourceMark rm; |
|
302 ciProfileData* data; |
|
303 for (data = first_data(); is_valid(data); data = next_data(data)) { |
|
304 st->print("%d", dp_to_di(data->dp())); |
|
305 st->fill_to(6); |
|
306 data->print_data_on(st); |
|
307 } |
|
308 } |
|
309 |
|
310 void ciReceiverTypeData::print_receiver_data_on(outputStream* st) { |
|
311 uint row; |
|
312 int entries = 0; |
|
313 for (row = 0; row < row_limit(); row++) { |
|
314 if (receiver(row) != NULL) entries++; |
|
315 } |
|
316 st->print_cr("count(%u) entries(%u)", count(), entries); |
|
317 for (row = 0; row < row_limit(); row++) { |
|
318 if (receiver(row) != NULL) { |
|
319 tab(st); |
|
320 receiver(row)->print_name_on(st); |
|
321 st->print_cr("(%u)", receiver_count(row)); |
|
322 } |
|
323 } |
|
324 } |
|
325 |
|
326 void ciReceiverTypeData::print_data_on(outputStream* st) { |
|
327 print_shared(st, "ciReceiverTypeData"); |
|
328 print_receiver_data_on(st); |
|
329 } |
|
330 |
|
331 void ciVirtualCallData::print_data_on(outputStream* st) { |
|
332 print_shared(st, "ciVirtualCallData"); |
|
333 rtd_super()->print_receiver_data_on(st); |
|
334 } |
|
335 #endif |