Tue, 25 Feb 2014 18:16:24 +0100
8031752: Failed speculative optimizations should be reattempted when root of compilation is different
Summary: support for speculative traps that keep track of the root of the compilation in which a trap occurs.
Reviewed-by: kvn, twisti
1.1 --- a/src/share/vm/ci/ciClassList.hpp Mon Jan 27 13:14:53 2014 +0100 1.2 +++ b/src/share/vm/ci/ciClassList.hpp Tue Feb 25 18:16:24 2014 +0100 1.3 @@ -103,6 +103,7 @@ 1.4 friend class ciMethodType; \ 1.5 friend class ciReceiverTypeData; \ 1.6 friend class ciTypeEntries; \ 1.7 +friend class ciSpeculativeTrapData; \ 1.8 friend class ciSymbol; \ 1.9 friend class ciArray; \ 1.10 friend class ciObjArray; \
2.1 --- a/src/share/vm/ci/ciMethodData.cpp Mon Jan 27 13:14:53 2014 +0100 2.2 +++ b/src/share/vm/ci/ciMethodData.cpp Tue Feb 25 18:16:24 2014 +0100 2.3 @@ -78,6 +78,35 @@ 2.4 _parameters = NULL; 2.5 } 2.6 2.7 +void ciMethodData::load_extra_data() { 2.8 + MethodData* mdo = get_MethodData(); 2.9 + 2.10 + // speculative trap entries also hold a pointer to a Method so need to be translated 2.11 + DataLayout* dp_src = mdo->extra_data_base(); 2.12 + DataLayout* end_src = mdo->extra_data_limit(); 2.13 + DataLayout* dp_dst = extra_data_base(); 2.14 + for (;; dp_src = MethodData::next_extra(dp_src), dp_dst = MethodData::next_extra(dp_dst)) { 2.15 + assert(dp_src < end_src, "moved past end of extra data"); 2.16 + assert(dp_src->tag() == dp_dst->tag(), err_msg("should be same tags %d != %d", dp_src->tag(), dp_dst->tag())); 2.17 + switch(dp_src->tag()) { 2.18 + case DataLayout::speculative_trap_data_tag: { 2.19 + ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst); 2.20 + SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src); 2.21 + data_dst->translate_from(data_src); 2.22 + break; 2.23 + } 2.24 + case DataLayout::bit_data_tag: 2.25 + break; 2.26 + case DataLayout::no_tag: 2.27 + case DataLayout::arg_info_data_tag: 2.28 + // An empty slot or ArgInfoData entry marks the end of the trap data 2.29 + return; 2.30 + default: 2.31 + fatal(err_msg("bad tag = %d", dp_src->tag())); 2.32 + } 2.33 + } 2.34 +} 2.35 + 2.36 void ciMethodData::load_data() { 2.37 MethodData* mdo = get_MethodData(); 2.38 if (mdo == NULL) { 2.39 @@ -116,6 +145,8 @@ 2.40 parameters->translate_from(mdo->parameters_type_data()); 2.41 } 2.42 2.43 + load_extra_data(); 2.44 + 2.45 // Note: Extra data are all BitData, and do not need translation. 2.46 _current_mileage = MethodData::mileage_of(mdo->method()); 2.47 _invocation_counter = mdo->invocation_count(); 2.48 @@ -156,6 +187,12 @@ 2.49 set_type(translate_klass(k)); 2.50 } 2.51 2.52 +void ciSpeculativeTrapData::translate_from(const ProfileData* data) { 2.53 + Method* m = data->as_SpeculativeTrapData()->method(); 2.54 + ciMethod* ci_m = CURRENT_ENV->get_method(m); 2.55 + set_method(ci_m); 2.56 +} 2.57 + 2.58 // Get the data at an arbitrary (sort of) data index. 2.59 ciProfileData* ciMethodData::data_at(int data_index) { 2.60 if (out_of_bounds(data_index)) { 2.61 @@ -203,33 +240,65 @@ 2.62 return next; 2.63 } 2.64 2.65 -// Translate a bci to its corresponding data, or NULL. 2.66 -ciProfileData* ciMethodData::bci_to_data(int bci) { 2.67 - ciProfileData* data = data_before(bci); 2.68 - for ( ; is_valid(data); data = next_data(data)) { 2.69 - if (data->bci() == bci) { 2.70 - set_hint_di(dp_to_di(data->dp())); 2.71 - return data; 2.72 - } else if (data->bci() > bci) { 2.73 - break; 2.74 - } 2.75 - } 2.76 +ciProfileData* ciMethodData::bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots) { 2.77 // bci_to_extra_data(bci) ... 2.78 DataLayout* dp = data_layout_at(data_size()); 2.79 DataLayout* end = data_layout_at(data_size() + extra_data_size()); 2.80 - for (; dp < end; dp = MethodData::next_extra(dp)) { 2.81 - if (dp->tag() == DataLayout::no_tag) { 2.82 + two_free_slots = false; 2.83 + for (;dp < end; dp = MethodData::next_extra(dp)) { 2.84 + switch(dp->tag()) { 2.85 + case DataLayout::no_tag: 2.86 _saw_free_extra_data = true; // observed an empty slot (common case) 2.87 + two_free_slots = (MethodData::next_extra(dp)->tag() == DataLayout::no_tag); 2.88 return NULL; 2.89 + case DataLayout::arg_info_data_tag: 2.90 + return NULL; // ArgInfoData is at the end of extra data section. 2.91 + case DataLayout::bit_data_tag: 2.92 + if (m == NULL && dp->bci() == bci) { 2.93 + return new ciBitData(dp); 2.94 + } 2.95 + break; 2.96 + case DataLayout::speculative_trap_data_tag: { 2.97 + ciSpeculativeTrapData* data = new ciSpeculativeTrapData(dp); 2.98 + // data->method() might be null if the MDO is snapshotted 2.99 + // concurrently with a trap 2.100 + if (m != NULL && data->method() == m && dp->bci() == bci) { 2.101 + return data; 2.102 + } 2.103 + break; 2.104 } 2.105 - if (dp->tag() == DataLayout::arg_info_data_tag) { 2.106 - break; // ArgInfoData is at the end of extra data section. 2.107 + default: 2.108 + fatal(err_msg("bad tag = %d", dp->tag())); 2.109 } 2.110 - if (dp->bci() == bci) { 2.111 - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); 2.112 - return new ciBitData(dp); 2.113 + } 2.114 + return NULL; 2.115 +} 2.116 + 2.117 +// Translate a bci to its corresponding data, or NULL. 2.118 +ciProfileData* ciMethodData::bci_to_data(int bci, ciMethod* m) { 2.119 + // If m is not NULL we look for a SpeculativeTrapData entry 2.120 + if (m == NULL) { 2.121 + ciProfileData* data = data_before(bci); 2.122 + for ( ; is_valid(data); data = next_data(data)) { 2.123 + if (data->bci() == bci) { 2.124 + set_hint_di(dp_to_di(data->dp())); 2.125 + return data; 2.126 + } else if (data->bci() > bci) { 2.127 + break; 2.128 + } 2.129 } 2.130 } 2.131 + bool two_free_slots = false; 2.132 + ciProfileData* result = bci_to_extra_data(bci, m, two_free_slots); 2.133 + if (result != NULL) { 2.134 + return result; 2.135 + } 2.136 + if (m != NULL && !two_free_slots) { 2.137 + // We were looking for a SpeculativeTrapData entry we didn't 2.138 + // find. Room is not available for more SpeculativeTrapData 2.139 + // entries, look in the non SpeculativeTrapData entries. 2.140 + return bci_to_data(bci, NULL); 2.141 + } 2.142 return NULL; 2.143 } 2.144 2.145 @@ -525,18 +594,25 @@ 2.146 st->print_cr("--- Extra data:"); 2.147 DataLayout* dp = data_layout_at(data_size()); 2.148 DataLayout* end = data_layout_at(data_size() + extra_data_size()); 2.149 - for (; dp < end; dp = MethodData::next_extra(dp)) { 2.150 - if (dp->tag() == DataLayout::no_tag) continue; 2.151 - if (dp->tag() == DataLayout::bit_data_tag) { 2.152 + for (;; dp = MethodData::next_extra(dp)) { 2.153 + assert(dp < end, "moved past end of extra data"); 2.154 + switch (dp->tag()) { 2.155 + case DataLayout::no_tag: 2.156 + continue; 2.157 + case DataLayout::bit_data_tag: 2.158 data = new BitData(dp); 2.159 - } else { 2.160 - assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); 2.161 + break; 2.162 + case DataLayout::arg_info_data_tag: 2.163 data = new ciArgInfoData(dp); 2.164 dp = end; // ArgInfoData is at the end of extra data section. 2.165 + break; 2.166 + default: 2.167 + fatal(err_msg("unexpected tag %d", dp->tag())); 2.168 } 2.169 st->print("%d", dp_to_di(data->dp())); 2.170 st->fill_to(6); 2.171 data->print_data_on(st); 2.172 + if (dp >= end) return; 2.173 } 2.174 } 2.175 2.176 @@ -569,8 +645,8 @@ 2.177 st->cr(); 2.178 } 2.179 2.180 -void ciCallTypeData::print_data_on(outputStream* st) const { 2.181 - print_shared(st, "ciCallTypeData"); 2.182 +void ciCallTypeData::print_data_on(outputStream* st, const char* extra) const { 2.183 + print_shared(st, "ciCallTypeData", extra); 2.184 if (has_arguments()) { 2.185 tab(st, true); 2.186 st->print("argument types"); 2.187 @@ -599,18 +675,18 @@ 2.188 } 2.189 } 2.190 2.191 -void ciReceiverTypeData::print_data_on(outputStream* st) const { 2.192 - print_shared(st, "ciReceiverTypeData"); 2.193 +void ciReceiverTypeData::print_data_on(outputStream* st, const char* extra) const { 2.194 + print_shared(st, "ciReceiverTypeData", extra); 2.195 print_receiver_data_on(st); 2.196 } 2.197 2.198 -void ciVirtualCallData::print_data_on(outputStream* st) const { 2.199 - print_shared(st, "ciVirtualCallData"); 2.200 +void ciVirtualCallData::print_data_on(outputStream* st, const char* extra) const { 2.201 + print_shared(st, "ciVirtualCallData", extra); 2.202 rtd_super()->print_receiver_data_on(st); 2.203 } 2.204 2.205 -void ciVirtualCallTypeData::print_data_on(outputStream* st) const { 2.206 - print_shared(st, "ciVirtualCallTypeData"); 2.207 +void ciVirtualCallTypeData::print_data_on(outputStream* st, const char* extra) const { 2.208 + print_shared(st, "ciVirtualCallTypeData", extra); 2.209 rtd_super()->print_receiver_data_on(st); 2.210 if (has_arguments()) { 2.211 tab(st, true); 2.212 @@ -624,8 +700,15 @@ 2.213 } 2.214 } 2.215 2.216 -void ciParametersTypeData::print_data_on(outputStream* st) const { 2.217 - st->print_cr("Parametertypes"); 2.218 +void ciParametersTypeData::print_data_on(outputStream* st, const char* extra) const { 2.219 + st->print_cr("ciParametersTypeData"); 2.220 parameters()->print_data_on(st); 2.221 } 2.222 + 2.223 +void ciSpeculativeTrapData::print_data_on(outputStream* st, const char* extra) const { 2.224 + st->print_cr("ciSpeculativeTrapData"); 2.225 + tab(st); 2.226 + method()->print_short_name(st); 2.227 + st->cr(); 2.228 +} 2.229 #endif
3.1 --- a/src/share/vm/ci/ciMethodData.hpp Mon Jan 27 13:14:53 2014 +0100 3.2 +++ b/src/share/vm/ci/ciMethodData.hpp Tue Feb 25 18:16:24 2014 +0100 3.3 @@ -31,6 +31,7 @@ 3.4 #include "ci/ciUtilities.hpp" 3.5 #include "oops/methodData.hpp" 3.6 #include "oops/oop.inline.hpp" 3.7 +#include "runtime/deoptimization.hpp" 3.8 3.9 class ciBitData; 3.10 class ciCounterData; 3.11 @@ -44,6 +45,7 @@ 3.12 class ciCallTypeData; 3.13 class ciVirtualCallTypeData; 3.14 class ciParametersTypeData; 3.15 +class ciSpeculativeTrapData;; 3.16 3.17 typedef ProfileData ciProfileData; 3.18 3.19 @@ -173,7 +175,7 @@ 3.20 } 3.21 3.22 #ifndef PRODUCT 3.23 - void print_data_on(outputStream* st) const; 3.24 + void print_data_on(outputStream* st, const char* extra) const; 3.25 #endif 3.26 }; 3.27 3.28 @@ -200,7 +202,7 @@ 3.29 } 3.30 void translate_receiver_data_from(const ProfileData* data); 3.31 #ifndef PRODUCT 3.32 - void print_data_on(outputStream* st) const; 3.33 + void print_data_on(outputStream* st, const char* extra) const; 3.34 void print_receiver_data_on(outputStream* st) const; 3.35 #endif 3.36 }; 3.37 @@ -225,7 +227,7 @@ 3.38 rtd_super()->translate_receiver_data_from(data); 3.39 } 3.40 #ifndef PRODUCT 3.41 - void print_data_on(outputStream* st) const; 3.42 + void print_data_on(outputStream* st, const char* extra) const; 3.43 #endif 3.44 }; 3.45 3.46 @@ -287,7 +289,7 @@ 3.47 } 3.48 3.49 #ifndef PRODUCT 3.50 - void print_data_on(outputStream* st) const; 3.51 + void print_data_on(outputStream* st, const char* extra) const; 3.52 #endif 3.53 }; 3.54 3.55 @@ -336,7 +338,26 @@ 3.56 } 3.57 3.58 #ifndef PRODUCT 3.59 - void print_data_on(outputStream* st) const; 3.60 + void print_data_on(outputStream* st, const char* extra) const; 3.61 +#endif 3.62 +}; 3.63 + 3.64 +class ciSpeculativeTrapData : public SpeculativeTrapData { 3.65 +public: 3.66 + ciSpeculativeTrapData(DataLayout* layout) : SpeculativeTrapData(layout) {} 3.67 + 3.68 + virtual void translate_from(const ProfileData* data); 3.69 + 3.70 + ciMethod* method() const { 3.71 + return (ciMethod*)intptr_at(method_offset); 3.72 + } 3.73 + 3.74 + void set_method(ciMethod* m) { 3.75 + set_intptr_at(method_offset, (intptr_t)m); 3.76 + } 3.77 + 3.78 +#ifndef PRODUCT 3.79 + void print_data_on(outputStream* st, const char* extra) const; 3.80 #endif 3.81 }; 3.82 3.83 @@ -436,6 +457,16 @@ 3.84 3.85 ciArgInfoData *arg_info() const; 3.86 3.87 + address data_base() const { 3.88 + return (address) _data; 3.89 + } 3.90 + DataLayout* limit_data_position() const { 3.91 + return (DataLayout*)((address)data_base() + _data_size); 3.92 + } 3.93 + 3.94 + void load_extra_data(); 3.95 + ciProfileData* bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots); 3.96 + 3.97 public: 3.98 bool is_method_data() const { return true; } 3.99 3.100 @@ -475,9 +506,11 @@ 3.101 ciProfileData* next_data(ciProfileData* current); 3.102 bool is_valid(ciProfileData* current) { return current != NULL; } 3.103 3.104 - // Get the data at an arbitrary bci, or NULL if there is none. 3.105 - ciProfileData* bci_to_data(int bci); 3.106 - ciProfileData* bci_to_extra_data(int bci, bool create_if_missing); 3.107 + DataLayout* extra_data_base() const { return limit_data_position(); } 3.108 + 3.109 + // Get the data at an arbitrary bci, or NULL if there is none. If m 3.110 + // is not NULL look for a SpeculativeTrapData if any first. 3.111 + ciProfileData* bci_to_data(int bci, ciMethod* m = NULL); 3.112 3.113 uint overflow_trap_count() const { 3.114 return _orig.overflow_trap_count(); 3.115 @@ -496,12 +529,13 @@ 3.116 3.117 // Helpful query functions that decode trap_state. 3.118 int has_trap_at(ciProfileData* data, int reason); 3.119 - int has_trap_at(int bci, int reason) { 3.120 - return has_trap_at(bci_to_data(bci), reason); 3.121 + int has_trap_at(int bci, ciMethod* m, int reason) { 3.122 + assert((m != NULL) == Deoptimization::reason_is_speculate(reason), "inconsistent method/reason"); 3.123 + return has_trap_at(bci_to_data(bci, m), reason); 3.124 } 3.125 int trap_recompiled_at(ciProfileData* data); 3.126 - int trap_recompiled_at(int bci) { 3.127 - return trap_recompiled_at(bci_to_data(bci)); 3.128 + int trap_recompiled_at(int bci, ciMethod* m) { 3.129 + return trap_recompiled_at(bci_to_data(bci, m)); 3.130 } 3.131 3.132 void clear_escape_info();
4.1 --- a/src/share/vm/interpreter/bytecodeTracer.cpp Mon Jan 27 13:14:53 2014 +0100 4.2 +++ b/src/share/vm/interpreter/bytecodeTracer.cpp Tue Feb 25 18:16:24 2014 +0100 4.3 @@ -596,7 +596,7 @@ 4.4 if (data != NULL) { 4.5 st->print(" %d", mdo->dp_to_di(data->dp())); 4.6 st->fill_to(6); 4.7 - data->print_data_on(st); 4.8 + data->print_data_on(st, mdo); 4.9 } 4.10 } 4.11 }
5.1 --- a/src/share/vm/oops/instanceKlass.cpp Mon Jan 27 13:14:53 2014 +0100 5.2 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Feb 25 18:16:24 2014 +0100 5.3 @@ -2234,15 +2234,7 @@ 5.4 for (int m = 0; m < methods()->length(); m++) { 5.5 MethodData* mdo = methods()->at(m)->method_data(); 5.6 if (mdo != NULL) { 5.7 - for (ProfileData* data = mdo->first_data(); 5.8 - mdo->is_valid(data); 5.9 - data = mdo->next_data(data)) { 5.10 - data->clean_weak_klass_links(is_alive); 5.11 - } 5.12 - ParametersTypeData* parameters = mdo->parameters_type_data(); 5.13 - if (parameters != NULL) { 5.14 - parameters->clean_weak_klass_links(is_alive); 5.15 - } 5.16 + mdo->clean_method_data(is_alive); 5.17 } 5.18 } 5.19 }
6.1 --- a/src/share/vm/oops/instanceKlass.hpp Mon Jan 27 13:14:53 2014 +0100 6.2 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Feb 25 18:16:24 2014 +0100 6.3 @@ -306,7 +306,7 @@ 6.4 // three cases: 6.5 // NULL: no implementor. 6.6 // A Klass* that's not itself: one implementor. 6.7 - // Itsef: more than one implementors. 6.8 + // Itself: more than one implementors. 6.9 // embedded host klass follows here 6.10 // The embedded host klass only exists in an anonymous class for 6.11 // dynamic language support (JSR 292 enabled). The host class grants
7.1 --- a/src/share/vm/oops/methodData.cpp Mon Jan 27 13:14:53 2014 +0100 7.2 +++ b/src/share/vm/oops/methodData.cpp Tue Feb 25 18:16:24 2014 +0100 7.3 @@ -80,8 +80,42 @@ 7.4 _data = NULL; 7.5 } 7.6 7.7 +char* ProfileData::print_data_on_helper(const MethodData* md) const { 7.8 + DataLayout* dp = md->extra_data_base(); 7.9 + DataLayout* end = md->extra_data_limit(); 7.10 + stringStream ss; 7.11 + for (;; dp = MethodData::next_extra(dp)) { 7.12 + assert(dp < end, "moved past end of extra data"); 7.13 + switch(dp->tag()) { 7.14 + case DataLayout::speculative_trap_data_tag: 7.15 + if (dp->bci() == bci()) { 7.16 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 7.17 + int trap = data->trap_state(); 7.18 + char buf[100]; 7.19 + ss.print("trap/"); 7.20 + data->method()->print_short_name(&ss); 7.21 + ss.print("(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); 7.22 + } 7.23 + break; 7.24 + case DataLayout::bit_data_tag: 7.25 + break; 7.26 + case DataLayout::no_tag: 7.27 + case DataLayout::arg_info_data_tag: 7.28 + return ss.as_string(); 7.29 + break; 7.30 + default: 7.31 + fatal(err_msg("unexpected tag %d", dp->tag())); 7.32 + } 7.33 + } 7.34 + return NULL; 7.35 +} 7.36 + 7.37 +void ProfileData::print_data_on(outputStream* st, const MethodData* md) const { 7.38 + print_data_on(st, print_data_on_helper(md)); 7.39 +} 7.40 + 7.41 #ifndef PRODUCT 7.42 -void ProfileData::print_shared(outputStream* st, const char* name) const { 7.43 +void ProfileData::print_shared(outputStream* st, const char* name, const char* extra) const { 7.44 st->print("bci: %d", bci()); 7.45 st->fill_to(tab_width_one); 7.46 st->print("%s", name); 7.47 @@ -91,9 +125,13 @@ 7.48 char buf[100]; 7.49 st->print("trap(%s) ", Deoptimization::format_trap_state(buf, sizeof(buf), trap)); 7.50 } 7.51 + if (extra != NULL) { 7.52 + st->print(extra); 7.53 + } 7.54 int flags = data()->flags(); 7.55 - if (flags != 0) 7.56 + if (flags != 0) { 7.57 st->print("flags(%d) ", flags); 7.58 + } 7.59 } 7.60 7.61 void ProfileData::tab(outputStream* st, bool first) const { 7.62 @@ -109,8 +147,8 @@ 7.63 7.64 7.65 #ifndef PRODUCT 7.66 -void BitData::print_data_on(outputStream* st) const { 7.67 - print_shared(st, "BitData"); 7.68 +void BitData::print_data_on(outputStream* st, const char* extra) const { 7.69 + print_shared(st, "BitData", extra); 7.70 } 7.71 #endif // !PRODUCT 7.72 7.73 @@ -120,8 +158,8 @@ 7.74 // A CounterData corresponds to a simple counter. 7.75 7.76 #ifndef PRODUCT 7.77 -void CounterData::print_data_on(outputStream* st) const { 7.78 - print_shared(st, "CounterData"); 7.79 +void CounterData::print_data_on(outputStream* st, const char* extra) const { 7.80 + print_shared(st, "CounterData", extra); 7.81 st->print_cr("count(%u)", count()); 7.82 } 7.83 #endif // !PRODUCT 7.84 @@ -150,8 +188,8 @@ 7.85 } 7.86 7.87 #ifndef PRODUCT 7.88 -void JumpData::print_data_on(outputStream* st) const { 7.89 - print_shared(st, "JumpData"); 7.90 +void JumpData::print_data_on(outputStream* st, const char* extra) const { 7.91 + print_shared(st, "JumpData", extra); 7.92 st->print_cr("taken(%u) displacement(%d)", taken(), displacement()); 7.93 } 7.94 #endif // !PRODUCT 7.95 @@ -332,8 +370,8 @@ 7.96 st->cr(); 7.97 } 7.98 7.99 -void CallTypeData::print_data_on(outputStream* st) const { 7.100 - CounterData::print_data_on(st); 7.101 +void CallTypeData::print_data_on(outputStream* st, const char* extra) const { 7.102 + CounterData::print_data_on(st, extra); 7.103 if (has_arguments()) { 7.104 tab(st, true); 7.105 st->print("argument types"); 7.106 @@ -346,8 +384,8 @@ 7.107 } 7.108 } 7.109 7.110 -void VirtualCallTypeData::print_data_on(outputStream* st) const { 7.111 - VirtualCallData::print_data_on(st); 7.112 +void VirtualCallTypeData::print_data_on(outputStream* st, const char* extra) const { 7.113 + VirtualCallData::print_data_on(st, extra); 7.114 if (has_arguments()) { 7.115 tab(st, true); 7.116 st->print("argument types"); 7.117 @@ -400,12 +438,12 @@ 7.118 } 7.119 } 7.120 } 7.121 -void ReceiverTypeData::print_data_on(outputStream* st) const { 7.122 - print_shared(st, "ReceiverTypeData"); 7.123 +void ReceiverTypeData::print_data_on(outputStream* st, const char* extra) const { 7.124 + print_shared(st, "ReceiverTypeData", extra); 7.125 print_receiver_data_on(st); 7.126 } 7.127 -void VirtualCallData::print_data_on(outputStream* st) const { 7.128 - print_shared(st, "VirtualCallData"); 7.129 +void VirtualCallData::print_data_on(outputStream* st, const char* extra) const { 7.130 + print_shared(st, "VirtualCallData", extra); 7.131 print_receiver_data_on(st); 7.132 } 7.133 #endif // !PRODUCT 7.134 @@ -456,8 +494,8 @@ 7.135 7.136 7.137 #ifndef PRODUCT 7.138 -void RetData::print_data_on(outputStream* st) const { 7.139 - print_shared(st, "RetData"); 7.140 +void RetData::print_data_on(outputStream* st, const char* extra) const { 7.141 + print_shared(st, "RetData", extra); 7.142 uint row; 7.143 int entries = 0; 7.144 for (row = 0; row < row_limit(); row++) { 7.145 @@ -491,8 +529,8 @@ 7.146 } 7.147 7.148 #ifndef PRODUCT 7.149 -void BranchData::print_data_on(outputStream* st) const { 7.150 - print_shared(st, "BranchData"); 7.151 +void BranchData::print_data_on(outputStream* st, const char* extra) const { 7.152 + print_shared(st, "BranchData", extra); 7.153 st->print_cr("taken(%u) displacement(%d)", 7.154 taken(), displacement()); 7.155 tab(st); 7.156 @@ -565,8 +603,8 @@ 7.157 } 7.158 7.159 #ifndef PRODUCT 7.160 -void MultiBranchData::print_data_on(outputStream* st) const { 7.161 - print_shared(st, "MultiBranchData"); 7.162 +void MultiBranchData::print_data_on(outputStream* st, const char* extra) const { 7.163 + print_shared(st, "MultiBranchData", extra); 7.164 st->print_cr("default_count(%u) displacement(%d)", 7.165 default_count(), default_displacement()); 7.166 int cases = number_of_cases(); 7.167 @@ -579,8 +617,8 @@ 7.168 #endif 7.169 7.170 #ifndef PRODUCT 7.171 -void ArgInfoData::print_data_on(outputStream* st) const { 7.172 - print_shared(st, "ArgInfoData"); 7.173 +void ArgInfoData::print_data_on(outputStream* st, const char* extra) const { 7.174 + print_shared(st, "ArgInfoData", extra); 7.175 int nargs = number_of_args(); 7.176 for (int i = 0; i < nargs; i++) { 7.177 st->print(" 0x%x", arg_modified(i)); 7.178 @@ -611,10 +649,17 @@ 7.179 } 7.180 7.181 #ifndef PRODUCT 7.182 -void ParametersTypeData::print_data_on(outputStream* st) const { 7.183 - st->print("parameter types"); 7.184 +void ParametersTypeData::print_data_on(outputStream* st, const char* extra) const { 7.185 + st->print("parameter types", extra); 7.186 _parameters.print_data_on(st); 7.187 } 7.188 + 7.189 +void SpeculativeTrapData::print_data_on(outputStream* st, const char* extra) const { 7.190 + print_shared(st, "SpeculativeTrapData", extra); 7.191 + tab(st); 7.192 + method()->print_short_name(st); 7.193 + st->cr(); 7.194 +} 7.195 #endif 7.196 7.197 // ================================================================== 7.198 @@ -740,7 +785,27 @@ 7.199 return DataLayout::compute_size_in_bytes(cell_count); 7.200 } 7.201 7.202 -int MethodData::compute_extra_data_count(int data_size, int empty_bc_count) { 7.203 +bool MethodData::is_speculative_trap_bytecode(Bytecodes::Code code) { 7.204 + // Bytecodes for which we may use speculation 7.205 + switch (code) { 7.206 + case Bytecodes::_checkcast: 7.207 + case Bytecodes::_instanceof: 7.208 + case Bytecodes::_aastore: 7.209 + case Bytecodes::_invokevirtual: 7.210 + case Bytecodes::_invokeinterface: 7.211 + case Bytecodes::_if_acmpeq: 7.212 + case Bytecodes::_if_acmpne: 7.213 + case Bytecodes::_invokestatic: 7.214 +#ifdef COMPILER2 7.215 + return UseTypeSpeculation; 7.216 +#endif 7.217 + default: 7.218 + return false; 7.219 + } 7.220 + return false; 7.221 +} 7.222 + 7.223 +int MethodData::compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps) { 7.224 if (ProfileTraps) { 7.225 // Assume that up to 3% of BCIs with no MDP will need to allocate one. 7.226 int extra_data_count = (uint)(empty_bc_count * 3) / 128 + 1; 7.227 @@ -751,7 +816,18 @@ 7.228 extra_data_count = one_percent_of_data; 7.229 if (extra_data_count > empty_bc_count) 7.230 extra_data_count = empty_bc_count; // no need for more 7.231 - return extra_data_count; 7.232 + 7.233 + // Make sure we have a minimum number of extra data slots to 7.234 + // allocate SpeculativeTrapData entries. We would want to have one 7.235 + // entry per compilation that inlines this method and for which 7.236 + // some type speculation assumption fails. So the room we need for 7.237 + // the SpeculativeTrapData entries doesn't directly depend on the 7.238 + // size of the method. Because it's hard to estimate, we reserve 7.239 + // space for an arbitrary number of entries. 7.240 + int spec_data_count = (needs_speculative_traps ? SpecTrapLimitExtraEntries : 0) * 7.241 + (SpeculativeTrapData::static_cell_count() + DataLayout::header_size_in_cells()); 7.242 + 7.243 + return MAX2(extra_data_count, spec_data_count); 7.244 } else { 7.245 return 0; 7.246 } 7.247 @@ -764,15 +840,17 @@ 7.248 BytecodeStream stream(method); 7.249 Bytecodes::Code c; 7.250 int empty_bc_count = 0; // number of bytecodes lacking data 7.251 + bool needs_speculative_traps = false; 7.252 while ((c = stream.next()) >= 0) { 7.253 int size_in_bytes = compute_data_size(&stream); 7.254 data_size += size_in_bytes; 7.255 if (size_in_bytes == 0) empty_bc_count += 1; 7.256 + needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c); 7.257 } 7.258 int object_size = in_bytes(data_offset()) + data_size; 7.259 7.260 // Add some extra DataLayout cells (at least one) to track stray traps. 7.261 - int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); 7.262 + int extra_data_count = compute_extra_data_count(data_size, empty_bc_count, needs_speculative_traps); 7.263 object_size += extra_data_count * DataLayout::compute_size_in_bytes(0); 7.264 7.265 // Add a cell to record information about modified arguments. 7.266 @@ -1004,18 +1082,23 @@ 7.267 _data[0] = 0; // apparently not set below. 7.268 BytecodeStream stream(method); 7.269 Bytecodes::Code c; 7.270 + bool needs_speculative_traps = false; 7.271 while ((c = stream.next()) >= 0) { 7.272 int size_in_bytes = initialize_data(&stream, data_size); 7.273 data_size += size_in_bytes; 7.274 if (size_in_bytes == 0) empty_bc_count += 1; 7.275 + needs_speculative_traps = needs_speculative_traps || is_speculative_trap_bytecode(c); 7.276 } 7.277 _data_size = data_size; 7.278 int object_size = in_bytes(data_offset()) + data_size; 7.279 7.280 // Add some extra DataLayout cells (at least one) to track stray traps. 7.281 - int extra_data_count = compute_extra_data_count(data_size, empty_bc_count); 7.282 + int extra_data_count = compute_extra_data_count(data_size, empty_bc_count, needs_speculative_traps); 7.283 int extra_size = extra_data_count * DataLayout::compute_size_in_bytes(0); 7.284 7.285 + // Let's zero the space for the extra data 7.286 + Copy::zero_to_bytes(((address)_data) + data_size, extra_size); 7.287 + 7.288 // Add a cell to record information about modified arguments. 7.289 // Set up _args_modified array after traps cells so that 7.290 // the code for traps cells works. 7.291 @@ -1027,17 +1110,17 @@ 7.292 int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1); 7.293 object_size += extra_size + arg_data_size; 7.294 7.295 - int args_cell = ParametersTypeData::compute_cell_count(method()); 7.296 + int parms_cell = ParametersTypeData::compute_cell_count(method()); 7.297 // If we are profiling parameters, we reserver an area near the end 7.298 // of the MDO after the slots for bytecodes (because there's no bci 7.299 // for method entry so they don't fit with the framework for the 7.300 // profiling of bytecodes). We store the offset within the MDO of 7.301 // this area (or -1 if no parameter is profiled) 7.302 - if (args_cell > 0) { 7.303 - object_size += DataLayout::compute_size_in_bytes(args_cell); 7.304 + if (parms_cell > 0) { 7.305 + object_size += DataLayout::compute_size_in_bytes(parms_cell); 7.306 _parameters_type_data_di = data_size + extra_size + arg_data_size; 7.307 DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size); 7.308 - dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell); 7.309 + dp->initialize(DataLayout::parameters_type_data_tag, 0, parms_cell); 7.310 } else { 7.311 _parameters_type_data_di = -1; 7.312 } 7.313 @@ -1128,39 +1211,113 @@ 7.314 break; 7.315 } 7.316 } 7.317 - return bci_to_extra_data(bci, false); 7.318 + return bci_to_extra_data(bci, NULL, false); 7.319 } 7.320 7.321 -// Translate a bci to its corresponding extra data, or NULL. 7.322 -ProfileData* MethodData::bci_to_extra_data(int bci, bool create_if_missing) { 7.323 - DataLayout* dp = extra_data_base(); 7.324 - DataLayout* end = extra_data_limit(); 7.325 - DataLayout* avail = NULL; 7.326 - for (; dp < end; dp = next_extra(dp)) { 7.327 +DataLayout* MethodData::next_extra(DataLayout* dp) { 7.328 + int nb_cells = 0; 7.329 + switch(dp->tag()) { 7.330 + case DataLayout::bit_data_tag: 7.331 + case DataLayout::no_tag: 7.332 + nb_cells = BitData::static_cell_count(); 7.333 + break; 7.334 + case DataLayout::speculative_trap_data_tag: 7.335 + nb_cells = SpeculativeTrapData::static_cell_count(); 7.336 + break; 7.337 + default: 7.338 + fatal(err_msg("unexpected tag %d", dp->tag())); 7.339 + } 7.340 + return (DataLayout*)((address)dp + DataLayout::compute_size_in_bytes(nb_cells)); 7.341 +} 7.342 + 7.343 +ProfileData* MethodData::bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp) { 7.344 + DataLayout* end = extra_data_limit(); 7.345 + 7.346 + for (;; dp = next_extra(dp)) { 7.347 + assert(dp < end, "moved past end of extra data"); 7.348 // No need for "OrderAccess::load_acquire" ops, 7.349 // since the data structure is monotonic. 7.350 - if (dp->tag() == DataLayout::no_tag) break; 7.351 - if (dp->tag() == DataLayout::arg_info_data_tag) { 7.352 - dp = end; // ArgInfoData is at the end of extra data section. 7.353 + switch(dp->tag()) { 7.354 + case DataLayout::no_tag: 7.355 + return NULL; 7.356 + case DataLayout::arg_info_data_tag: 7.357 + dp = end; 7.358 + return NULL; // ArgInfoData is at the end of extra data section. 7.359 + case DataLayout::bit_data_tag: 7.360 + if (m == NULL && dp->bci() == bci) { 7.361 + return new BitData(dp); 7.362 + } 7.363 break; 7.364 - } 7.365 - if (dp->bci() == bci) { 7.366 - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); 7.367 - return new BitData(dp); 7.368 + case DataLayout::speculative_trap_data_tag: 7.369 + if (m != NULL) { 7.370 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 7.371 + // data->method() may be null in case of a concurrent 7.372 + // allocation. Assume it's for the same method and use that 7.373 + // entry in that case. 7.374 + if (dp->bci() == bci) { 7.375 + if (data->method() == NULL) { 7.376 + return NULL; 7.377 + } else if (data->method() == m) { 7.378 + return data; 7.379 + } 7.380 + } 7.381 + } 7.382 + break; 7.383 + default: 7.384 + fatal(err_msg("unexpected tag %d", dp->tag())); 7.385 } 7.386 } 7.387 - if (create_if_missing && dp < end) { 7.388 - // Allocate this one. There is no mutual exclusion, 7.389 - // so two threads could allocate different BCIs to the 7.390 - // same data layout. This means these extra data 7.391 - // records, like most other MDO contents, must not be 7.392 - // trusted too much. 7.393 - DataLayout temp; 7.394 - temp.initialize(DataLayout::bit_data_tag, bci, 0); 7.395 - dp->release_set_header(temp.header()); 7.396 - assert(dp->tag() == DataLayout::bit_data_tag, "sane"); 7.397 - //NO: assert(dp->bci() == bci, "no concurrent allocation"); 7.398 - return new BitData(dp); 7.399 + return NULL; 7.400 +} 7.401 + 7.402 + 7.403 +// Translate a bci to its corresponding extra data, or NULL. 7.404 +ProfileData* MethodData::bci_to_extra_data(int bci, Method* m, bool create_if_missing) { 7.405 + // This code assumes an entry for a SpeculativeTrapData is 2 cells 7.406 + assert(2*DataLayout::compute_size_in_bytes(BitData::static_cell_count()) == 7.407 + DataLayout::compute_size_in_bytes(SpeculativeTrapData::static_cell_count()), 7.408 + "code needs to be adjusted"); 7.409 + 7.410 + DataLayout* dp = extra_data_base(); 7.411 + DataLayout* end = extra_data_limit(); 7.412 + 7.413 + // Allocation in the extra data space has to be atomic because not 7.414 + // all entries have the same size and non atomic concurrent 7.415 + // allocation would result in a corrupted extra data space. 7.416 + while (true) { 7.417 + ProfileData* result = bci_to_extra_data_helper(bci, m, dp); 7.418 + if (result != NULL) { 7.419 + return result; 7.420 + } 7.421 + 7.422 + if (create_if_missing && dp < end) { 7.423 + assert(dp->tag() == DataLayout::no_tag || (dp->tag() == DataLayout::speculative_trap_data_tag && m != NULL), "should be free"); 7.424 + assert(next_extra(dp)->tag() == DataLayout::no_tag || next_extra(dp)->tag() == DataLayout::arg_info_data_tag, "should be free or arg info"); 7.425 + u1 tag = m == NULL ? DataLayout::bit_data_tag : DataLayout::speculative_trap_data_tag; 7.426 + // SpeculativeTrapData is 2 slots. Make sure we have room. 7.427 + if (m != NULL && next_extra(dp)->tag() != DataLayout::no_tag) { 7.428 + return NULL; 7.429 + } 7.430 + DataLayout temp; 7.431 + temp.initialize(tag, bci, 0); 7.432 + // May have been set concurrently 7.433 + if (dp->header() != temp.header() && !dp->atomic_set_header(temp.header())) { 7.434 + // Allocation failure because of concurrent allocation. Try 7.435 + // again. 7.436 + continue; 7.437 + } 7.438 + assert(dp->tag() == tag, "sane"); 7.439 + assert(dp->bci() == bci, "no concurrent allocation"); 7.440 + if (tag == DataLayout::bit_data_tag) { 7.441 + return new BitData(dp); 7.442 + } else { 7.443 + // If being allocated concurrently, one trap may be lost 7.444 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 7.445 + data->set_method(m); 7.446 + return data; 7.447 + } 7.448 + } 7.449 + return NULL; 7.450 } 7.451 return NULL; 7.452 } 7.453 @@ -1205,25 +1362,35 @@ 7.454 for ( ; is_valid(data); data = next_data(data)) { 7.455 st->print("%d", dp_to_di(data->dp())); 7.456 st->fill_to(6); 7.457 - data->print_data_on(st); 7.458 + data->print_data_on(st, this); 7.459 } 7.460 st->print_cr("--- Extra data:"); 7.461 DataLayout* dp = extra_data_base(); 7.462 DataLayout* end = extra_data_limit(); 7.463 - for (; dp < end; dp = next_extra(dp)) { 7.464 + for (;; dp = next_extra(dp)) { 7.465 + assert(dp < end, "moved past end of extra data"); 7.466 // No need for "OrderAccess::load_acquire" ops, 7.467 // since the data structure is monotonic. 7.468 - if (dp->tag() == DataLayout::no_tag) continue; 7.469 - if (dp->tag() == DataLayout::bit_data_tag) { 7.470 + switch(dp->tag()) { 7.471 + case DataLayout::no_tag: 7.472 + continue; 7.473 + case DataLayout::bit_data_tag: 7.474 data = new BitData(dp); 7.475 - } else { 7.476 - assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo"); 7.477 + break; 7.478 + case DataLayout::speculative_trap_data_tag: 7.479 + data = new SpeculativeTrapData(dp); 7.480 + break; 7.481 + case DataLayout::arg_info_data_tag: 7.482 data = new ArgInfoData(dp); 7.483 dp = end; // ArgInfoData is at the end of extra data section. 7.484 + break; 7.485 + default: 7.486 + fatal(err_msg("unexpected tag %d", dp->tag())); 7.487 } 7.488 st->print("%d", dp_to_di(data->dp())); 7.489 st->fill_to(6); 7.490 data->print_data_on(st); 7.491 + if (dp >= end) return; 7.492 } 7.493 } 7.494 #endif 7.495 @@ -1346,3 +1513,110 @@ 7.496 assert(profile_parameters_jsr292_only(), "inconsistent"); 7.497 return m->is_compiled_lambda_form(); 7.498 } 7.499 + 7.500 +void MethodData::clean_extra_data_helper(DataLayout* dp, int shift, bool reset) { 7.501 + if (shift == 0) { 7.502 + return; 7.503 + } 7.504 + if (!reset) { 7.505 + // Move all cells of trap entry at dp left by "shift" cells 7.506 + intptr_t* start = (intptr_t*)dp; 7.507 + intptr_t* end = (intptr_t*)next_extra(dp); 7.508 + for (intptr_t* ptr = start; ptr < end; ptr++) { 7.509 + *(ptr-shift) = *ptr; 7.510 + } 7.511 + } else { 7.512 + // Reset "shift" cells stopping at dp 7.513 + intptr_t* start = ((intptr_t*)dp) - shift; 7.514 + intptr_t* end = (intptr_t*)dp; 7.515 + for (intptr_t* ptr = start; ptr < end; ptr++) { 7.516 + *ptr = 0; 7.517 + } 7.518 + } 7.519 +} 7.520 + 7.521 +// Remove SpeculativeTrapData entries that reference an unloaded 7.522 +// method 7.523 +void MethodData::clean_extra_data(BoolObjectClosure* is_alive) { 7.524 + DataLayout* dp = extra_data_base(); 7.525 + DataLayout* end = extra_data_limit(); 7.526 + 7.527 + int shift = 0; 7.528 + for (; dp < end; dp = next_extra(dp)) { 7.529 + switch(dp->tag()) { 7.530 + case DataLayout::speculative_trap_data_tag: { 7.531 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 7.532 + Method* m = data->method(); 7.533 + assert(m != NULL, "should have a method"); 7.534 + if (!m->method_holder()->is_loader_alive(is_alive)) { 7.535 + // "shift" accumulates the number of cells for dead 7.536 + // SpeculativeTrapData entries that have been seen so 7.537 + // far. Following entries must be shifted left by that many 7.538 + // cells to remove the dead SpeculativeTrapData entries. 7.539 + shift += (int)((intptr_t*)next_extra(dp) - (intptr_t*)dp); 7.540 + } else { 7.541 + // Shift this entry left if it follows dead 7.542 + // SpeculativeTrapData entries 7.543 + clean_extra_data_helper(dp, shift); 7.544 + } 7.545 + break; 7.546 + } 7.547 + case DataLayout::bit_data_tag: 7.548 + // Shift this entry left if it follows dead SpeculativeTrapData 7.549 + // entries 7.550 + clean_extra_data_helper(dp, shift); 7.551 + continue; 7.552 + case DataLayout::no_tag: 7.553 + case DataLayout::arg_info_data_tag: 7.554 + // We are at end of the live trap entries. The previous "shift" 7.555 + // cells contain entries that are either dead or were shifted 7.556 + // left. They need to be reset to no_tag 7.557 + clean_extra_data_helper(dp, shift, true); 7.558 + return; 7.559 + default: 7.560 + fatal(err_msg("unexpected tag %d", dp->tag())); 7.561 + } 7.562 + } 7.563 +} 7.564 + 7.565 +// Verify there's no unloaded method referenced by a 7.566 +// SpeculativeTrapData entry 7.567 +void MethodData::verify_extra_data_clean(BoolObjectClosure* is_alive) { 7.568 +#ifdef ASSERT 7.569 + DataLayout* dp = extra_data_base(); 7.570 + DataLayout* end = extra_data_limit(); 7.571 + 7.572 + for (; dp < end; dp = next_extra(dp)) { 7.573 + switch(dp->tag()) { 7.574 + case DataLayout::speculative_trap_data_tag: { 7.575 + SpeculativeTrapData* data = new SpeculativeTrapData(dp); 7.576 + Method* m = data->method(); 7.577 + assert(m != NULL && m->method_holder()->is_loader_alive(is_alive), "Method should exist"); 7.578 + break; 7.579 + } 7.580 + case DataLayout::bit_data_tag: 7.581 + continue; 7.582 + case DataLayout::no_tag: 7.583 + case DataLayout::arg_info_data_tag: 7.584 + return; 7.585 + default: 7.586 + fatal(err_msg("unexpected tag %d", dp->tag())); 7.587 + } 7.588 + } 7.589 +#endif 7.590 +} 7.591 + 7.592 +void MethodData::clean_method_data(BoolObjectClosure* is_alive) { 7.593 + for (ProfileData* data = first_data(); 7.594 + is_valid(data); 7.595 + data = next_data(data)) { 7.596 + data->clean_weak_klass_links(is_alive); 7.597 + } 7.598 + ParametersTypeData* parameters = parameters_type_data(); 7.599 + if (parameters != NULL) { 7.600 + parameters->clean_weak_klass_links(is_alive); 7.601 + } 7.602 + 7.603 + clean_extra_data(is_alive); 7.604 + verify_extra_data_clean(is_alive); 7.605 +}
8.1 --- a/src/share/vm/oops/methodData.hpp Mon Jan 27 13:14:53 2014 +0100 8.2 +++ b/src/share/vm/oops/methodData.hpp Tue Feb 25 18:16:24 2014 +0100 8.3 @@ -120,7 +120,8 @@ 8.4 arg_info_data_tag, 8.5 call_type_data_tag, 8.6 virtual_call_type_data_tag, 8.7 - parameters_type_data_tag 8.8 + parameters_type_data_tag, 8.9 + speculative_trap_data_tag 8.10 }; 8.11 8.12 enum { 8.13 @@ -189,8 +190,11 @@ 8.14 void set_header(intptr_t value) { 8.15 _header._bits = value; 8.16 } 8.17 - void release_set_header(intptr_t value) { 8.18 - OrderAccess::release_store_ptr(&_header._bits, value); 8.19 + bool atomic_set_header(intptr_t value) { 8.20 + if (Atomic::cmpxchg_ptr(value, (volatile intptr_t*)&_header._bits, 0) == 0) { 8.21 + return true; 8.22 + } 8.23 + return false; 8.24 } 8.25 intptr_t header() { 8.26 return _header._bits; 8.27 @@ -266,6 +270,7 @@ 8.28 class MultiBranchData; 8.29 class ArgInfoData; 8.30 class ParametersTypeData; 8.31 +class SpeculativeTrapData; 8.32 8.33 // ProfileData 8.34 // 8.35 @@ -286,6 +291,8 @@ 8.36 // This is a pointer to a section of profiling data. 8.37 DataLayout* _data; 8.38 8.39 + char* print_data_on_helper(const MethodData* md) const; 8.40 + 8.41 protected: 8.42 DataLayout* data() { return _data; } 8.43 const DataLayout* data() const { return _data; } 8.44 @@ -400,6 +407,7 @@ 8.45 virtual bool is_CallTypeData() const { return false; } 8.46 virtual bool is_VirtualCallTypeData()const { return false; } 8.47 virtual bool is_ParametersTypeData() const { return false; } 8.48 + virtual bool is_SpeculativeTrapData()const { return false; } 8.49 8.50 8.51 BitData* as_BitData() const { 8.52 @@ -454,6 +462,10 @@ 8.53 assert(is_ParametersTypeData(), "wrong type"); 8.54 return is_ParametersTypeData() ? (ParametersTypeData*)this : NULL; 8.55 } 8.56 + SpeculativeTrapData* as_SpeculativeTrapData() const { 8.57 + assert(is_SpeculativeTrapData(), "wrong type"); 8.58 + return is_SpeculativeTrapData() ? (SpeculativeTrapData*)this : NULL; 8.59 + } 8.60 8.61 8.62 // Subclass specific initialization 8.63 @@ -469,12 +481,14 @@ 8.64 // translation here, and the required translators are in the ci subclasses. 8.65 virtual void translate_from(const ProfileData* data) {} 8.66 8.67 - virtual void print_data_on(outputStream* st) const { 8.68 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const { 8.69 ShouldNotReachHere(); 8.70 } 8.71 8.72 + void print_data_on(outputStream* st, const MethodData* md) const; 8.73 + 8.74 #ifndef PRODUCT 8.75 - void print_shared(outputStream* st, const char* name) const; 8.76 + void print_shared(outputStream* st, const char* name, const char* extra) const; 8.77 void tab(outputStream* st, bool first = false) const; 8.78 #endif 8.79 }; 8.80 @@ -522,7 +536,7 @@ 8.81 } 8.82 8.83 #ifndef PRODUCT 8.84 - void print_data_on(outputStream* st) const; 8.85 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.86 #endif 8.87 }; 8.88 8.89 @@ -566,7 +580,7 @@ 8.90 } 8.91 8.92 #ifndef PRODUCT 8.93 - void print_data_on(outputStream* st) const; 8.94 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.95 #endif 8.96 }; 8.97 8.98 @@ -639,7 +653,7 @@ 8.99 void post_initialize(BytecodeStream* stream, MethodData* mdo); 8.100 8.101 #ifndef PRODUCT 8.102 - void print_data_on(outputStream* st) const; 8.103 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.104 #endif 8.105 }; 8.106 8.107 @@ -1050,7 +1064,7 @@ 8.108 } 8.109 8.110 #ifndef PRODUCT 8.111 - virtual void print_data_on(outputStream* st) const; 8.112 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; 8.113 #endif 8.114 }; 8.115 8.116 @@ -1158,7 +1172,7 @@ 8.117 8.118 #ifndef PRODUCT 8.119 void print_receiver_data_on(outputStream* st) const; 8.120 - void print_data_on(outputStream* st) const; 8.121 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.122 #endif 8.123 }; 8.124 8.125 @@ -1191,7 +1205,7 @@ 8.126 } 8.127 8.128 #ifndef PRODUCT 8.129 - void print_data_on(outputStream* st) const; 8.130 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.131 #endif 8.132 }; 8.133 8.134 @@ -1317,7 +1331,7 @@ 8.135 } 8.136 8.137 #ifndef PRODUCT 8.138 - virtual void print_data_on(outputStream* st) const; 8.139 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; 8.140 #endif 8.141 }; 8.142 8.143 @@ -1416,7 +1430,7 @@ 8.144 void post_initialize(BytecodeStream* stream, MethodData* mdo); 8.145 8.146 #ifndef PRODUCT 8.147 - void print_data_on(outputStream* st) const; 8.148 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.149 #endif 8.150 }; 8.151 8.152 @@ -1480,7 +1494,7 @@ 8.153 void post_initialize(BytecodeStream* stream, MethodData* mdo); 8.154 8.155 #ifndef PRODUCT 8.156 - void print_data_on(outputStream* st) const; 8.157 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.158 #endif 8.159 }; 8.160 8.161 @@ -1637,7 +1651,7 @@ 8.162 void post_initialize(BytecodeStream* stream, MethodData* mdo); 8.163 8.164 #ifndef PRODUCT 8.165 - void print_data_on(outputStream* st) const; 8.166 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.167 #endif 8.168 }; 8.169 8.170 @@ -1664,7 +1678,7 @@ 8.171 } 8.172 8.173 #ifndef PRODUCT 8.174 - void print_data_on(outputStream* st) const; 8.175 + void print_data_on(outputStream* st, const char* extra = NULL) const; 8.176 #endif 8.177 }; 8.178 8.179 @@ -1725,7 +1739,7 @@ 8.180 } 8.181 8.182 #ifndef PRODUCT 8.183 - virtual void print_data_on(outputStream* st) const; 8.184 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; 8.185 #endif 8.186 8.187 static ByteSize stack_slot_offset(int i) { 8.188 @@ -1737,6 +1751,54 @@ 8.189 } 8.190 }; 8.191 8.192 +// SpeculativeTrapData 8.193 +// 8.194 +// A SpeculativeTrapData is used to record traps due to type 8.195 +// speculation. It records the root of the compilation: that type 8.196 +// speculation is wrong in the context of one compilation (for 8.197 +// method1) doesn't mean it's wrong in the context of another one (for 8.198 +// method2). Type speculation could have more/different data in the 8.199 +// context of the compilation of method2 and it's worthwhile to try an 8.200 +// optimization that failed for compilation of method1 in the context 8.201 +// of compilation of method2. 8.202 +// Space for SpeculativeTrapData entries is allocated from the extra 8.203 +// data space in the MDO. If we run out of space, the trap data for 8.204 +// the ProfileData at that bci is updated. 8.205 +class SpeculativeTrapData : public ProfileData { 8.206 +protected: 8.207 + enum { 8.208 + method_offset, 8.209 + speculative_trap_cell_count 8.210 + }; 8.211 +public: 8.212 + SpeculativeTrapData(DataLayout* layout) : ProfileData(layout) { 8.213 + assert(layout->tag() == DataLayout::speculative_trap_data_tag, "wrong type"); 8.214 + } 8.215 + 8.216 + virtual bool is_SpeculativeTrapData() const { return true; } 8.217 + 8.218 + static int static_cell_count() { 8.219 + return speculative_trap_cell_count; 8.220 + } 8.221 + 8.222 + virtual int cell_count() const { 8.223 + return static_cell_count(); 8.224 + } 8.225 + 8.226 + // Direct accessor 8.227 + Method* method() const { 8.228 + return (Method*)intptr_at(method_offset); 8.229 + } 8.230 + 8.231 + void set_method(Method* m) { 8.232 + set_intptr_at(method_offset, (intptr_t)m); 8.233 + } 8.234 + 8.235 +#ifndef PRODUCT 8.236 + virtual void print_data_on(outputStream* st, const char* extra = NULL) const; 8.237 +#endif 8.238 +}; 8.239 + 8.240 // MethodData* 8.241 // 8.242 // A MethodData* holds information which has been collected about 8.243 @@ -1803,7 +1865,7 @@ 8.244 8.245 // Whole-method sticky bits and flags 8.246 enum { 8.247 - _trap_hist_limit = 17, // decoupled from Deoptimization::Reason_LIMIT 8.248 + _trap_hist_limit = 18, // decoupled from Deoptimization::Reason_LIMIT 8.249 _trap_hist_mask = max_jubyte, 8.250 _extra_data_count = 4 // extra DataLayout headers, for trap history 8.251 }; // Public flag values 8.252 @@ -1858,6 +1920,7 @@ 8.253 // Helper for size computation 8.254 static int compute_data_size(BytecodeStream* stream); 8.255 static int bytecode_cell_count(Bytecodes::Code code); 8.256 + static bool is_speculative_trap_bytecode(Bytecodes::Code code); 8.257 enum { no_profile_data = -1, variable_cell_count = -2 }; 8.258 8.259 // Helper for initialization 8.260 @@ -1901,8 +1964,9 @@ 8.261 // What is the index of the first data entry? 8.262 int first_di() const { return 0; } 8.263 8.264 + ProfileData* bci_to_extra_data_helper(int bci, Method* m, DataLayout*& dp); 8.265 // Find or create an extra ProfileData: 8.266 - ProfileData* bci_to_extra_data(int bci, bool create_if_missing); 8.267 + ProfileData* bci_to_extra_data(int bci, Method* m, bool create_if_missing); 8.268 8.269 // return the argument info cell 8.270 ArgInfoData *arg_info(); 8.271 @@ -1925,6 +1989,10 @@ 8.272 static bool profile_parameters_jsr292_only(); 8.273 static bool profile_all_parameters(); 8.274 8.275 + void clean_extra_data(BoolObjectClosure* is_alive); 8.276 + void clean_extra_data_helper(DataLayout* dp, int shift, bool reset = false); 8.277 + void verify_extra_data_clean(BoolObjectClosure* is_alive); 8.278 + 8.279 public: 8.280 static int header_size() { 8.281 return sizeof(MethodData)/wordSize; 8.282 @@ -1933,7 +2001,7 @@ 8.283 // Compute the size of a MethodData* before it is created. 8.284 static int compute_allocation_size_in_bytes(methodHandle method); 8.285 static int compute_allocation_size_in_words(methodHandle method); 8.286 - static int compute_extra_data_count(int data_size, int empty_bc_count); 8.287 + static int compute_extra_data_count(int data_size, int empty_bc_count, bool needs_speculative_traps); 8.288 8.289 // Determine if a given bytecode can have profile information. 8.290 static bool bytecode_has_profile(Bytecodes::Code code) { 8.291 @@ -2074,9 +2142,26 @@ 8.292 ProfileData* bci_to_data(int bci); 8.293 8.294 // Same, but try to create an extra_data record if one is needed: 8.295 - ProfileData* allocate_bci_to_data(int bci) { 8.296 - ProfileData* data = bci_to_data(bci); 8.297 - return (data != NULL) ? data : bci_to_extra_data(bci, true); 8.298 + ProfileData* allocate_bci_to_data(int bci, Method* m) { 8.299 + ProfileData* data = NULL; 8.300 + // If m not NULL, try to allocate a SpeculativeTrapData entry 8.301 + if (m == NULL) { 8.302 + data = bci_to_data(bci); 8.303 + } 8.304 + if (data != NULL) { 8.305 + return data; 8.306 + } 8.307 + data = bci_to_extra_data(bci, m, true); 8.308 + if (data != NULL) { 8.309 + return data; 8.310 + } 8.311 + // If SpeculativeTrapData allocation fails try to allocate a 8.312 + // regular entry 8.313 + data = bci_to_data(bci); 8.314 + if (data != NULL) { 8.315 + return data; 8.316 + } 8.317 + return bci_to_extra_data(bci, NULL, true); 8.318 } 8.319 8.320 // Add a handful of extra data records, for trap tracking. 8.321 @@ -2084,7 +2169,7 @@ 8.322 DataLayout* extra_data_limit() const { return (DataLayout*)((address)this + size_in_bytes()); } 8.323 int extra_data_size() const { return (address)extra_data_limit() 8.324 - (address)extra_data_base(); } 8.325 - static DataLayout* next_extra(DataLayout* dp) { return (DataLayout*)((address)dp + in_bytes(DataLayout::cell_offset(0))); } 8.326 + static DataLayout* next_extra(DataLayout* dp); 8.327 8.328 // Return (uint)-1 for overflow. 8.329 uint trap_count(int reason) const { 8.330 @@ -2184,6 +2269,8 @@ 8.331 static bool profile_return(); 8.332 static bool profile_parameters(); 8.333 static bool profile_return_jsr292_only(); 8.334 + 8.335 + void clean_method_data(BoolObjectClosure* is_alive); 8.336 }; 8.337 8.338 #endif // SHARE_VM_OOPS_METHODDATAOOP_HPP
9.1 --- a/src/share/vm/opto/compile.cpp Mon Jan 27 13:14:53 2014 +0100 9.2 +++ b/src/share/vm/opto/compile.cpp Tue Feb 25 18:16:24 2014 +0100 9.3 @@ -3233,7 +3233,8 @@ 9.4 // because of a transient condition during start-up in the interpreter. 9.5 return false; 9.6 } 9.7 - if (md->has_trap_at(bci, reason) != 0) { 9.8 + ciMethod* m = Deoptimization::reason_is_speculate(reason) ? this->method() : NULL; 9.9 + if (md->has_trap_at(bci, m, reason) != 0) { 9.10 // Assume PerBytecodeTrapLimit==0, for a more conservative heuristic. 9.11 // Also, if there are multiple reasons, or if there is no per-BCI record, 9.12 // assume the worst. 9.13 @@ -3251,7 +3252,7 @@ 9.14 // Less-accurate variant which does not require a method and bci. 9.15 bool Compile::too_many_traps(Deoptimization::DeoptReason reason, 9.16 ciMethodData* logmd) { 9.17 - if (trap_count(reason) >= (uint)PerMethodTrapLimit) { 9.18 + if (trap_count(reason) >= Deoptimization::per_method_trap_limit(reason)) { 9.19 // Too many traps globally. 9.20 // Note that we use cumulative trap_count, not just md->trap_count. 9.21 if (log()) { 9.22 @@ -3286,10 +3287,11 @@ 9.23 uint m_cutoff = (uint) PerMethodRecompilationCutoff / 2 + 1; // not zero 9.24 Deoptimization::DeoptReason per_bc_reason 9.25 = Deoptimization::reason_recorded_per_bytecode_if_any(reason); 9.26 + ciMethod* m = Deoptimization::reason_is_speculate(reason) ? this->method() : NULL; 9.27 if ((per_bc_reason == Deoptimization::Reason_none 9.28 - || md->has_trap_at(bci, reason) != 0) 9.29 + || md->has_trap_at(bci, m, reason) != 0) 9.30 // The trap frequency measure we care about is the recompile count: 9.31 - && md->trap_recompiled_at(bci) 9.32 + && md->trap_recompiled_at(bci, m) 9.33 && md->overflow_recompile_count() >= bc_cutoff) { 9.34 // Do not emit a trap here if it has already caused recompilations. 9.35 // Also, if there are multiple reasons, or if there is no per-BCI record,
10.1 --- a/src/share/vm/opto/doCall.cpp Mon Jan 27 13:14:53 2014 +0100 10.2 +++ b/src/share/vm/opto/doCall.cpp Tue Feb 25 18:16:24 2014 +0100 10.3 @@ -250,7 +250,7 @@ 10.4 CallGenerator* miss_cg; 10.5 Deoptimization::DeoptReason reason = morphism == 2 ? 10.6 Deoptimization::Reason_bimorphic : 10.7 - Deoptimization::Reason_class_check; 10.8 + (speculative_receiver_type == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check); 10.9 if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) && 10.10 !too_many_traps(jvms->method(), jvms->bci(), reason) 10.11 ) {
11.1 --- a/src/share/vm/opto/graphKit.cpp Mon Jan 27 13:14:53 2014 +0100 11.2 +++ b/src/share/vm/opto/graphKit.cpp Tue Feb 25 18:16:24 2014 +0100 11.3 @@ -611,9 +611,10 @@ 11.4 // Usual case: Bail to interpreter. 11.5 // Reserve the right to recompile if we haven't seen anything yet. 11.6 11.7 + assert(!Deoptimization::reason_is_speculate(reason), "unsupported"); 11.8 Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile; 11.9 if (treat_throw_as_hot 11.10 - && (method()->method_data()->trap_recompiled_at(bci()) 11.11 + && (method()->method_data()->trap_recompiled_at(bci(), NULL) 11.12 || C->too_many_traps(reason))) { 11.13 // We cannot afford to take more traps here. Suffer in the interpreter. 11.14 if (C->log() != NULL) 11.15 @@ -2141,7 +2142,7 @@ 11.16 * 11.17 * @param n receiver node 11.18 * 11.19 - * @return node with improved type 11.20 + * @return node with improved type 11.21 */ 11.22 Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) { 11.23 if (!UseTypeSpeculation) { 11.24 @@ -2734,12 +2735,14 @@ 11.25 // Subsequent type checks will always fold up. 11.26 Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj, 11.27 ciKlass* require_klass, 11.28 - ciKlass* spec_klass, 11.29 + ciKlass* spec_klass, 11.30 bool safe_for_replace) { 11.31 if (!UseTypeProfile || !TypeProfileCasts) return NULL; 11.32 11.33 + Deoptimization::DeoptReason reason = spec_klass == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check; 11.34 + 11.35 // Make sure we haven't already deoptimized from this tactic. 11.36 - if (too_many_traps(Deoptimization::Reason_class_check)) 11.37 + if (too_many_traps(reason)) 11.38 return NULL; 11.39 11.40 // (No, this isn't a call, but it's enough like a virtual call 11.41 @@ -2761,7 +2764,7 @@ 11.42 &exact_obj); 11.43 { PreserveJVMState pjvms(this); 11.44 set_control(slow_ctl); 11.45 - uncommon_trap(Deoptimization::Reason_class_check, 11.46 + uncommon_trap(reason, 11.47 Deoptimization::Action_maybe_recompile); 11.48 } 11.49 if (safe_for_replace) { 11.50 @@ -2788,8 +2791,10 @@ 11.51 bool not_null) { 11.52 // type == NULL if profiling tells us this object is always null 11.53 if (type != NULL) { 11.54 - if (!too_many_traps(Deoptimization::Reason_null_check) && 11.55 - !too_many_traps(Deoptimization::Reason_class_check)) { 11.56 + Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check; 11.57 + Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check; 11.58 + if (!too_many_traps(null_reason) && 11.59 + !too_many_traps(class_reason)) { 11.60 Node* not_null_obj = NULL; 11.61 // not_null is true if we know the object is not null and 11.62 // there's no need for a null check 11.63 @@ -2808,7 +2813,7 @@ 11.64 { 11.65 PreserveJVMState pjvms(this); 11.66 set_control(slow_ctl); 11.67 - uncommon_trap(Deoptimization::Reason_class_check, 11.68 + uncommon_trap(class_reason, 11.69 Deoptimization::Action_maybe_recompile); 11.70 } 11.71 replace_in_map(not_null_obj, exact_obj); 11.72 @@ -2877,7 +2882,7 @@ 11.73 } 11.74 11.75 if (known_statically && UseTypeSpeculation) { 11.76 - // If we know the type check always succeed then we don't use the 11.77 + // If we know the type check always succeeds then we don't use the 11.78 // profiling data at this bytecode. Don't lose it, feed it to the 11.79 // type system as a speculative type. 11.80 not_null_obj = record_profiled_receiver_for_speculation(not_null_obj);
12.1 --- a/src/share/vm/opto/graphKit.hpp Mon Jan 27 13:14:53 2014 +0100 12.2 +++ b/src/share/vm/opto/graphKit.hpp Tue Feb 25 18:16:24 2014 +0100 12.3 @@ -406,7 +406,7 @@ 12.4 // Use the type profile to narrow an object type. 12.5 Node* maybe_cast_profiled_receiver(Node* not_null_obj, 12.6 ciKlass* require_klass, 12.7 - ciKlass* spec, 12.8 + ciKlass* spec, 12.9 bool safe_for_replace); 12.10 12.11 // Cast obj to type and emit guard unless we had too many traps here already
13.1 --- a/src/share/vm/runtime/deoptimization.cpp Mon Jan 27 13:14:53 2014 +0100 13.2 +++ b/src/share/vm/runtime/deoptimization.cpp Tue Feb 25 18:16:24 2014 +0100 13.3 @@ -1486,6 +1486,7 @@ 13.4 bool maybe_prior_trap = false; 13.5 bool maybe_prior_recompile = false; 13.6 pdata = query_update_method_data(trap_mdo, trap_bci, reason, 13.7 + nm->method(), 13.8 //outputs: 13.9 this_trap_count, 13.10 maybe_prior_trap, 13.11 @@ -1531,7 +1532,7 @@ 13.12 } 13.13 13.14 // Go back to the compiler if there are too many traps in this method. 13.15 - if (this_trap_count >= (uint)PerMethodTrapLimit) { 13.16 + if (this_trap_count >= per_method_trap_limit(reason)) { 13.17 // If there are too many traps in this method, force a recompile. 13.18 // This will allow the compiler to see the limit overflow, and 13.19 // take corrective action, if possible. 13.20 @@ -1619,6 +1620,7 @@ 13.21 Deoptimization::query_update_method_data(MethodData* trap_mdo, 13.22 int trap_bci, 13.23 Deoptimization::DeoptReason reason, 13.24 + Method* compiled_method, 13.25 //outputs: 13.26 uint& ret_this_trap_count, 13.27 bool& ret_maybe_prior_trap, 13.28 @@ -1642,9 +1644,16 @@ 13.29 // Find the profile data for this BCI. If there isn't one, 13.30 // try to allocate one from the MDO's set of spares. 13.31 // This will let us detect a repeated trap at this point. 13.32 - pdata = trap_mdo->allocate_bci_to_data(trap_bci); 13.33 + pdata = trap_mdo->allocate_bci_to_data(trap_bci, reason_is_speculate(reason) ? compiled_method : NULL); 13.34 13.35 if (pdata != NULL) { 13.36 + if (reason_is_speculate(reason) && !pdata->is_SpeculativeTrapData()) { 13.37 + if (LogCompilation && xtty != NULL) { 13.38 + ttyLocker ttyl; 13.39 + // no more room for speculative traps in this MDO 13.40 + xtty->elem("speculative_traps_oom"); 13.41 + } 13.42 + } 13.43 // Query the trap state of this profile datum. 13.44 int tstate0 = pdata->trap_state(); 13.45 if (!trap_state_has_reason(tstate0, per_bc_reason)) 13.46 @@ -1682,8 +1691,10 @@ 13.47 uint ignore_this_trap_count; 13.48 bool ignore_maybe_prior_trap; 13.49 bool ignore_maybe_prior_recompile; 13.50 + assert(!reason_is_speculate(reason), "reason speculate only used by compiler"); 13.51 query_update_method_data(trap_mdo, trap_bci, 13.52 (DeoptReason)reason, 13.53 + NULL, 13.54 ignore_this_trap_count, 13.55 ignore_maybe_prior_trap, 13.56 ignore_maybe_prior_recompile); 13.57 @@ -1811,7 +1822,8 @@ 13.58 "div0_check", 13.59 "age", 13.60 "predicate", 13.61 - "loop_limit_check" 13.62 + "loop_limit_check", 13.63 + "speculate_class_check" 13.64 }; 13.65 const char* Deoptimization::_trap_action_name[Action_LIMIT] = { 13.66 // Note: Keep this in sync. with enum DeoptAction.
14.1 --- a/src/share/vm/runtime/deoptimization.hpp Mon Jan 27 13:14:53 2014 +0100 14.2 +++ b/src/share/vm/runtime/deoptimization.hpp Tue Feb 25 18:16:24 2014 +0100 14.3 @@ -59,6 +59,7 @@ 14.4 Reason_age, // nmethod too old; tier threshold reached 14.5 Reason_predicate, // compiler generated predicate failed 14.6 Reason_loop_limit_check, // compiler generated loop limits check failed 14.7 + Reason_speculate_class_check, // saw unexpected object class from type speculation 14.8 Reason_LIMIT, 14.9 // Note: Keep this enum in sync. with _trap_reason_name. 14.10 Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc 14.11 @@ -311,10 +312,23 @@ 14.12 return reason; 14.13 else if (reason == Reason_div0_check) // null check due to divide-by-zero? 14.14 return Reason_null_check; // recorded per BCI as a null check 14.15 + else if (reason == Reason_speculate_class_check) 14.16 + return Reason_class_check; 14.17 else 14.18 return Reason_none; 14.19 } 14.20 14.21 + static bool reason_is_speculate(int reason) { 14.22 + if (reason == Reason_speculate_class_check) { 14.23 + return true; 14.24 + } 14.25 + return false; 14.26 + } 14.27 + 14.28 + static uint per_method_trap_limit(int reason) { 14.29 + return reason_is_speculate(reason) ? (uint)PerMethodSpecTrapLimit : (uint)PerMethodTrapLimit; 14.30 + } 14.31 + 14.32 static const char* trap_reason_name(int reason); 14.33 static const char* trap_action_name(int action); 14.34 // Format like reason='foo' action='bar' index='123'. 14.35 @@ -337,6 +351,7 @@ 14.36 static ProfileData* query_update_method_data(MethodData* trap_mdo, 14.37 int trap_bci, 14.38 DeoptReason reason, 14.39 + Method* compiled_method, 14.40 //outputs: 14.41 uint& ret_this_trap_count, 14.42 bool& ret_maybe_prior_trap,
15.1 --- a/src/share/vm/runtime/globals.hpp Mon Jan 27 13:14:53 2014 +0100 15.2 +++ b/src/share/vm/runtime/globals.hpp Tue Feb 25 18:16:24 2014 +0100 15.3 @@ -3055,9 +3055,15 @@ 15.4 product(intx, PerMethodTrapLimit, 100, \ 15.5 "Limit on traps (of one kind) in a method (includes inlines)") \ 15.6 \ 15.7 + experimental(intx, PerMethodSpecTrapLimit, 5000, \ 15.8 + "Limit on speculative traps (of one kind) in a method (includes inlines)") \ 15.9 + \ 15.10 product(intx, PerBytecodeTrapLimit, 4, \ 15.11 "Limit on traps (of one kind) at a particular BCI") \ 15.12 \ 15.13 + experimental(intx, SpecTrapLimitExtraEntries, 3, \ 15.14 + "Extra method data trap entries for speculation") \ 15.15 + \ 15.16 develop(intx, InlineFrequencyRatio, 20, \ 15.17 "Ratio of call site execution to caller method invocation") \ 15.18 \
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java Tue Feb 25 18:16:24 2014 +0100 16.3 @@ -0,0 +1,97 @@ 16.4 +/* 16.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 16.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 16.7 + * 16.8 + * This code is free software; you can redistribute it and/or modify it 16.9 + * under the terms of the GNU General Public License version 2 only, as 16.10 + * published by the Free Software Foundation. 16.11 + * 16.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 16.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16.15 + * version 2 for more details (a copy is included in the LICENSE file that 16.16 + * accompanied this code). 16.17 + * 16.18 + * You should have received a copy of the GNU General Public License version 16.19 + * 2 along with this work; if not, write to the Free Software Foundation, 16.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 16.21 + * 16.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 16.23 + * or visit www.oracle.com if you need additional information or have any 16.24 + * questions. 16.25 + */ 16.26 + 16.27 +/* 16.28 + * @test 16.29 + * @bug 8031752 16.30 + * @summary speculative traps need to be cleaned up at GC 16.31 + * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UnlockExperimentalVMOptions -XX:+UseTypeSpeculation -XX:TypeProfileLevel=222 -XX:CompileCommand=exclude,java.lang.reflect.Method::invoke -XX:CompileCommand=exclude,sun.reflect.DelegatingMethodAccessorImpl::invoke -Xmx1M TestSpecTrapClassUnloading 16.32 + * 16.33 + */ 16.34 + 16.35 +import java.lang.reflect.Method; 16.36 + 16.37 +public class TestSpecTrapClassUnloading { 16.38 + static class B { 16.39 + final public boolean m(Object o) { 16.40 + if (o.getClass() == B.class) { 16.41 + return true; 16.42 + } 16.43 + return false; 16.44 + } 16.45 + } 16.46 + 16.47 + static class MemoryChunk { 16.48 + MemoryChunk other; 16.49 + long[] array; 16.50 + MemoryChunk(MemoryChunk other) { 16.51 + other = other; 16.52 + array = new long[1024 * 1024 * 1024]; 16.53 + } 16.54 + } 16.55 + 16.56 + static void m1(B b, Object o) { 16.57 + b.m(o); 16.58 + } 16.59 + 16.60 + static void m2(B b, Object o) { 16.61 + b.m(o); 16.62 + } 16.63 + 16.64 + public static void main(String[] args) throws Exception { 16.65 + Method m = B.class.getMethod("m", Object.class); 16.66 + Object o = new Object(); 16.67 + B b = new B(); 16.68 + 16.69 + // add speculative trap in B.m() for m1 16.70 + for (int i = 0; i < 20000; i++) { 16.71 + m1(b, b); 16.72 + } 16.73 + m1(b, o); 16.74 + 16.75 + // add speculative trap in B.m() for code generated by reflection 16.76 + for (int i = 0; i < 20000; i++) { 16.77 + m.invoke(b, b); 16.78 + } 16.79 + m.invoke(b, o); 16.80 + 16.81 + m = null; 16.82 + 16.83 + // add speculative trap in B.m() for m2 16.84 + for (int i = 0; i < 20000; i++) { 16.85 + m2(b, b); 16.86 + } 16.87 + m2(b, o); 16.88 + 16.89 + // Exhaust memory which causes the code generated by 16.90 + // reflection to be unloaded but B.m() is not. 16.91 + MemoryChunk root = null; 16.92 + try { 16.93 + while (true) { 16.94 + root = new MemoryChunk(root); 16.95 + } 16.96 + } catch(OutOfMemoryError e) { 16.97 + root = null; 16.98 + } 16.99 + } 16.100 +}