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