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()) {