Mercurial > hg > graal-jvmci-8
comparison src/share/vm/ci/ciMethodData.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | f95d63e2154a |
children | bd7a7ce2e264 |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. | 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. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
21 * questions. | 21 * questions. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "precompiled.hpp" | 25 #include "precompiled.hpp" |
26 #include "ci/ciMetadata.hpp" | |
26 #include "ci/ciMethodData.hpp" | 27 #include "ci/ciMethodData.hpp" |
27 #include "ci/ciUtilities.hpp" | 28 #include "ci/ciUtilities.hpp" |
28 #include "memory/allocation.inline.hpp" | 29 #include "memory/allocation.inline.hpp" |
29 #include "memory/resourceArea.hpp" | 30 #include "memory/resourceArea.hpp" |
30 #include "runtime/deoptimization.hpp" | 31 #include "runtime/deoptimization.hpp" |
33 // ciMethodData | 34 // ciMethodData |
34 | 35 |
35 // ------------------------------------------------------------------ | 36 // ------------------------------------------------------------------ |
36 // ciMethodData::ciMethodData | 37 // ciMethodData::ciMethodData |
37 // | 38 // |
38 ciMethodData::ciMethodData(methodDataHandle h_md) : ciObject(h_md) { | 39 ciMethodData::ciMethodData(MethodData* md) : ciMetadata(md) { |
39 assert(h_md() != NULL, "no null method data"); | 40 assert(md != NULL, "no null method data"); |
40 Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord)); | 41 Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord)); |
41 _data = NULL; | 42 _data = NULL; |
42 _data_size = 0; | 43 _data_size = 0; |
43 _extra_data_size = 0; | 44 _extra_data_size = 0; |
44 _current_mileage = 0; | 45 _current_mileage = 0; |
54 } | 55 } |
55 | 56 |
56 // ------------------------------------------------------------------ | 57 // ------------------------------------------------------------------ |
57 // ciMethodData::ciMethodData | 58 // ciMethodData::ciMethodData |
58 // | 59 // |
59 // No methodDataOop. | 60 // No MethodData*. |
60 ciMethodData::ciMethodData() : ciObject() { | 61 ciMethodData::ciMethodData() : ciMetadata(NULL) { |
61 Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord)); | 62 Copy::zero_to_words((HeapWord*) &_orig, sizeof(_orig) / sizeof(HeapWord)); |
62 _data = NULL; | 63 _data = NULL; |
63 _data_size = 0; | 64 _data_size = 0; |
64 _extra_data_size = 0; | 65 _extra_data_size = 0; |
65 _current_mileage = 0; | 66 _current_mileage = 0; |
73 // Initialize the escape information (to "don't know."); | 74 // Initialize the escape information (to "don't know."); |
74 _eflags = _arg_local = _arg_stack = _arg_returned = 0; | 75 _eflags = _arg_local = _arg_stack = _arg_returned = 0; |
75 } | 76 } |
76 | 77 |
77 void ciMethodData::load_data() { | 78 void ciMethodData::load_data() { |
78 methodDataOop mdo = get_methodDataOop(); | 79 MethodData* mdo = get_MethodData(); |
79 if (mdo == NULL) return; | 80 if (mdo == NULL) return; |
80 | 81 |
81 // To do: don't copy the data if it is not "ripe" -- require a minimum # | 82 // To do: don't copy the data if it is not "ripe" -- require a minimum # |
82 // of invocations. | 83 // of invocations. |
83 | 84 |
84 // Snapshot the data -- actually, take an approximate snapshot of | 85 // Snapshot the data -- actually, take an approximate snapshot of |
85 // the data. Any concurrently executing threads may be changing the | 86 // the data. Any concurrently executing threads may be changing the |
86 // data as we copy it. | 87 // data as we copy it. |
87 int skip_header = oopDesc::header_size(); | 88 Copy::disjoint_words((HeapWord*) mdo, |
88 Copy::disjoint_words((HeapWord*) mdo + skip_header, | 89 (HeapWord*) &_orig, |
89 (HeapWord*) &_orig + skip_header, | 90 sizeof(_orig) / HeapWordSize); |
90 sizeof(_orig) / HeapWordSize - skip_header); | |
91 DEBUG_ONLY(*_orig.adr_method() = NULL); // no dangling oops, please | |
92 Arena* arena = CURRENT_ENV->arena(); | 91 Arena* arena = CURRENT_ENV->arena(); |
93 _data_size = mdo->data_size(); | 92 _data_size = mdo->data_size(); |
94 _extra_data_size = mdo->extra_data_size(); | 93 _extra_data_size = mdo->extra_data_size(); |
95 int total_size = _data_size + _extra_data_size; | 94 int total_size = _data_size + _extra_data_size; |
96 _data = (intptr_t *) arena->Amalloc(total_size); | 95 _data = (intptr_t *) arena->Amalloc(total_size); |
105 ci_data->translate_from(data); | 104 ci_data->translate_from(data); |
106 ci_data = next_data(ci_data); | 105 ci_data = next_data(ci_data); |
107 data = mdo->next_data(data); | 106 data = mdo->next_data(data); |
108 } | 107 } |
109 // Note: Extra data are all BitData, and do not need translation. | 108 // Note: Extra data are all BitData, and do not need translation. |
110 _current_mileage = methodDataOopDesc::mileage_of(mdo->method()); | 109 _current_mileage = MethodData::mileage_of(mdo->method()); |
111 _invocation_counter = mdo->invocation_count(); | 110 _invocation_counter = mdo->invocation_count(); |
112 _backedge_counter = mdo->backedge_count(); | 111 _backedge_counter = mdo->backedge_count(); |
113 _state = mdo->is_mature()? mature_state: immature_state; | 112 _state = mdo->is_mature()? mature_state: immature_state; |
114 | 113 |
115 _eflags = mdo->eflags(); | 114 _eflags = mdo->eflags(); |
118 _arg_returned = mdo->arg_returned(); | 117 _arg_returned = mdo->arg_returned(); |
119 } | 118 } |
120 | 119 |
121 void ciReceiverTypeData::translate_receiver_data_from(ProfileData* data) { | 120 void ciReceiverTypeData::translate_receiver_data_from(ProfileData* data) { |
122 for (uint row = 0; row < row_limit(); row++) { | 121 for (uint row = 0; row < row_limit(); row++) { |
123 klassOop k = data->as_ReceiverTypeData()->receiver(row); | 122 Klass* k = data->as_ReceiverTypeData()->receiver(row); |
124 if (k != NULL) { | 123 if (k != NULL) { |
125 ciKlass* klass = CURRENT_ENV->get_object(k)->as_klass(); | 124 ciKlass* klass = CURRENT_ENV->get_klass(k); |
126 set_receiver(row, klass); | 125 set_receiver(row, klass); |
127 } | 126 } |
128 } | 127 } |
129 } | 128 } |
130 | 129 |
182 } | 181 } |
183 } | 182 } |
184 // bci_to_extra_data(bci) ... | 183 // bci_to_extra_data(bci) ... |
185 DataLayout* dp = data_layout_at(data_size()); | 184 DataLayout* dp = data_layout_at(data_size()); |
186 DataLayout* end = data_layout_at(data_size() + extra_data_size()); | 185 DataLayout* end = data_layout_at(data_size() + extra_data_size()); |
187 for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) { | 186 for (; dp < end; dp = MethodData::next_extra(dp)) { |
188 if (dp->tag() == DataLayout::no_tag) { | 187 if (dp->tag() == DataLayout::no_tag) { |
189 _saw_free_extra_data = true; // observed an empty slot (common case) | 188 _saw_free_extra_data = true; // observed an empty slot (common case) |
190 return NULL; | 189 return NULL; |
191 } | 190 } |
192 if (dp->tag() == DataLayout::arg_info_data_tag) { | 191 if (dp->tag() == DataLayout::arg_info_data_tag) { |
234 } | 233 } |
235 } | 234 } |
236 | 235 |
237 void ciMethodData::clear_escape_info() { | 236 void ciMethodData::clear_escape_info() { |
238 VM_ENTRY_MARK; | 237 VM_ENTRY_MARK; |
239 methodDataOop mdo = get_methodDataOop(); | 238 MethodData* mdo = get_MethodData(); |
240 if (mdo != NULL) { | 239 if (mdo != NULL) { |
241 mdo->clear_escape_info(); | 240 mdo->clear_escape_info(); |
242 ArgInfoData *aid = arg_info(); | 241 ArgInfoData *aid = arg_info(); |
243 int arg_count = (aid == NULL) ? 0 : aid->number_of_args(); | 242 int arg_count = (aid == NULL) ? 0 : aid->number_of_args(); |
244 for (int i = 0; i < arg_count; i++) { | 243 for (int i = 0; i < arg_count; i++) { |
246 } | 245 } |
247 } | 246 } |
248 _eflags = _arg_local = _arg_stack = _arg_returned = 0; | 247 _eflags = _arg_local = _arg_stack = _arg_returned = 0; |
249 } | 248 } |
250 | 249 |
251 // copy our escape info to the methodDataOop if it exists | 250 // copy our escape info to the MethodData* if it exists |
252 void ciMethodData::update_escape_info() { | 251 void ciMethodData::update_escape_info() { |
253 VM_ENTRY_MARK; | 252 VM_ENTRY_MARK; |
254 methodDataOop mdo = get_methodDataOop(); | 253 MethodData* mdo = get_MethodData(); |
255 if ( mdo != NULL) { | 254 if ( mdo != NULL) { |
256 mdo->set_eflags(_eflags); | 255 mdo->set_eflags(_eflags); |
257 mdo->set_arg_local(_arg_local); | 256 mdo->set_arg_local(_arg_local); |
258 mdo->set_arg_stack(_arg_stack); | 257 mdo->set_arg_stack(_arg_stack); |
259 mdo->set_arg_returned(_arg_returned); | 258 mdo->set_arg_returned(_arg_returned); |
264 } | 263 } |
265 } | 264 } |
266 | 265 |
267 void ciMethodData::set_compilation_stats(short loops, short blocks) { | 266 void ciMethodData::set_compilation_stats(short loops, short blocks) { |
268 VM_ENTRY_MARK; | 267 VM_ENTRY_MARK; |
269 methodDataOop mdo = get_methodDataOop(); | 268 MethodData* mdo = get_MethodData(); |
270 if (mdo != NULL) { | 269 if (mdo != NULL) { |
271 mdo->set_num_loops(loops); | 270 mdo->set_num_loops(loops); |
272 mdo->set_num_blocks(blocks); | 271 mdo->set_num_blocks(blocks); |
273 } | 272 } |
274 } | 273 } |
275 | 274 |
276 void ciMethodData::set_would_profile(bool p) { | 275 void ciMethodData::set_would_profile(bool p) { |
277 VM_ENTRY_MARK; | 276 VM_ENTRY_MARK; |
278 methodDataOop mdo = get_methodDataOop(); | 277 MethodData* mdo = get_MethodData(); |
279 if (mdo != NULL) { | 278 if (mdo != NULL) { |
280 mdo->set_would_profile(p); | 279 mdo->set_would_profile(p); |
281 } | 280 } |
282 } | 281 } |
283 | 282 |
284 bool ciMethodData::has_escape_info() { | 283 bool ciMethodData::has_escape_info() { |
285 return eflag_set(methodDataOopDesc::estimated); | 284 return eflag_set(MethodData::estimated); |
286 } | 285 } |
287 | 286 |
288 void ciMethodData::set_eflag(methodDataOopDesc::EscapeFlag f) { | 287 void ciMethodData::set_eflag(MethodData::EscapeFlag f) { |
289 set_bits(_eflags, f); | 288 set_bits(_eflags, f); |
290 } | 289 } |
291 | 290 |
292 void ciMethodData::clear_eflag(methodDataOopDesc::EscapeFlag f) { | 291 void ciMethodData::clear_eflag(MethodData::EscapeFlag f) { |
293 clear_bits(_eflags, f); | 292 clear_bits(_eflags, f); |
294 } | 293 } |
295 | 294 |
296 bool ciMethodData::eflag_set(methodDataOopDesc::EscapeFlag f) const { | 295 bool ciMethodData::eflag_set(MethodData::EscapeFlag f) const { |
297 return mask_bits(_eflags, f) != 0; | 296 return mask_bits(_eflags, f) != 0; |
298 } | 297 } |
299 | 298 |
300 void ciMethodData::set_arg_local(int i) { | 299 void ciMethodData::set_arg_local(int i) { |
301 set_nth_bit(_arg_local, i); | 300 set_nth_bit(_arg_local, i); |
336 assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number"); | 335 assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number"); |
337 return aid->arg_modified(arg); | 336 return aid->arg_modified(arg); |
338 } | 337 } |
339 | 338 |
340 ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) { | 339 ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) { |
341 // Get offset within methodDataOop of the data array | 340 // Get offset within MethodData* of the data array |
342 ByteSize data_offset = methodDataOopDesc::data_offset(); | 341 ByteSize data_offset = MethodData::data_offset(); |
343 | 342 |
344 // Get cell offset of the ProfileData within data array | 343 // Get cell offset of the ProfileData within data array |
345 int cell_offset = dp_to_di(data->dp()); | 344 int cell_offset = dp_to_di(data->dp()); |
346 | 345 |
347 // Add in counter_offset, the # of bytes into the ProfileData of counter or flag | 346 // Add in counter_offset, the # of bytes into the ProfileData of counter or flag |
352 | 351 |
353 ciArgInfoData *ciMethodData::arg_info() const { | 352 ciArgInfoData *ciMethodData::arg_info() const { |
354 // Should be last, have to skip all traps. | 353 // Should be last, have to skip all traps. |
355 DataLayout* dp = data_layout_at(data_size()); | 354 DataLayout* dp = data_layout_at(data_size()); |
356 DataLayout* end = data_layout_at(data_size() + extra_data_size()); | 355 DataLayout* end = data_layout_at(data_size() + extra_data_size()); |
357 for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) { | 356 for (; dp < end; dp = MethodData::next_extra(dp)) { |
358 if (dp->tag() == DataLayout::arg_info_data_tag) | 357 if (dp->tag() == DataLayout::arg_info_data_tag) |
359 return new ciArgInfoData(dp); | 358 return new ciArgInfoData(dp); |
360 } | 359 } |
361 return NULL; | 360 return NULL; |
362 } | 361 } |
363 | 362 |
364 | 363 |
365 // Implementation of the print method. | 364 // Implementation of the print method. |
366 void ciMethodData::print_impl(outputStream* st) { | 365 void ciMethodData::print_impl(outputStream* st) { |
367 ciObject::print_impl(st); | 366 ciMetadata::print_impl(st); |
368 } | 367 } |
369 | 368 |
370 #ifndef PRODUCT | 369 #ifndef PRODUCT |
371 void ciMethodData::print() { | 370 void ciMethodData::print() { |
372 print_data_on(tty); | 371 print_data_on(tty); |
381 data->print_data_on(st); | 380 data->print_data_on(st); |
382 } | 381 } |
383 st->print_cr("--- Extra data:"); | 382 st->print_cr("--- Extra data:"); |
384 DataLayout* dp = data_layout_at(data_size()); | 383 DataLayout* dp = data_layout_at(data_size()); |
385 DataLayout* end = data_layout_at(data_size() + extra_data_size()); | 384 DataLayout* end = data_layout_at(data_size() + extra_data_size()); |
386 for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) { | 385 for (; dp < end; dp = MethodData::next_extra(dp)) { |
387 if (dp->tag() == DataLayout::no_tag) continue; | 386 if (dp->tag() == DataLayout::no_tag) continue; |
388 if (dp->tag() == DataLayout::bit_data_tag) { | 387 if (dp->tag() == DataLayout::bit_data_tag) { |
389 data = new BitData(dp); | 388 data = new BitData(dp); |
390 } else { | 389 } else { |
391 assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); | 390 assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); |