1 /* 2 * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. 3 * Copyright 2008, 2009 Red Hat, Inc. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 // Class hierarchy: 27 // - SharkStateScanner 28 // - SharkCacherDecacher 29 // - SharkDecacher 30 // - SharkJavaCallDecacher 31 // - SharkVMCallDecacher 32 // - SharkTrapDecacher 33 // - SharkCacher 34 // - SharkJavaCallCacher 35 // - SharkVMCallCacher 36 // - SharkFunctionEntryCacher 37 // - SharkNormalEntryCacher 38 // - SharkOSREntryCacher 39 40 class SharkCacherDecacher : public SharkStateScanner { 41 protected: 42 SharkCacherDecacher(SharkFunction* function) 43 : SharkStateScanner(function) {} 44 45 // Helper 46 protected: 47 static int adjusted_offset(SharkValue* value, int offset) { 48 if (value->is_two_word()) 49 offset--; 50 return offset; 51 } 52 }; 53 54 class SharkDecacher : public SharkCacherDecacher { 55 protected: 56 SharkDecacher(SharkFunction* function, int bci) 57 : SharkCacherDecacher(function), _bci(bci) {} 58 59 private: 60 int _bci; 61 62 protected: 63 int bci() const { 64 return _bci; 65 } 66 67 private: 68 int _pc_offset; 69 OopMap* _oopmap; 70 GrowableArray<ScopeValue*>* _exparray; 71 GrowableArray<MonitorValue*>* _monarray; 72 GrowableArray<ScopeValue*>* _locarray; 73 74 private: 75 int pc_offset() const { 76 return _pc_offset; 77 } 78 OopMap* oopmap() const { 79 return _oopmap; 80 } 81 GrowableArray<ScopeValue*>* exparray() const { 82 return _exparray; 83 } 84 GrowableArray<MonitorValue*>* monarray() const { 85 return _monarray; 86 } 87 GrowableArray<ScopeValue*>* locarray() const { 88 return _locarray; 89 } 90 91 // Callbacks 92 protected: 93 void start_frame(); 94 95 void start_stack(int stack_depth); 96 void process_stack_slot(int index, SharkValue** value, int offset); 97 98 void start_monitors(int num_monitors); 99 void process_monitor(int index, int box_offset, int obj_offset); 100 101 void process_oop_tmp_slot(llvm::Value** value, int offset); 102 void process_method_slot(llvm::Value** value, int offset); 103 void process_pc_slot(int offset); 104 105 void start_locals(); 106 void process_local_slot(int index, SharkValue** value, int offset); 107 108 void end_frame(); 109 110 // oopmap and debuginfo helpers 111 private: 112 static int oopmap_slot_munge(int offset) { 113 return SharkStack::oopmap_slot_munge(offset); 114 } 115 static VMReg slot2reg(int offset) { 116 return SharkStack::slot2reg(offset); 117 } 118 static Location slot2loc(int offset, Location::Type type) { 119 return Location::new_stk_loc(type, offset * wordSize); 120 } 121 static LocationValue* slot2lv(int offset, Location::Type type) { 122 return new LocationValue(slot2loc(offset, type)); 123 } 124 static Location::Type location_type(SharkValue** addr, bool maybe_two_word) { 125 // low addresses this end 126 // Type 32-bit 64-bit 127 // ---------------------------------------------------- 128 // stack[0] local[3] jobject oop oop 129 // stack[1] local[2] NULL normal lng 130 // stack[2] local[1] jlong normal invalid 131 // stack[3] local[0] jint normal normal 132 // 133 // high addresses this end 134 135 SharkValue *value = *addr; 136 if (value) { 137 if (value->is_jobject()) 138 return Location::oop; 139 #ifdef _LP64 140 if (value->is_two_word()) 141 return Location::invalid; 142 #endif // _LP64 143 return Location::normal; 144 } 145 else { 146 if (maybe_two_word) { 147 value = *(addr - 1); 148 if (value && value->is_two_word()) { 149 #ifdef _LP64 150 if (value->is_jlong()) 151 return Location::lng; 152 if (value->is_jdouble()) 153 return Location::dbl; 154 ShouldNotReachHere(); 155 #else 156 return Location::normal; 157 #endif // _LP64 158 } 159 } 160 return Location::invalid; 161 } 162 } 163 164 // Stack slot helpers 165 protected: 166 virtual bool stack_slot_needs_write(int index, SharkValue* value) = 0; 167 virtual bool stack_slot_needs_oopmap(int index, SharkValue* value) = 0; 168 virtual bool stack_slot_needs_debuginfo(int index, SharkValue* value) = 0; 169 170 static Location::Type stack_location_type(int index, SharkValue** addr) { 171 return location_type(addr, *addr == NULL); 172 } 173 174 // Local slot helpers 175 protected: 176 virtual bool local_slot_needs_write(int index, SharkValue* value) = 0; 177 virtual bool local_slot_needs_oopmap(int index, SharkValue* value) = 0; 178 virtual bool local_slot_needs_debuginfo(int index, SharkValue* value) = 0; 179 180 static Location::Type local_location_type(int index, SharkValue** addr) { 181 return location_type(addr, index > 0); 182 } 183 184 // Writer helper 185 protected: 186 void write_value_to_frame(const llvm::Type* type, 187 llvm::Value* value, 188 int offset); 189 }; 190 191 class SharkJavaCallDecacher : public SharkDecacher { 192 public: 193 SharkJavaCallDecacher(SharkFunction* function, int bci, ciMethod* callee) 194 : SharkDecacher(function, bci), _callee(callee) {} 195 196 private: 197 ciMethod* _callee; 198 199 protected: 200 ciMethod* callee() const { 201 return _callee; 202 } 203 204 // Stack slot helpers 205 protected: 206 bool stack_slot_needs_write(int index, SharkValue* value) { 207 return value && (index < callee()->arg_size() || value->is_jobject()); 208 } 209 bool stack_slot_needs_oopmap(int index, SharkValue* value) { 210 return value && value->is_jobject() && index >= callee()->arg_size(); 211 } 212 bool stack_slot_needs_debuginfo(int index, SharkValue* value) { 213 return index >= callee()->arg_size(); 214 } 215 216 // Local slot helpers 217 protected: 218 bool local_slot_needs_write(int index, SharkValue* value) { 219 return value && value->is_jobject(); 220 } 221 bool local_slot_needs_oopmap(int index, SharkValue* value) { 222 return value && value->is_jobject(); 223 } 224 bool local_slot_needs_debuginfo(int index, SharkValue* value) { 225 return true; 226 } 227 }; 228 229 class SharkVMCallDecacher : public SharkDecacher { 230 public: 231 SharkVMCallDecacher(SharkFunction* function, int bci) 232 : SharkDecacher(function, bci) {} 233 234 // Stack slot helpers 235 protected: 236 bool stack_slot_needs_write(int index, SharkValue* value) { 237 return value && value->is_jobject(); 238 } 239 bool stack_slot_needs_oopmap(int index, SharkValue* value) { 240 return value && value->is_jobject(); 241 } 242 bool stack_slot_needs_debuginfo(int index, SharkValue* value) { 243 return true; 244 } 245 246 // Local slot helpers 247 protected: 248 bool local_slot_needs_write(int index, SharkValue* value) { 249 return value && value->is_jobject(); 250 } 251 bool local_slot_needs_oopmap(int index, SharkValue* value) { 252 return value && value->is_jobject(); 253 } 254 bool local_slot_needs_debuginfo(int index, SharkValue* value) { 255 return true; 256 } 257 }; 258 259 class SharkTrapDecacher : public SharkDecacher { 260 public: 261 SharkTrapDecacher(SharkFunction* function, int bci) 262 : SharkDecacher(function, bci) {} 263 264 // Stack slot helpers 265 protected: 266 bool stack_slot_needs_write(int index, SharkValue* value) { 267 return value != NULL; 268 } 269 bool stack_slot_needs_oopmap(int index, SharkValue* value) { 270 return value && value->is_jobject(); 271 } 272 bool stack_slot_needs_debuginfo(int index, SharkValue* value) { 273 return true; 274 } 275 276 // Local slot helpers 277 protected: 278 bool local_slot_needs_write(int index, SharkValue* value) { 279 return value != NULL; 280 } 281 bool local_slot_needs_oopmap(int index, SharkValue* value) { 282 return value && value->is_jobject(); 283 } 284 bool local_slot_needs_debuginfo(int index, SharkValue* value) { 285 return true; 286 } 287 }; 288 289 class SharkCacher : public SharkCacherDecacher { 290 protected: 291 SharkCacher(SharkFunction* function) 292 : SharkCacherDecacher(function) {} 293 294 // Callbacks 295 protected: 296 void process_stack_slot(int index, SharkValue** value, int offset); 297 298 void process_oop_tmp_slot(llvm::Value** value, int offset); 299 virtual void process_method_slot(llvm::Value** value, int offset); 300 301 virtual void process_local_slot(int index, SharkValue** value, int offset); 302 303 // Stack slot helper 304 protected: 305 virtual bool stack_slot_needs_read(int index, SharkValue* value) = 0; 306 307 // Local slot helper 308 protected: 309 virtual bool local_slot_needs_read(int index, SharkValue* value) { 310 return value && value->is_jobject(); 311 } 312 313 // Writer helper 314 protected: 315 llvm::Value* read_value_from_frame(const llvm::Type* type, int offset); 316 }; 317 318 class SharkJavaCallCacher : public SharkCacher { 319 public: 320 SharkJavaCallCacher(SharkFunction* function, ciMethod* callee) 321 : SharkCacher(function), _callee(callee) {} 322 323 private: 324 ciMethod* _callee; 325 326 protected: 327 ciMethod* callee() const { 328 return _callee; 329 } 330 331 // Stack slot helper 332 protected: 333 bool stack_slot_needs_read(int index, SharkValue* value) { 334 return value && (index < callee()->return_type()->size() || 335 value->is_jobject()); 336 } 337 }; 338 339 class SharkVMCallCacher : public SharkCacher { 340 public: 341 SharkVMCallCacher(SharkFunction* function) 342 : SharkCacher(function) {} 343 344 // Stack slot helper 345 protected: 346 bool stack_slot_needs_read(int index, SharkValue* value) { 347 return value && value->is_jobject(); 348 } 349 }; 350 351 class SharkFunctionEntryCacher : public SharkCacher { 352 public: 353 SharkFunctionEntryCacher(SharkFunction* function, llvm::Value* method) 354 : SharkCacher(function), _method(method) {} 355 356 private: 357 llvm::Value* _method; 358 359 private: 360 llvm::Value* method() const { 361 return _method; 362 } 363 364 // Method slot callback 365 protected: 366 void process_method_slot(llvm::Value** value, int offset); 367 368 // Stack slot helper 369 protected: 370 bool stack_slot_needs_read(int index, SharkValue* value) { 371 ShouldNotReachHere(); // entry block shouldn't have stack 372 } 373 374 // Local slot helper 375 protected: 376 bool local_slot_needs_read(int index, SharkValue* value) { 377 return value != NULL; 378 } 379 }; 380 381 class SharkNormalEntryCacher : public SharkFunctionEntryCacher { 382 public: 383 SharkNormalEntryCacher(SharkFunction* function, llvm::Value* method) 384 : SharkFunctionEntryCacher(function, method) {} 385 }; 386 387 class SharkOSREntryCacher : public SharkFunctionEntryCacher { 388 public: 389 SharkOSREntryCacher(SharkFunction* function, 390 llvm::Value* method, 391 llvm::Value* osr_buf) 392 : SharkFunctionEntryCacher(function, method), 393 _osr_buf( 394 builder()->CreateBitCast( 395 osr_buf, 396 llvm::PointerType::getUnqual( 397 llvm::ArrayType::get( 398 SharkType::intptr_type(), 399 max_locals() + max_monitors() * 2)))) {} 400 401 private: 402 llvm::Value* _osr_buf; 403 404 private: 405 llvm::Value* osr_buf() const { 406 return _osr_buf; 407 } 408 409 // Callbacks 410 protected: 411 void process_monitor(int index, int box_offset, int obj_offset); 412 void process_local_slot(int index, SharkValue** value, int offset); 413 414 // Helper 415 private: 416 llvm::Value* CreateAddressOfOSRBufEntry(int offset, const llvm::Type* type); 417 };