1 /* 2 * Copyright (c) 1999, 2010, 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 #ifndef SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP 27 #define SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP 28 29 #include "ci/ciMethod.hpp" 30 #include "code/debugInfoRec.hpp" 31 #include "shark/sharkBuilder.hpp" 32 #include "shark/sharkFunction.hpp" 33 #include "shark/sharkStateScanner.hpp" 34 35 // Class hierarchy: 36 // - SharkStateScanner 37 // - SharkCacherDecacher 38 // - SharkDecacher 39 // - SharkJavaCallDecacher 40 // - SharkVMCallDecacher 41 // - SharkTrapDecacher 42 // - SharkCacher 43 // - SharkJavaCallCacher 44 // - SharkVMCallCacher 45 // - SharkFunctionEntryCacher 46 // - SharkNormalEntryCacher 47 // - SharkOSREntryCacher 48 49 class SharkCacherDecacher : public SharkStateScanner { 50 protected: 51 SharkCacherDecacher(SharkFunction* function) 52 : SharkStateScanner(function) {} 53 54 // Helper 55 protected: 56 static int adjusted_offset(SharkValue* value, int offset) { 57 if (value->is_two_word()) 58 offset--; 59 return offset; 60 } 61 }; 62 63 class SharkDecacher : public SharkCacherDecacher { 64 protected: 65 SharkDecacher(SharkFunction* function, int bci) 66 : SharkCacherDecacher(function), _bci(bci) {} 67 68 private: 69 int _bci; 70 71 protected: 72 int bci() const { 73 return _bci; 74 } 75 76 private: 77 int _pc_offset; 78 OopMap* _oopmap; 79 GrowableArray<ScopeValue*>* _exparray; 80 GrowableArray<MonitorValue*>* _monarray; 81 GrowableArray<ScopeValue*>* _locarray; 82 83 private: 84 int pc_offset() const { 85 return _pc_offset; 86 } 87 OopMap* oopmap() const { 88 return _oopmap; 89 } 90 GrowableArray<ScopeValue*>* exparray() const { 91 return _exparray; 92 } 93 GrowableArray<MonitorValue*>* monarray() const { 94 return _monarray; 95 } 96 GrowableArray<ScopeValue*>* locarray() const { 97 return _locarray; 98 } 99 100 // Callbacks 101 protected: 102 void start_frame(); 103 104 void start_stack(int stack_depth); 105 void process_stack_slot(int index, SharkValue** value, int offset); 106 107 void start_monitors(int num_monitors); 108 void process_monitor(int index, int box_offset, int obj_offset); 109 110 void process_oop_tmp_slot(llvm::Value** value, int offset); 111 void process_method_slot(llvm::Value** value, int offset); 112 void process_pc_slot(int offset); 113 114 void start_locals(); 115 void process_local_slot(int index, SharkValue** value, int offset); 116 117 void end_frame(); 118 119 // oopmap and debuginfo helpers 120 private: 121 static int oopmap_slot_munge(int offset) { 122 return SharkStack::oopmap_slot_munge(offset); 123 } 124 static VMReg slot2reg(int offset) { 125 return SharkStack::slot2reg(offset); 126 } 127 static Location slot2loc(int offset, Location::Type type) { 128 return Location::new_stk_loc(type, offset * wordSize); 129 } 130 static LocationValue* slot2lv(int offset, Location::Type type) { 131 return new LocationValue(slot2loc(offset, type)); 132 } 133 static Location::Type location_type(SharkValue** addr, bool maybe_two_word) { 134 // low addresses this end 135 // Type 32-bit 64-bit 136 // ---------------------------------------------------- 137 // stack[0] local[3] jobject oop oop 138 // stack[1] local[2] NULL normal lng 139 // stack[2] local[1] jlong normal invalid 140 // stack[3] local[0] jint normal normal 141 // 142 // high addresses this end 143 144 SharkValue *value = *addr; 145 if (value) { 146 if (value->is_jobject()) 147 return Location::oop; 148 #ifdef _LP64 149 if (value->is_two_word()) 150 return Location::invalid; 151 #endif // _LP64 152 return Location::normal; 153 } 154 else { 155 if (maybe_two_word) { 156 value = *(addr - 1); 157 if (value && value->is_two_word()) { 158 #ifdef _LP64 159 if (value->is_jlong()) 160 return Location::lng; 161 if (value->is_jdouble()) 162 return Location::dbl; 163 ShouldNotReachHere(); 164 #else 165 return Location::normal; 166 #endif // _LP64 167 } 168 } 169 return Location::invalid; 170 } 171 } 172 173 // Stack slot helpers 174 protected: 175 virtual bool stack_slot_needs_write(int index, SharkValue* value) = 0; 176 virtual bool stack_slot_needs_oopmap(int index, SharkValue* value) = 0; 177 virtual bool stack_slot_needs_debuginfo(int index, SharkValue* value) = 0; 178 179 static Location::Type stack_location_type(int index, SharkValue** addr) { 180 return location_type(addr, *addr == NULL); 181 } 182 183 // Local slot helpers 184 protected: 185 virtual bool local_slot_needs_write(int index, SharkValue* value) = 0; 186 virtual bool local_slot_needs_oopmap(int index, SharkValue* value) = 0; 187 virtual bool local_slot_needs_debuginfo(int index, SharkValue* value) = 0; 188 189 static Location::Type local_location_type(int index, SharkValue** addr) { 190 return location_type(addr, index > 0); 191 } 192 193 // Writer helper 194 protected: 195 void write_value_to_frame(llvm::Type* type, 196 llvm::Value* value, 197 int offset); 198 }; 199 200 class SharkJavaCallDecacher : public SharkDecacher { 201 public: 202 SharkJavaCallDecacher(SharkFunction* function, int bci, ciMethod* callee) 203 : SharkDecacher(function, bci), _callee(callee) {} 204 205 private: 206 ciMethod* _callee; 207 208 protected: 209 ciMethod* callee() const { 210 return _callee; 211 } 212 213 // Stack slot helpers 214 protected: 215 bool stack_slot_needs_write(int index, SharkValue* value) { 216 return value && (index < callee()->arg_size() || value->is_jobject()); 217 } 218 bool stack_slot_needs_oopmap(int index, SharkValue* value) { 219 return value && value->is_jobject() && index >= callee()->arg_size(); 220 } 221 bool stack_slot_needs_debuginfo(int index, SharkValue* value) { 222 return index >= callee()->arg_size(); 223 } 224 225 // Local slot helpers 226 protected: 227 bool local_slot_needs_write(int index, SharkValue* value) { 228 return value && value->is_jobject(); 229 } 230 bool local_slot_needs_oopmap(int index, SharkValue* value) { 231 return value && value->is_jobject(); 232 } 233 bool local_slot_needs_debuginfo(int index, SharkValue* value) { 234 return true; 235 } 236 }; 237 238 class SharkVMCallDecacher : public SharkDecacher { 239 public: 240 SharkVMCallDecacher(SharkFunction* function, int bci) 241 : SharkDecacher(function, bci) {} 242 243 // Stack slot helpers 244 protected: 245 bool stack_slot_needs_write(int index, SharkValue* value) { 246 return value && value->is_jobject(); 247 } 248 bool stack_slot_needs_oopmap(int index, SharkValue* value) { 249 return value && value->is_jobject(); 250 } 251 bool stack_slot_needs_debuginfo(int index, SharkValue* value) { 252 return true; 253 } 254 255 // Local slot helpers 256 protected: 257 bool local_slot_needs_write(int index, SharkValue* value) { 258 return value && value->is_jobject(); 259 } 260 bool local_slot_needs_oopmap(int index, SharkValue* value) { 261 return value && value->is_jobject(); 262 } 263 bool local_slot_needs_debuginfo(int index, SharkValue* value) { 264 return true; 265 } 266 }; 267 268 class SharkTrapDecacher : public SharkDecacher { 269 public: 270 SharkTrapDecacher(SharkFunction* function, int bci) 271 : SharkDecacher(function, bci) {} 272 273 // Stack slot helpers 274 protected: 275 bool stack_slot_needs_write(int index, SharkValue* value) { 276 return value != NULL; 277 } 278 bool stack_slot_needs_oopmap(int index, SharkValue* value) { 279 return value && value->is_jobject(); 280 } 281 bool stack_slot_needs_debuginfo(int index, SharkValue* value) { 282 return true; 283 } 284 285 // Local slot helpers 286 protected: 287 bool local_slot_needs_write(int index, SharkValue* value) { 288 return value != NULL; 289 } 290 bool local_slot_needs_oopmap(int index, SharkValue* value) { 291 return value && value->is_jobject(); 292 } 293 bool local_slot_needs_debuginfo(int index, SharkValue* value) { 294 return true; 295 } 296 }; 297 298 class SharkCacher : public SharkCacherDecacher { 299 protected: 300 SharkCacher(SharkFunction* function) 301 : SharkCacherDecacher(function) {} 302 303 // Callbacks 304 protected: 305 void process_stack_slot(int index, SharkValue** value, int offset); 306 307 void process_oop_tmp_slot(llvm::Value** value, int offset); 308 virtual void process_method_slot(llvm::Value** value, int offset); 309 310 virtual void process_local_slot(int index, SharkValue** value, int offset); 311 312 // Stack slot helper 313 protected: 314 virtual bool stack_slot_needs_read(int index, SharkValue* value) = 0; 315 316 // Local slot helper 317 protected: 318 virtual bool local_slot_needs_read(int index, SharkValue* value) { 319 return value && value->is_jobject(); 320 } 321 322 // Writer helper 323 protected: 324 llvm::Value* read_value_from_frame(llvm::Type* type, int offset); 325 }; 326 327 class SharkJavaCallCacher : public SharkCacher { 328 public: 329 SharkJavaCallCacher(SharkFunction* function, ciMethod* callee) 330 : SharkCacher(function), _callee(callee) {} 331 332 private: 333 ciMethod* _callee; 334 335 protected: 336 ciMethod* callee() const { 337 return _callee; 338 } 339 340 // Stack slot helper 341 protected: 342 bool stack_slot_needs_read(int index, SharkValue* value) { 343 return value && (index < callee()->return_type()->size() || 344 value->is_jobject()); 345 } 346 }; 347 348 class SharkVMCallCacher : public SharkCacher { 349 public: 350 SharkVMCallCacher(SharkFunction* function) 351 : SharkCacher(function) {} 352 353 // Stack slot helper 354 protected: 355 bool stack_slot_needs_read(int index, SharkValue* value) { 356 return value && value->is_jobject(); 357 } 358 }; 359 360 class SharkFunctionEntryCacher : public SharkCacher { 361 public: 362 SharkFunctionEntryCacher(SharkFunction* function, llvm::Value* method) 363 : SharkCacher(function), _method(method) {} 364 365 private: 366 llvm::Value* _method; 367 368 private: 369 llvm::Value* method() const { 370 return _method; 371 } 372 373 // Method slot callback 374 protected: 375 void process_method_slot(llvm::Value** value, int offset); 376 377 // Stack slot helper 378 protected: 379 bool stack_slot_needs_read(int index, SharkValue* value) { 380 ShouldNotReachHere(); // entry block shouldn't have stack 381 } 382 383 // Local slot helper 384 protected: 385 bool local_slot_needs_read(int index, SharkValue* value) { 386 return value != NULL; 387 } 388 }; 389 390 class SharkNormalEntryCacher : public SharkFunctionEntryCacher { 391 public: 392 SharkNormalEntryCacher(SharkFunction* function, llvm::Value* method) 393 : SharkFunctionEntryCacher(function, method) {} 394 }; 395 396 class SharkOSREntryCacher : public SharkFunctionEntryCacher { 397 public: 398 SharkOSREntryCacher(SharkFunction* function, 399 llvm::Value* method, 400 llvm::Value* osr_buf) 401 : SharkFunctionEntryCacher(function, method), 402 _osr_buf( 403 builder()->CreateBitCast( 404 osr_buf, 405 llvm::PointerType::getUnqual( 406 llvm::ArrayType::get( 407 SharkType::intptr_type(), 408 max_locals() + max_monitors() * 2)))) {} 409 410 private: 411 llvm::Value* _osr_buf; 412 413 private: 414 llvm::Value* osr_buf() const { 415 return _osr_buf; 416 } 417 418 // Callbacks 419 protected: 420 void process_monitor(int index, int box_offset, int obj_offset); 421 void process_local_slot(int index, SharkValue** value, int offset); 422 423 // Helper 424 private: 425 llvm::Value* CreateAddressOfOSRBufEntry(int offset, llvm::Type* type); 426 }; 427 428 #endif // SHARE_VM_SHARK_SHARKCACHEDECACHE_HPP