Mercurial > hg > graal-jvmci-8
comparison src/share/vm/ci/bcEscapeAnalyzer.cpp @ 45:48a3fa21394b
6667615: (Escape Analysis) extend MDO to cache arguments escape state
Summary: Use MDO to cache arguments escape state determined by the byte code escape analyzer.
Reviewed-by: never
author | kvn |
---|---|
date | Tue, 11 Mar 2008 19:00:38 -0700 |
parents | a61af66fc99e |
children | e1e86702e43e |
comparison
equal
deleted
inserted
replaced
44:52fed2ec0afb | 45:48a3fa21394b |
---|---|
102 void lpush() { spush(); spush(); } | 102 void lpush() { spush(); spush(); } |
103 | 103 |
104 }; | 104 }; |
105 | 105 |
106 void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { | 106 void BCEscapeAnalyzer::set_returned(ArgumentMap vars) { |
107 for (int i = 0; i <= _arg_size; i++) { | 107 for (int i = 0; i < _arg_size; i++) { |
108 if (vars.contains(i)) | 108 if (vars.contains(i)) |
109 _arg_returned.set_bit(i); | 109 _arg_returned.set_bit(i); |
110 } | 110 } |
111 _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated()); | 111 _return_local = _return_local && !(vars.contains_unknown() || vars.contains_allocated()); |
112 _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars()); | 112 _return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars()); |
113 } | 113 } |
114 | 114 |
115 | |
116 // return true if any element of vars is an argument | 115 // return true if any element of vars is an argument |
117 bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) { | 116 bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) { |
118 for (int i = 0; i <= _arg_size; i++) { | 117 for (int i = 0; i < _arg_size; i++) { |
119 if (vars.contains(i)) | 118 if (vars.contains(i)) |
120 return true; | 119 return true; |
121 } | 120 } |
122 return false; | 121 return false; |
123 } | 122 } |
124 | 123 |
125 // return true if any element of vars is an arg_stack argument | 124 // return true if any element of vars is an arg_stack argument |
126 bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ | 125 bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){ |
127 if (_conservative) | 126 if (_conservative) |
128 return true; | 127 return true; |
129 for (int i = 0; i <= _arg_size; i++) { | 128 for (int i = 0; i < _arg_size; i++) { |
130 if (vars.contains(i) && _arg_stack.at(i)) | 129 if (vars.contains(i) && _arg_stack.at(i)) |
131 return true; | 130 return true; |
132 } | 131 } |
133 return false; | 132 return false; |
134 } | 133 } |
135 | 134 |
136 void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) { | 135 void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) { |
137 for (int i = 0; i <= _arg_size; i++) { | 136 for (int i = 0; i < _arg_size; i++) { |
138 if (vars.contains(i)) { | 137 if (vars.contains(i)) { |
139 bm.clear_bit(i); | 138 bm.clear_bit(i); |
140 } | 139 } |
141 } | 140 } |
142 } | 141 } |
142 | |
143 void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) { | 143 void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) { |
144 clear_bits(vars, _arg_local); | 144 clear_bits(vars, _arg_local); |
145 } | 145 } |
146 | 146 |
147 void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars) { | 147 void BCEscapeAnalyzer::set_global_escape(ArgumentMap vars) { |
153 | 153 |
154 void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) { | 154 void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) { |
155 clear_bits(vars, _dirty); | 155 clear_bits(vars, _dirty); |
156 } | 156 } |
157 | 157 |
158 void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) { | |
159 | |
160 for (int i = 0; i < _arg_size; i++) { | |
161 if (vars.contains(i)) { | |
162 set_arg_modified(i, offs, size); | |
163 } | |
164 } | |
165 if (vars.contains_unknown()) | |
166 _unknown_modified = true; | |
167 } | |
168 | |
158 bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) { | 169 bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) { |
159 for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) { | 170 for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) { |
160 if (scope->method() == callee) { | 171 if (scope->method() == callee) { |
161 return true; | 172 return true; |
162 } | 173 } |
163 } | 174 } |
164 return false; | 175 return false; |
176 } | |
177 | |
178 bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) { | |
179 if (offset == OFFSET_ANY) | |
180 return _arg_modified[arg] != 0; | |
181 assert(arg >= 0 && arg < _arg_size, "must be an argument."); | |
182 bool modified = false; | |
183 int l = offset / HeapWordSize; | |
184 int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize; | |
185 if (l > ARG_OFFSET_MAX) | |
186 l = ARG_OFFSET_MAX; | |
187 if (h > ARG_OFFSET_MAX+1) | |
188 h = ARG_OFFSET_MAX + 1; | |
189 for (int i = l; i < h; i++) { | |
190 modified = modified || (_arg_modified[arg] & (1 << i)) != 0; | |
191 } | |
192 return modified; | |
193 } | |
194 | |
195 void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) { | |
196 if (offset == OFFSET_ANY) { | |
197 _arg_modified[arg] = (uint) -1; | |
198 return; | |
199 } | |
200 assert(arg >= 0 && arg < _arg_size, "must be an argument."); | |
201 int l = offset / HeapWordSize; | |
202 int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize; | |
203 if (l > ARG_OFFSET_MAX) | |
204 l = ARG_OFFSET_MAX; | |
205 if (h > ARG_OFFSET_MAX+1) | |
206 h = ARG_OFFSET_MAX + 1; | |
207 for (int i = l; i < h; i++) { | |
208 _arg_modified[arg] |= (1 << i); | |
209 } | |
165 } | 210 } |
166 | 211 |
167 void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) { | 212 void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) { |
168 int i; | 213 int i; |
169 | 214 |
195 if (skip_callee) { | 240 if (skip_callee) { |
196 TRACE_BCEA(3, tty->print_cr("[EA] skipping method %s::%s", holder->name()->as_utf8(), target->name()->as_utf8())); | 241 TRACE_BCEA(3, tty->print_cr("[EA] skipping method %s::%s", holder->name()->as_utf8(), target->name()->as_utf8())); |
197 for (i = 0; i < arg_size; i++) { | 242 for (i = 0; i < arg_size; i++) { |
198 set_method_escape(state.raw_pop()); | 243 set_method_escape(state.raw_pop()); |
199 } | 244 } |
245 _unknown_modified = true; // assume the worst since we don't analyze the called method | |
200 return; | 246 return; |
201 } | 247 } |
202 | 248 |
203 // determine actual method (use CHA if necessary) | 249 // determine actual method (use CHA if necessary) |
204 ciMethod* inline_target = NULL; | 250 ciMethod* inline_target = NULL; |
222 bool must_record_dependencies = false; | 268 bool must_record_dependencies = false; |
223 for (i = arg_size - 1; i >= 0; i--) { | 269 for (i = arg_size - 1; i >= 0; i--) { |
224 ArgumentMap arg = state.raw_pop(); | 270 ArgumentMap arg = state.raw_pop(); |
225 if (!is_argument(arg)) | 271 if (!is_argument(arg)) |
226 continue; | 272 continue; |
273 for (int j = 0; j < _arg_size; j++) { | |
274 if (arg.contains(j)) { | |
275 _arg_modified[j] |= analyzer._arg_modified[i]; | |
276 } | |
277 } | |
227 if (!is_arg_stack(arg)) { | 278 if (!is_arg_stack(arg)) { |
228 // arguments have already been recognized as escaping | 279 // arguments have already been recognized as escaping |
229 } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { | 280 } else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) { |
230 set_method_escape(arg); | 281 set_method_escape(arg); |
231 must_record_dependencies = true; | 282 must_record_dependencies = true; |
232 } else { | 283 } else { |
233 set_global_escape(arg); | 284 set_global_escape(arg); |
234 } | 285 } |
235 } | 286 } |
287 _unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects(); | |
236 | 288 |
237 // record dependencies if at least one parameter retained stack-allocatable | 289 // record dependencies if at least one parameter retained stack-allocatable |
238 if (must_record_dependencies) { | 290 if (must_record_dependencies) { |
239 if (code == Bytecodes::_invokeinterface || code == Bytecodes::_invokevirtual && !target->is_final_method()) { | 291 if (code == Bytecodes::_invokeinterface || code == Bytecodes::_invokevirtual && !target->is_final_method()) { |
240 _dependencies.append(actual_recv); | 292 _dependencies.append(actual_recv); |
248 // conservatively mark all actual parameters as escaping globally | 300 // conservatively mark all actual parameters as escaping globally |
249 for (i = 0; i < arg_size; i++) { | 301 for (i = 0; i < arg_size; i++) { |
250 ArgumentMap arg = state.raw_pop(); | 302 ArgumentMap arg = state.raw_pop(); |
251 if (!is_argument(arg)) | 303 if (!is_argument(arg)) |
252 continue; | 304 continue; |
305 set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize); | |
253 set_global_escape(arg); | 306 set_global_escape(arg); |
254 } | 307 } |
308 _unknown_modified = true; // assume the worst since we don't know the called method | |
255 } | 309 } |
256 } | 310 } |
257 | 311 |
258 bool BCEscapeAnalyzer::contains(uint arg_set1, uint arg_set2) { | 312 bool BCEscapeAnalyzer::contains(uint arg_set1, uint arg_set2) { |
259 return ((~arg_set1) | arg_set2) == 0; | 313 return ((~arg_set1) | arg_set2) == 0; |
419 { | 473 { |
420 state.spop(); | 474 state.spop(); |
421 state.spop(); | 475 state.spop(); |
422 ArgumentMap arr = state.apop(); | 476 ArgumentMap arr = state.apop(); |
423 set_method_escape(arr); | 477 set_method_escape(arr); |
478 set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize); | |
424 break; | 479 break; |
425 } | 480 } |
426 case Bytecodes::_lastore: | 481 case Bytecodes::_lastore: |
427 case Bytecodes::_dastore: | 482 case Bytecodes::_dastore: |
428 { | 483 { |
429 state.lpop(); | 484 state.lpop(); |
430 state.spop(); | 485 state.spop(); |
431 ArgumentMap arr = state.apop(); | 486 ArgumentMap arr = state.apop(); |
432 set_method_escape(arr); | 487 set_method_escape(arr); |
488 set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize); | |
433 break; | 489 break; |
434 } | 490 } |
435 case Bytecodes::_aastore: | 491 case Bytecodes::_aastore: |
436 { | 492 { |
437 set_global_escape(state.apop()); | 493 set_global_escape(state.apop()); |
438 state.spop(); | 494 state.spop(); |
439 ArgumentMap arr = state.apop(); | 495 ArgumentMap arr = state.apop(); |
496 set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize); | |
440 break; | 497 break; |
441 } | 498 } |
442 case Bytecodes::_pop: | 499 case Bytecodes::_pop: |
443 state.raw_pop(); | 500 state.raw_pop(); |
444 break; | 501 break; |
760 state.lpop(); | 817 state.lpop(); |
761 } | 818 } |
762 if (s.cur_bc() != Bytecodes::_putstatic) { | 819 if (s.cur_bc() != Bytecodes::_putstatic) { |
763 ArgumentMap p = state.apop(); | 820 ArgumentMap p = state.apop(); |
764 set_method_escape(p); | 821 set_method_escape(p); |
822 set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize); | |
765 } | 823 } |
766 } | 824 } |
767 break; | 825 break; |
768 case Bytecodes::_invokevirtual: | 826 case Bytecodes::_invokevirtual: |
769 case Bytecodes::_invokespecial: | 827 case Bytecodes::_invokespecial: |
870 } | 928 } |
871 } | 929 } |
872 } | 930 } |
873 | 931 |
874 void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) { | 932 void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) { |
875 StateInfo *d_state = blockstates+dest->index(); | 933 StateInfo *d_state = blockstates + dest->index(); |
876 int nlocals = _method->max_locals(); | 934 int nlocals = _method->max_locals(); |
877 | 935 |
878 // exceptions may cause transfer of control to handlers in the middle of a | 936 // exceptions may cause transfer of control to handlers in the middle of a |
879 // block, so we don't merge the incoming state of exception handlers | 937 // block, so we don't merge the incoming state of exception handlers |
880 if (dest->is_handler()) | 938 if (dest->is_handler()) |
914 t.set_difference(d_state->_vars[i]); | 972 t.set_difference(d_state->_vars[i]); |
915 extra_vars.set_union(t); | 973 extra_vars.set_union(t); |
916 } | 974 } |
917 for (int i = 0; i < s_state->_stack_height; i++) { | 975 for (int i = 0; i < s_state->_stack_height; i++) { |
918 ArgumentMap t; | 976 ArgumentMap t; |
977 //extra_vars |= !d_state->_vars[i] & s_state->_vars[i]; | |
919 t.clear(); | 978 t.clear(); |
920 t = s_state->_stack[i]; | 979 t = s_state->_stack[i]; |
921 t.set_difference(d_state->_stack[i]); | 980 t.set_difference(d_state->_stack[i]); |
922 extra_vars.set_union(t); | 981 extra_vars.set_union(t); |
923 } | 982 } |
931 int numLocals = _method->max_locals(); | 990 int numLocals = _method->max_locals(); |
932 StateInfo state; | 991 StateInfo state; |
933 | 992 |
934 int datacount = (numblocks + 1) * (stkSize + numLocals); | 993 int datacount = (numblocks + 1) * (stkSize + numLocals); |
935 int datasize = datacount * sizeof(ArgumentMap); | 994 int datasize = datacount * sizeof(ArgumentMap); |
936 StateInfo *blockstates = (StateInfo *) arena->Amalloc(_methodBlocks->num_blocks() * sizeof(StateInfo)); | 995 StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo)); |
937 ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize); | 996 ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize); |
938 for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap(); | 997 for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap(); |
939 ArgumentMap *dp = statedata; | 998 ArgumentMap *dp = statedata; |
940 state._vars = dp; | 999 state._vars = dp; |
941 dp += numLocals; | 1000 dp += numLocals; |
959 | 1018 |
960 // initialize block 0 state from method signature | 1019 // initialize block 0 state from method signature |
961 ArgumentMap allVars; // all oop arguments to method | 1020 ArgumentMap allVars; // all oop arguments to method |
962 ciSignature* sig = method()->signature(); | 1021 ciSignature* sig = method()->signature(); |
963 int j = 0; | 1022 int j = 0; |
1023 ciBlock* first_blk = _methodBlocks->block_containing(0); | |
1024 int fb_i = first_blk->index(); | |
964 if (!method()->is_static()) { | 1025 if (!method()->is_static()) { |
965 // record information for "this" | 1026 // record information for "this" |
966 blockstates[0]._vars[j].set(j); | 1027 blockstates[fb_i]._vars[j].set(j); |
967 allVars.add(j); | 1028 allVars.add(j); |
968 j++; | 1029 j++; |
969 } | 1030 } |
970 for (int i = 0; i < sig->count(); i++) { | 1031 for (int i = 0; i < sig->count(); i++) { |
971 ciType* t = sig->type_at(i); | 1032 ciType* t = sig->type_at(i); |
972 if (!t->is_primitive_type()) { | 1033 if (!t->is_primitive_type()) { |
973 blockstates[0]._vars[j].set(j); | 1034 blockstates[fb_i]._vars[j].set(j); |
974 allVars.add(j); | 1035 allVars.add(j); |
975 } | 1036 } |
976 j += t->size(); | 1037 j += t->size(); |
977 } | 1038 } |
978 blockstates[0]._initialized = true; | 1039 blockstates[fb_i]._initialized = true; |
979 assert(j == _arg_size, "just checking"); | 1040 assert(j == _arg_size, "just checking"); |
980 | 1041 |
981 ArgumentMap unknown_map; | 1042 ArgumentMap unknown_map; |
982 unknown_map.add_unknown(); | 1043 unknown_map.add_unknown(); |
983 | 1044 |
984 worklist.push(_methodBlocks->block_containing(0)); | 1045 worklist.push(first_blk); |
985 while(worklist.length() > 0) { | 1046 while(worklist.length() > 0) { |
986 ciBlock *blk = worklist.pop(); | 1047 ciBlock *blk = worklist.pop(); |
987 StateInfo *blkState = blockstates+blk->index(); | 1048 StateInfo *blkState = blockstates + blk->index(); |
988 if (blk->is_handler() || blk->is_ret_target()) { | 1049 if (blk->is_handler() || blk->is_ret_target()) { |
989 // for an exception handler or a target of a ret instruction, we assume the worst case, | 1050 // for an exception handler or a target of a ret instruction, we assume the worst case, |
990 // that any variable or stack slot could contain any argument | 1051 // that any variable could contain any argument |
991 for (int i = 0; i < numLocals; i++) { | 1052 for (int i = 0; i < numLocals; i++) { |
992 state._vars[i] = allVars; | 1053 state._vars[i] = allVars; |
993 } | 1054 } |
994 if (blk->is_handler()) { | 1055 if (blk->is_handler()) { |
995 state._stack_height = 1; | 1056 state._stack_height = 1; |
996 } else { | 1057 } else { |
997 state._stack_height = blkState->_stack_height; | 1058 state._stack_height = blkState->_stack_height; |
998 } | 1059 } |
999 for (int i = 0; i < state._stack_height; i++) { | 1060 for (int i = 0; i < state._stack_height; i++) { |
1061 // ??? should this be unknown_map ??? | |
1000 state._stack[i] = allVars; | 1062 state._stack[i] = allVars; |
1001 } | 1063 } |
1002 } else { | 1064 } else { |
1003 for (int i = 0; i < numLocals; i++) { | 1065 for (int i = 0; i < numLocals; i++) { |
1004 state._vars[i] = blkState->_vars[i]; | 1066 state._vars[i] = blkState->_vars[i]; |
1051 | 1113 |
1052 vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() { | 1114 vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() { |
1053 vmIntrinsics::ID iid = method()->intrinsic_id(); | 1115 vmIntrinsics::ID iid = method()->intrinsic_id(); |
1054 | 1116 |
1055 if (iid == vmIntrinsics::_getClass || | 1117 if (iid == vmIntrinsics::_getClass || |
1118 iid == vmIntrinsics::_fillInStackTrace || | |
1056 iid == vmIntrinsics::_hashCode) | 1119 iid == vmIntrinsics::_hashCode) |
1057 return iid; | 1120 return iid; |
1058 else | 1121 else |
1059 return vmIntrinsics::_none; | 1122 return vmIntrinsics::_none; |
1060 } | 1123 } |
1061 | 1124 |
1062 bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) { | 1125 bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) { |
1063 ArgumentMap empty; | 1126 ArgumentMap arg; |
1064 empty.clear(); | 1127 arg.clear(); |
1065 switch (iid) { | 1128 switch (iid) { |
1066 case vmIntrinsics::_getClass: | 1129 case vmIntrinsics::_getClass: |
1067 _return_local = false; | 1130 _return_local = false; |
1131 break; | |
1132 case vmIntrinsics::_fillInStackTrace: | |
1133 arg.set(0); // 'this' | |
1134 set_returned(arg); | |
1068 break; | 1135 break; |
1069 case vmIntrinsics::_hashCode: | 1136 case vmIntrinsics::_hashCode: |
1070 // initialized state is correct | 1137 // initialized state is correct |
1071 break; | 1138 break; |
1072 default: | 1139 default: |
1107 } else { | 1174 } else { |
1108 _return_local = true; | 1175 _return_local = true; |
1109 _return_allocated = true; | 1176 _return_allocated = true; |
1110 } | 1177 } |
1111 _allocated_escapes = false; | 1178 _allocated_escapes = false; |
1179 _unknown_modified = false; | |
1112 } | 1180 } |
1113 | 1181 |
1114 void BCEscapeAnalyzer::clear_escape_info() { | 1182 void BCEscapeAnalyzer::clear_escape_info() { |
1115 ciSignature* sig = method()->signature(); | 1183 ciSignature* sig = method()->signature(); |
1116 int arg_count = sig->count(); | 1184 int arg_count = sig->count(); |
1117 ArgumentMap var; | 1185 ArgumentMap var; |
1186 if (!method()->is_static()) { | |
1187 arg_count++; // allow for "this" | |
1188 } | |
1118 for (int i = 0; i < arg_count; i++) { | 1189 for (int i = 0; i < arg_count; i++) { |
1190 set_arg_modified(i, OFFSET_ANY, 4); | |
1119 var.clear(); | 1191 var.clear(); |
1120 var.set(i); | 1192 var.set(i); |
1193 set_modified(var, OFFSET_ANY, 4); | |
1121 set_global_escape(var); | 1194 set_global_escape(var); |
1122 } | 1195 } |
1123 _arg_local.clear(); | 1196 _arg_local.clear(); |
1124 _arg_stack.clear(); | 1197 _arg_stack.clear(); |
1125 _arg_returned.clear(); | 1198 _arg_returned.clear(); |
1126 _return_local = false; | 1199 _return_local = false; |
1127 _return_allocated = false; | 1200 _return_allocated = false; |
1128 _allocated_escapes = true; | 1201 _allocated_escapes = true; |
1202 _unknown_modified = true; | |
1129 } | 1203 } |
1130 | 1204 |
1131 | 1205 |
1132 void BCEscapeAnalyzer::compute_escape_info() { | 1206 void BCEscapeAnalyzer::compute_escape_info() { |
1133 int i; | 1207 int i; |
1203 } else if (is_return_allocated()) { | 1277 } else if (is_return_allocated()) { |
1204 tty->print_cr(" allocated return values"); | 1278 tty->print_cr(" allocated return values"); |
1205 } else { | 1279 } else { |
1206 tty->print_cr(" non-local return values"); | 1280 tty->print_cr(" non-local return values"); |
1207 } | 1281 } |
1282 tty->print(" modified args: "); | |
1283 for (int i = 0; i < _arg_size; i++) { | |
1284 if (_arg_modified[i] == 0) | |
1285 tty->print(" 0"); | |
1286 else | |
1287 tty->print(" 0x%x", _arg_modified[i]); | |
1288 } | |
1208 tty->cr(); | 1289 tty->cr(); |
1209 tty->print(" flags: "); | 1290 tty->print(" flags: "); |
1291 if (_unknown_modified) | |
1292 tty->print(" unknown_modified"); | |
1210 if (_return_allocated) | 1293 if (_return_allocated) |
1211 tty->print(" return_allocated"); | 1294 tty->print(" return_allocated"); |
1212 tty->cr(); | 1295 tty->cr(); |
1213 } | 1296 } |
1214 | 1297 |
1226 methodData()->set_arg_stack(i); | 1309 methodData()->set_arg_stack(i); |
1227 } | 1310 } |
1228 if (_arg_returned.at(i)) { | 1311 if (_arg_returned.at(i)) { |
1229 methodData()->set_arg_returned(i); | 1312 methodData()->set_arg_returned(i); |
1230 } | 1313 } |
1314 methodData()->set_arg_modified(i, _arg_modified[i]); | |
1231 } | 1315 } |
1232 if (_return_local) { | 1316 if (_return_local) { |
1233 methodData()->set_eflag(methodDataOopDesc::return_local); | 1317 methodData()->set_eflag(methodDataOopDesc::return_local); |
1234 } | 1318 } |
1235 methodData()->set_eflag(methodDataOopDesc::estimated); | 1319 methodData()->set_eflag(methodDataOopDesc::estimated); |
1242 // read escape information from method descriptor | 1326 // read escape information from method descriptor |
1243 for (int i = 0; i < _arg_size; i++) { | 1327 for (int i = 0; i < _arg_size; i++) { |
1244 _arg_local.at_put(i, methodData()->is_arg_local(i)); | 1328 _arg_local.at_put(i, methodData()->is_arg_local(i)); |
1245 _arg_stack.at_put(i, methodData()->is_arg_stack(i)); | 1329 _arg_stack.at_put(i, methodData()->is_arg_stack(i)); |
1246 _arg_returned.at_put(i, methodData()->is_arg_returned(i)); | 1330 _arg_returned.at_put(i, methodData()->is_arg_returned(i)); |
1331 _arg_modified[i] = methodData()->arg_modified(i); | |
1247 } | 1332 } |
1248 _return_local = methodData()->eflag_set(methodDataOopDesc::return_local); | 1333 _return_local = methodData()->eflag_set(methodDataOopDesc::return_local); |
1249 | 1334 |
1250 // dump result of loaded escape information | 1335 // dump result of loaded escape information |
1251 #ifndef PRODUCT | 1336 #ifndef PRODUCT |
1259 _arg_returned.print_on(tty); | 1344 _arg_returned.print_on(tty); |
1260 } else { | 1345 } else { |
1261 tty->print_cr(" non-local return values"); | 1346 tty->print_cr(" non-local return values"); |
1262 } | 1347 } |
1263 tty->print(" modified args: "); | 1348 tty->print(" modified args: "); |
1349 for (int i = 0; i < _arg_size; i++) { | |
1350 if (_arg_modified[i] == 0) | |
1351 tty->print(" 0"); | |
1352 else | |
1353 tty->print(" 0x%x", _arg_modified[i]); | |
1354 } | |
1264 tty->cr(); | 1355 tty->cr(); |
1265 } | 1356 } |
1266 #endif | 1357 #endif |
1267 | 1358 |
1268 } | 1359 } |
1279 , _arg_returned(_arg_size) | 1370 , _arg_returned(_arg_size) |
1280 , _dirty(_arg_size) | 1371 , _dirty(_arg_size) |
1281 , _return_local(false) | 1372 , _return_local(false) |
1282 , _return_allocated(false) | 1373 , _return_allocated(false) |
1283 , _allocated_escapes(false) | 1374 , _allocated_escapes(false) |
1375 , _unknown_modified(false) | |
1284 , _dependencies() | 1376 , _dependencies() |
1285 , _parent(parent) | 1377 , _parent(parent) |
1286 , _level(parent == NULL ? 0 : parent->level() + 1) { | 1378 , _level(parent == NULL ? 0 : parent->level() + 1) { |
1287 if (!_conservative) { | 1379 if (!_conservative) { |
1288 _arg_local.clear(); | 1380 _arg_local.clear(); |
1289 _arg_stack.clear(); | 1381 _arg_stack.clear(); |
1290 _arg_returned.clear(); | 1382 _arg_returned.clear(); |
1291 _dirty.clear(); | 1383 _dirty.clear(); |
1292 Arena* arena = CURRENT_ENV->arena(); | 1384 Arena* arena = CURRENT_ENV->arena(); |
1385 _arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint)); | |
1386 Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint)); | |
1293 | 1387 |
1294 if (methodData() == NULL) | 1388 if (methodData() == NULL) |
1295 return; | 1389 return; |
1296 bool printit = _method->should_print_assembly(); | 1390 bool printit = _method->should_print_assembly(); |
1297 if (methodData()->has_escape_info()) { | 1391 if (methodData()->has_escape_info()) { |