1 /* 2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 3 * Copyright 2008, 2009, 2010 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_SHARKSTACK_HPP 27 #define SHARE_VM_SHARK_SHARKSTACK_HPP 28 29 #include "shark/llvmHeaders.hpp" 30 #include "shark/sharkInvariants.hpp" 31 #include "shark/sharkType.hpp" 32 33 class SharkFunction; 34 class SharkNativeWrapper; 35 class SharkStackWithNormalFrame; 36 class SharkStackWithNativeFrame; 37 38 class SharkStack : public SharkCompileInvariants { 39 public: 40 static SharkStack* CreateBuildAndPushFrame( 41 SharkFunction* function, llvm::Value* method); 42 static SharkStack* CreateBuildAndPushFrame( 43 SharkNativeWrapper* wrapper, llvm::Value* method); 44 45 protected: 46 SharkStack(const SharkCompileInvariants* parent) 47 : SharkCompileInvariants(parent) {} 48 49 protected: 50 void initialize(llvm::Value* method); 51 52 protected: 53 void CreateStackOverflowCheck(llvm::Value* sp); 54 55 // Properties of the method being compiled 56 protected: 57 virtual int arg_size() const = 0; 58 virtual int max_locals() const = 0; 59 virtual int max_stack() const = 0; 60 virtual int max_monitors() const = 0; 61 62 // BasicBlock creation 63 protected: 64 virtual llvm::BasicBlock* CreateBlock(const char* name = "") const = 0; 65 66 // Interpreter entry point for bailouts 67 protected: 68 virtual address interpreter_entry_point() const = 0; 69 70 // Interface with the Zero stack 71 private: 72 llvm::Value* zero_stack() const { 73 return builder()->CreateAddressOfStructEntry( 74 thread(), 75 JavaThread::zero_stack_offset(), 76 SharkType::zeroStack_type(), 77 "zero_stack"); 78 } 79 llvm::Value* stack_base() const { 80 return builder()->CreateValueOfStructEntry( 81 zero_stack(), 82 ZeroStack::base_offset(), 83 SharkType::intptr_type(), 84 "stack_base"); 85 } 86 llvm::Value* stack_pointer_addr() const { 87 return builder()->CreateAddressOfStructEntry( 88 zero_stack(), 89 ZeroStack::sp_offset(), 90 llvm::PointerType::getUnqual(SharkType::intptr_type()), 91 "stack_pointer_addr"); 92 } 93 llvm::Value* frame_pointer_addr() const { 94 return builder()->CreateAddressOfStructEntry( 95 thread(), 96 JavaThread::top_zero_frame_offset(), 97 llvm::PointerType::getUnqual(SharkType::intptr_type()), 98 "frame_pointer_addr"); 99 } 100 101 public: 102 llvm::LoadInst* CreateLoadStackPointer(const char *name = "") { 103 return builder()->CreateLoad(stack_pointer_addr(), name); 104 } 105 llvm::StoreInst* CreateStoreStackPointer(llvm::Value* value) { 106 return builder()->CreateStore(value, stack_pointer_addr()); 107 } 108 llvm::LoadInst* CreateLoadFramePointer(const char *name = "") { 109 return builder()->CreateLoad(frame_pointer_addr(), name); 110 } 111 llvm::StoreInst* CreateStoreFramePointer(llvm::Value* value) { 112 return builder()->CreateStore(value, frame_pointer_addr()); 113 } 114 llvm::Value* CreatePopFrame(int result_slots); 115 116 // Interface with the frame anchor 117 private: 118 llvm::Value* last_Java_sp_addr() const { 119 return builder()->CreateAddressOfStructEntry( 120 thread(), 121 JavaThread::last_Java_sp_offset(), 122 llvm::PointerType::getUnqual(SharkType::intptr_type()), 123 "last_Java_sp_addr"); 124 } 125 llvm::Value* last_Java_fp_addr() const { 126 return builder()->CreateAddressOfStructEntry( 127 thread(), 128 JavaThread::last_Java_fp_offset(), 129 llvm::PointerType::getUnqual(SharkType::intptr_type()), 130 "last_Java_fp_addr"); 131 } 132 133 public: 134 void CreateSetLastJavaFrame() { 135 // Note that whenever _last_Java_sp != NULL other anchor fields 136 // must be valid. The profiler apparently depends on this. 137 NOT_PRODUCT(CreateAssertLastJavaSPIsNull()); 138 builder()->CreateStore(CreateLoadFramePointer(), last_Java_fp_addr()); 139 // XXX There's last_Java_pc as well, but I don't think anything uses it 140 // Also XXX: should we fence here? Zero doesn't... 141 builder()->CreateStore(CreateLoadStackPointer(), last_Java_sp_addr()); 142 // Also also XXX: we could probably cache the sp (and the fp we know??) 143 } 144 void CreateResetLastJavaFrame() { 145 builder()->CreateStore(LLVMValue::intptr_constant(0), last_Java_sp_addr()); 146 } 147 148 private: 149 void CreateAssertLastJavaSPIsNull() const PRODUCT_RETURN; 150 151 // Our method's frame 152 private: 153 llvm::Value* _frame; 154 int _extended_frame_size; 155 int _stack_slots_offset; 156 157 public: 158 int extended_frame_size() const { 159 return _extended_frame_size; 160 } 161 int oopmap_frame_size() const { 162 return extended_frame_size() - arg_size(); 163 } 164 165 // Offsets of things in the frame 166 private: 167 int _monitors_slots_offset; 168 int _oop_tmp_slot_offset; 169 int _method_slot_offset; 170 int _pc_slot_offset; 171 int _locals_slots_offset; 172 173 public: 174 int stack_slots_offset() const { 175 return _stack_slots_offset; 176 } 177 int oop_tmp_slot_offset() const { 178 return _oop_tmp_slot_offset; 179 } 180 int method_slot_offset() const { 181 return _method_slot_offset; 182 } 183 int pc_slot_offset() const { 184 return _pc_slot_offset; 185 } 186 int locals_slots_offset() const { 187 return _locals_slots_offset; 188 } 189 int monitor_offset(int index) const { 190 assert(index >= 0 && index < max_monitors(), "invalid monitor index"); 191 return _monitors_slots_offset + 192 (max_monitors() - 1 - index) * frame::interpreter_frame_monitor_size(); 193 } 194 int monitor_object_offset(int index) const { 195 return monitor_offset(index) + 196 (BasicObjectLock::obj_offset_in_bytes() >> LogBytesPerWord); 197 } 198 int monitor_header_offset(int index) const { 199 return monitor_offset(index) + 200 ((BasicObjectLock::lock_offset_in_bytes() + 201 BasicLock::displaced_header_offset_in_bytes()) >> LogBytesPerWord); 202 } 203 204 // Addresses of things in the frame 205 public: 206 llvm::Value* slot_addr(int offset, 207 llvm::Type* type = NULL, 208 const char* name = "") const; 209 210 llvm::Value* monitor_addr(int index) const { 211 return slot_addr( 212 monitor_offset(index), 213 SharkType::monitor_type(), 214 "monitor"); 215 } 216 llvm::Value* monitor_object_addr(int index) const { 217 return slot_addr( 218 monitor_object_offset(index), 219 SharkType::oop_type(), 220 "object_addr"); 221 } 222 llvm::Value* monitor_header_addr(int index) const { 223 return slot_addr( 224 monitor_header_offset(index), 225 SharkType::intptr_type(), 226 "displaced_header_addr"); 227 } 228 229 // oopmap helpers 230 public: 231 static int oopmap_slot_munge(int offset) { 232 return offset << (LogBytesPerWord - LogBytesPerInt); 233 } 234 static VMReg slot2reg(int offset) { 235 return VMRegImpl::stack2reg(oopmap_slot_munge(offset)); 236 } 237 }; 238 239 class SharkStackWithNormalFrame : public SharkStack { 240 friend class SharkStack; 241 242 protected: 243 SharkStackWithNormalFrame(SharkFunction* function, llvm::Value* method); 244 245 private: 246 SharkFunction* _function; 247 248 private: 249 SharkFunction* function() const { 250 return _function; 251 } 252 253 // Properties of the method being compiled 254 private: 255 int arg_size() const; 256 int max_locals() const; 257 int max_stack() const; 258 int max_monitors() const; 259 260 // BasicBlock creation 261 private: 262 llvm::BasicBlock* CreateBlock(const char* name = "") const; 263 264 // Interpreter entry point for bailouts 265 private: 266 address interpreter_entry_point() const; 267 }; 268 269 class SharkStackWithNativeFrame : public SharkStack { 270 friend class SharkStack; 271 272 protected: 273 SharkStackWithNativeFrame(SharkNativeWrapper* wrapper, llvm::Value* method); 274 275 private: 276 SharkNativeWrapper* _wrapper; 277 278 private: 279 SharkNativeWrapper* wrapper() const { 280 return _wrapper; 281 } 282 283 // Properties of the method being compiled 284 private: 285 int arg_size() const; 286 int max_locals() const; 287 int max_stack() const; 288 int max_monitors() const; 289 290 // BasicBlock creation 291 private: 292 llvm::BasicBlock* CreateBlock(const char* name = "") const; 293 294 // Interpreter entry point for bailouts 295 private: 296 address interpreter_entry_point() const; 297 }; 298 299 #endif // SHARE_VM_SHARK_SHARKSTACK_HPP