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